blob: 426109a1d4c68c32652cc082854a54d5c8a480b9 [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;
Harald Welte801ed1a2023-04-30 15:07:00 +100026friend module BSC_Tests_ASCI;
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +020027
Neels Hofmeyr4f118412020-06-04 15:25:10 +020028import from Misc_Helpers all;
Harald Welte4003d112017-12-09 22:35:39 +010029import from General_Types all;
Harald Welte28d943e2017-11-25 15:00:50 +010030import from Osmocom_Types all;
Harald Welteae026692017-12-09 01:03:01 +010031import from GSM_Types all;
Harald Welte28d943e2017-11-25 15:00:50 +010032import from IPL4asp_Types all;
33
Harald Welte6f521d82017-12-11 19:52:02 +010034import from BSSAP_Types all;
Harald Welte6811d102019-04-14 22:23:14 +020035import from RAN_Adapter all;
Harald Welte47cd0e32020-08-21 12:39:11 +020036import from BSSAP_LE_Adapter all;
37import from BSSAP_LE_CodecPort all;
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020038import from BSSAP_LE_Types all;
39import from BSSLAP_Types all;
Harald Welteae026692017-12-09 01:03:01 +010040import from BSSAP_CodecPort all;
41import from BSSMAP_Templates all;
Harald Welte28d943e2017-11-25 15:00:50 +010042import from IPA_Emulation all;
Stefan Sperling830dc9d2018-02-12 21:08:28 +010043import from IPA_CodecPort all;
Harald Welteae026692017-12-09 01:03:01 +010044import from IPA_Types all;
Stefan Sperling0796a822018-10-05 13:01:39 +020045import from IPA_Testing all;
Harald Welteae026692017-12-09 01:03:01 +010046import from RSL_Types all;
Harald Welte624f9632017-12-16 19:26:04 +010047import from RSL_Emulation all;
Daniel Willmann191e0d92018-01-17 12:44:35 +010048import from MGCP_Emulation all;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010049import from MGCP_Templates all;
50import from MGCP_Types all;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +020051import from MGCP_CodecPort all;
Harald Welte28d943e2017-11-25 15:00:50 +010052
Harald Welte96c94412017-12-09 03:12:45 +010053import from Osmocom_CTRL_Functions all;
Harald Weltea5d2ab22017-12-09 14:21:42 +010054import from Osmocom_CTRL_Types all;
Harald Welteffe55fc2018-01-17 22:39:54 +010055import from Osmocom_CTRL_Adapter all;
Harald Welte96c94412017-12-09 03:12:45 +010056
Daniel Willmannebdecc02020-08-12 15:30:17 +020057import from StatsD_Types all;
58import from StatsD_CodecPort all;
59import from StatsD_CodecPort_CtrlFunct all;
60import from StatsD_Checker all;
61
Harald Weltebc03c762018-02-12 18:09:38 +010062import from Osmocom_VTY_Functions all;
63import from TELNETasp_PortType all;
64
Harald Welte6f521d82017-12-11 19:52:02 +010065import from MobileL3_CommonIE_Types all;
Harald Weltee3bd6582018-01-31 22:51:25 +010066import from MobileL3_Types all;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010067import from MobileL3_RRM_Types all;
Harald Welte6f521d82017-12-11 19:52:02 +010068import from L3_Templates all;
69import from GSM_RR_Types all;
70
Stefan Sperlingc307e682018-06-14 15:15:46 +020071import from SCCP_Templates all;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010072import from BSSMAP_Templates all;
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020073import from BSSMAP_LE_Templates all;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010074
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010075import from SCCPasp_Types all;
76
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020077import from GSM_SystemInformation all;
78import from GSM_RestOctets all;
Neels Hofmeyrad132f22020-07-08 02:20:16 +020079import from TCCConversion_Functions all;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020080
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060081const integer NUM_TRX := 4;
Harald Welte5d1a2202017-12-13 19:51:29 +010082const integer NUM_BTS := 3;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020083const 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 +060084const 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 +020085const integer NUM_MSC := 3;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020086const integer NUM_MGW := 2;
Harald Welteae026692017-12-09 01:03:01 +010087const float T3101_MAX := 12.0;
Harald Welte28d943e2017-11-25 15:00:50 +010088
Harald Welte799c97b2017-12-14 17:50:30 +010089/* make sure to sync this with the osmo-bts.cfg you're using */
Philipp Maiercb6cc482018-03-26 13:08:00 +020090const integer NUM_TCHH_PER_BTS := 2;
91const integer NUM_TCHF_PER_BTS := 4;
Neels Hofmeyr74083c22020-07-29 00:43:01 +020092const integer NUM_SDCCH_PER_BTS := 3;
Harald Welte799c97b2017-12-14 17:50:30 +010093
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060094friend type record BtsTrxIdx {
95 uint8_t bts,
96 uint8_t trx
97}
98
99private type record BtsParams {
100 integer trx_num,
101 integer tsc
102}
103
Neels Hofmeyrbf720202021-10-02 12:58:24 +0200104/* Default Training Sequence Code expected for bts[i]:
105 * BTS 0 has BSIC 10 (and no explicit timeslot training_sequence_code config), so expecting TSC = (BSIC & 7) = 2.
106 * BTS 1 has BSIC 11, TSC = (BSIC & 7) = 3.
107 * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
108 * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
109 */
Harald Welte801ed1a2023-04-30 15:07:00 +1000110friend const BtsParams c_BtsParams[NUM_BTS_CFG] := {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600111 /* BTS0 */ { trx_num := 1, tsc := 2 },
112 /* BTS1 */ { trx_num := 1, tsc := 3 },
Vadim Yanitskiy7a3d2932022-05-29 20:37:46 +0600113 /* BTS2 */ { trx_num := 4, tsc := 4 },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600114 /* BTS3 */ { trx_num := 1, tsc := 4 }
Neels Hofmeyrbf720202021-10-02 12:58:24 +0200115}
Harald Welte4003d112017-12-09 22:35:39 +0100116
Vadim Yanitskiy59494702022-09-14 15:29:04 +0700117private const RSL_IE_Body c_mr_conf_5_90 :=
Pau Espin Pedrolf7634dc2022-09-02 17:56:00 +0200118 valueof(RSL_IE_Body:{multirate_cfg := ts_RSL_MultirateCfg(true, 0, '00000100'B /* 5,90k */)});
119
Harald Welte21b46bd2017-12-17 19:46:32 +0100120/* per-BTS state which we keep */
Harald Welte96c94412017-12-09 03:12:45 +0100121type record BTS_State {
Harald Welte21b46bd2017-12-17 19:46:32 +0100122 /* component reference to the IPA_Client component used for RSL */
Harald Weltea5d2ab22017-12-09 14:21:42 +0100123 IPA_Client rsl
Harald Welte96c94412017-12-09 03:12:45 +0100124}
125
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200126/* Default list of counters for an 'msc' entity. */
127const CounterNameVals counternames_msc_mscpool := {
128 { "mscpool:subscr:new", 0 },
129 { "mscpool:subscr:known", 0 },
130 { "mscpool:subscr:reattach", 0 },
131 { "mscpool:subscr:attach_lost", 0 },
132 { "mscpool:subscr:paged", 0 }
133};
134
Neels Hofmeyrbf037052020-10-28 22:52:02 +0000135/* List of global mscpool counters, not related to a specific 'msc' entity. */
136const CounterNameVals counternames_bsc_mscpool := {
137 { "mscpool:subscr:no_msc", 0 }
138};
139
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000140/* Default list of counters for 'bsc' and 'bts' entities. */
141const CounterNameVals counternames_bsc_bts_handover := {
142 { "assignment:attempted", 0 },
143 { "assignment:completed", 0 },
144 { "assignment:stopped", 0 },
145 { "assignment:no_channel", 0 },
146 { "assignment:timeout", 0 },
147 { "assignment:failed", 0 },
148 { "assignment:error", 0 },
149
150 { "handover:attempted", 0 },
151 { "handover:completed", 0 },
152 { "handover:stopped", 0 },
153 { "handover:no_channel", 0 },
154 { "handover:timeout", 0 },
155 { "handover:failed", 0 },
156 { "handover:error", 0 },
157
158 { "intra_cell_ho:attempted", 0 },
159 { "intra_cell_ho:completed", 0 },
160 { "intra_cell_ho:stopped", 0 },
161 { "intra_cell_ho:no_channel", 0 },
162 { "intra_cell_ho:timeout", 0 },
163 { "intra_cell_ho:failed", 0 },
164 { "intra_cell_ho:error", 0 },
165
166 { "intra_bsc_ho:attempted", 0 },
167 { "intra_bsc_ho:completed", 0 },
168 { "intra_bsc_ho:stopped", 0 },
169 { "intra_bsc_ho:no_channel", 0 },
170 { "intra_bsc_ho:timeout", 0 },
171 { "intra_bsc_ho:failed", 0 },
172 { "intra_bsc_ho:error", 0 },
173
174 { "interbsc_ho_out:attempted", 0 },
175 { "interbsc_ho_out:completed", 0 },
176 { "interbsc_ho_out:stopped", 0 },
177 { "interbsc_ho_out:timeout", 0 },
178 { "interbsc_ho_out:failed", 0 },
179 { "interbsc_ho_out:error", 0 },
180
181 { "interbsc_ho_in:attempted", 0 },
182 { "interbsc_ho_in:completed", 0 },
183 { "interbsc_ho_in:stopped", 0 },
184 { "interbsc_ho_in:no_channel", 0 },
185 { "interbsc_ho_in:timeout", 0 },
186 { "interbsc_ho_in:failed", 0 },
187 { "interbsc_ho_in:error", 0 }
188};
189
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100190const CounterNameVals counternames_bts_handover := {
191 { "incoming_intra_bsc_ho:attempted", 0 },
192 { "incoming_intra_bsc_ho:completed", 0 },
193 { "incoming_intra_bsc_ho:stopped", 0 },
194 { "incoming_intra_bsc_ho:no_channel", 0 },
195 { "incoming_intra_bsc_ho:timeout", 0 },
196 { "incoming_intra_bsc_ho:failed", 0 },
197 { "incoming_intra_bsc_ho:error", 0 }
198};
199
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200200/* Set of all System Information received during one RSL port's startup.
201 * Note that some System Information may be sent on RSL, but lacking actual SI data, to indicate that the BTS should not
202 * broadcast that SI type. That will be reflected as 'omit' here.
203 */
204type record SystemInformationConfig {
205 SystemInformationType1 si1 optional,
206 SystemInformationType2 si2 optional,
207 SystemInformationType2bis si2bis optional,
208 SystemInformationType2ter si2ter optional,
Neels Hofmeyrad132f22020-07-08 02:20:16 +0200209 SI2quaterRestOctetsList si2quater optional,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200210 SystemInformationType3 si3 optional,
211 SystemInformationType4 si4 optional,
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100212 SystemInformationType13 si13 optional,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200213 SystemInformationType5 si5 optional,
214 SystemInformationType5bis si5bis optional,
215 SystemInformationType5ter si5ter optional,
216 SystemInformationType6 si6 optional
217};
218
219const SystemInformationConfig SystemInformationConfig_omit := {
220 si1 := omit,
221 si2 := omit,
222 si2bis := omit,
223 si2ter := omit,
224 si2quater := omit,
225 si3 := omit,
226 si4 := omit,
227 si13 := omit,
228 si5 := omit,
229 si5bis := omit,
230 si5ter := omit,
231 si6 := omit
232};
233
234/* tr_EUTRAN_CellDesc with defaults used in BSC_Tests.ttcn */
235template EUTRAN_CellDesc tr_EUTRAN_CellDesc_default(template (present) uint16_t e_arfcn := ?,
236 template uint3_t meas_bw := 3)
237:= tr_EUTRAN_CellDesc(e_arfcn := e_arfcn,
238 meas_bw_presence := '1'B,
239 meas_bw := meas_bw);
240
241/* tr_EUTRAN_NeighbourCells with defaults used in BSC_Tests.ttcn */
Harald Welte65e419a2020-08-21 12:38:33 +0200242template EUTRAN_NeighbourCells tr_EUTRAN_NeighbourCells_default(template (present) EUTRAN_CellDescs cell_desc_list := { tr_EUTRAN_CellDesc_default },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200243 template uint3_t prio := 3,
244 template (present) uint5_t thresh_high := 20,
245 template uint5_t thresh_low := 10,
246 template uint5_t qrxlevmin := 22)
247:= tr_EUTRAN_NeighbourCells(
248 cell_desc_list := cell_desc_list,
249 prio_presence := '1'B,
250 prio := prio,
251 thresh_high := thresh_high,
252 thresh_low_presence := '1'B,
253 thresh_low := thresh_low,
254 qrxlevmin_presence := '1'B,
255 qrxlevmin := qrxlevmin);
256
257template SystemInformationConfig SystemInformationConfig_default := {
258 si1 := {
259 cell_chan_desc := '8FB38000000000000000000000000000'O,
260 rach_control := {
261 max_retrans := RACH_MAX_RETRANS_7,
262 tx_integer := '1001'B,
263 cell_barr_access := false,
264 re_not_allowed := true,
265 acc := '0000010000000000'B
266 },
267 rest_octets := ?
268 },
269 si2 := {
270 bcch_freq_list := '00000000000000000000000000000000'O,
271 ncc_permitted := '11111111'B,
272 rach_control := {
273 max_retrans := RACH_MAX_RETRANS_7,
274 tx_integer := '1001'B,
275 cell_barr_access := false,
276 re_not_allowed := true,
277 acc := '0000010000000000'B
278 }
279 },
280 si2bis := omit,
281 si2ter := {
282 extd_bcch_freq_list := '8E320000000000000000000000000800'O,
283 rest_octets := ?
284 },
285 si2quater := {
286 tr_SI2quaterRestOctets_EUTRAN( repeated_neigh_cells := { tr_EUTRAN_NeighbourCells_default } )
287 },
288 si3 := {
289 cell_id := 0,
290 lai := {
291 mcc_mnc := '001F01'H,
292 lac := 1
293 },
294 ctrl_chan_desc := {
295 msc_r99 := true,
296 att := true,
297 bs_ag_blks_res := 1,
298 ccch_conf := CCHAN_DESC_1CCCH_COMBINED,
299 si22ind := false,
300 cbq3 := CBQ3_IU_MODE_NOT_SUPPORTED,
301 spare := '00'B,
302 bs_pa_mfrms := 3,
303 t3212 := 30
304 },
305 cell_options := {
306 dn_ind := false,
307 pwrc := false,
308 dtx := MS_SHALL_USE_UL_DTX,
309 radio_link_tout_div4 := 7
310 },
311 cell_sel_par := {
312 cell_resel_hyst_2dB := 2,
313 ms_txpwr_max_cch := 7,
314 acs := '0'B,
315 neci := true,
316 rxlev_access_min := 0
317 },
318 rach_control := {
319 max_retrans := RACH_MAX_RETRANS_7,
320 tx_integer := '1001'B,
321 cell_barr_access := false,
322 re_not_allowed := true,
323 acc := '0000010000000000'B
324 },
325 rest_octets := {
326 sel_params := {
327 presence := '0'B,
328 params := omit
329 },
330 pwr_offset := {
331 presence := '0'B,
332 offset := omit
333 },
334 si_2ter_ind := '1'B,
335 early_cm_ind := '0'B,
336 sched_where := {
337 presence := '0'B,
338 where := omit
339 },
340 gprs_ind := {
341 presence := '1'B,
342 ind := {
343 ra_colour := 0,
344 si13_pos := '0'B
345 }
346 },
347 umts_early_cm_ind := '1'B,
348 si2_quater_ind := {
349 presence := '1'B,
350 ind := '0'B
351 },
352 iu_mode_ind := omit,
353 si21_ind := {
354 presence := '0'B,
355 pos := omit
356 }
357 }
358 },
359 si4 := {
360 lai := {
361 mcc_mnc := '001F01'H,
362 lac := 1
363 },
364 cell_sel_par := {
365 cell_resel_hyst_2dB := 2,
366 ms_txpwr_max_cch := 7,
367 acs := '0'B,
368 neci := true,
369 rxlev_access_min := 0
370 },
371 rach_control := {
372 max_retrans := RACH_MAX_RETRANS_7,
373 tx_integer := '1001'B,
374 cell_barr_access := false,
375 re_not_allowed := true,
376 acc := '0000010000000000'B
377 },
Neels Hofmeyr74083c22020-07-29 00:43:01 +0200378 cbch_chan_desc := {
379 iei := '64'O,
380 v := {
381 chan_nr := {
382 u := {
383 sdcch4 := {
384 tag := '001'B,
385 sub_chan := 2
386 }
387 },
388 tn := 0
389 },
390 tsc := 2,
391 h := false,
392 arfcn := 871,
393 maio_hsn := omit
394 }
395 },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200396 cbch_mobile_alloc := omit,
397 rest_octets := {
398 sel_params := {
399 presence := '0'B,
400 params := omit
401 },
402 pwr_offset := {
403 presence := '0'B,
404 offset := omit
405 },
406 gprs_ind := {
407 presence := '1'B,
408 ind := {
409 ra_colour := 0,
410 si13_pos := '0'B
411 }
412 },
413 s_presence := '0'B,
414 s := omit
415 }
416 },
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100417 si13 := {
418 rest_octets := {
419 presence := '1'B,
420 bcch_change_mark := ?,
421 si_change_field := '0000'B,
422 presence2 := '0'B,
423 si13_change_mark := omit,
424 gprs_ma := omit,
425 zero := '0'B, /* PBCCH not present in cell */
426 rac := 0,
427 spgc_ccch_sup := '0'B,
428 priority_access_thr := '110'B,
429 network_control_order := '00'B,
430 gprs_cell_opts := {
431 nmo := '01'B,
432 t3168 := '011'B,
433 t3192 := '010'B,
434 drx_timer_max := '011'B,
435 access_burst_type := '0'B,
436 control_ack_type := '1'B,
437 bs_cv_max := 15,
438 pan_presence := '1'B,
439 pan_dec := 1,
440 pan_inc := 1,
441 pan_max := '111'B,
442 ext_info_presence := ?,
443 ext_info_length := *,
444 ext_info := *
445 },
446 gprs_pwr_ctrl_params := {
447 alpha := 0,
448 t_avg_w := '10000'B,
449 t_avg_t := '10000'B,
450 pc_meas_chan := '0'B,
451 n_avg_i := '1000'B
452 }
453 }
454 },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200455 si5 := {
456 bcch_freq_list := '10000000000000000000000000000000'O
457 },
458 si5bis := omit,
459 si5ter := {
460 extd_bcch_freq_list := '9E050020000000000000000000000000'O
461 },
462 si6 := {
463 cell_id := 0,
464 lai := {
465 mcc_mnc := '001F01'H,
466 lac := 1
467 },
468 cell_options := {
469 dtx_ext := '1'B,
470 pwrc := false,
471 dtx := '01'B,
472 radio_link_timeout := '0111'B
473 },
474 ncc_permitted := '11111111'B,
Vadim Yanitskiy348b07c2022-03-10 17:11:22 +0300475 rest_octets := {
476 pch_nch_info := ?,
477 vbs_vgcs_options := ?,
478 dtm_support := '0'B,
479 rac := omit,
480 max_lapdm := omit,
481 band_ind := '0'B /* C0 ARFCN indicates 1800 band */
482 }
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200483 }
484 };
485
486
487/* List of all the System Information received on all RSL ports */
488type record of SystemInformationConfig SystemInformationConfig_list;
489
490function f_sysinfo_dec_raw(inout SystemInformationConfig si, RSL_Message rsl)
491{
492 var RSL_IE_Body sysinfo_type_ie;
493 var RSL_IE_SysinfoType si_type;
494 var octetstring data;
495
496 if (f_rsl_find_ie(rsl, RSL_IE_SYSINFO_TYPE, sysinfo_type_ie) == false) {
497 setverdict(fail, "Cannot find RSL_IE_SYSINFO_TYPE");
498 mtc.stop;
499 }
500 si_type := sysinfo_type_ie.sysinfo_type;
501
502 if (rsl.msg_type == RSL_MT_BCCH_INFO) {
503 var RSL_IE_Body bcch_ie;
504 if (f_rsl_find_ie(rsl, RSL_IE_FULL_BCCH_INFO, bcch_ie)) {
505 data := bcch_ie.other.payload;
506 }
507 } else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
508 var RSL_IE_Body l3_ie;
509 if (f_rsl_find_ie(rsl, RSL_IE_L3_INFO, l3_ie)) {
510 data := l3_ie.l3_info.payload;
511 }
512 } else {
513 setverdict(fail, "Don't understand this System Information message");
514 mtc.stop;
515 }
516
517 var boolean handled := false;
518
519 if (rsl.msg_type == RSL_MT_BCCH_INFO) {
520 handled := true;
521
522 if (si_type == RSL_SYSTEM_INFO_1) {
523 if (not isbound(data)) {
524 si.si1 := omit;
525 } else {
526 si.si1 := dec_SystemInformation(data).payload.si1;
527 }
528 } else if (si_type == RSL_SYSTEM_INFO_2) {
529 if (not isbound(data)) {
530 si.si2 := omit;
531 } else {
532 si.si2 := dec_SystemInformation(data).payload.si2;
533 }
534 } else if (si_type == RSL_SYSTEM_INFO_2bis) {
535 if (not isbound(data)) {
536 si.si2bis := omit;
537 } else {
538 si.si2bis := dec_SystemInformation(data).payload.si2bis;
539 }
540 } else if (si_type == RSL_SYSTEM_INFO_2ter) {
541 if (not isbound(data)) {
542 si.si2ter := omit;
543 } else {
544 si.si2ter := dec_SystemInformation(data).payload.si2ter;
545 }
546 } else if (si_type == RSL_SYSTEM_INFO_2quater) {
547 if (not isbound(data)) {
548 si.si2quater := {};
549 } else {
550 var SystemInformationType2quater decoded := dec_SystemInformation(data).payload.si2quater;
551 /* this is a *record* of SI2quaterRestOctets! (multiplexed) */
552 si.si2quater[decoded.rest_octets.si2quater_index] := decoded.rest_octets;
553 }
554 } else if (si_type == RSL_SYSTEM_INFO_3) {
555 if (not isbound(data)) {
556 si.si3 := omit;
557 } else {
558 si.si3 := dec_SystemInformation(data).payload.si3;
559 }
560 } else if (si_type == RSL_SYSTEM_INFO_4) {
561 if (not isbound(data)) {
562 si.si4 := omit;
563 } else {
564 si.si4 := dec_SystemInformation(data).payload.si4;
565 }
566 } else if (si_type == RSL_SYSTEM_INFO_13) {
567 if (not isbound(data)) {
568 si.si13 := omit;
569 } else {
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100570 si.si13 := dec_SystemInformation(data).payload.si13;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200571 }
572 } else {
573 handled := false;
574 }
575 } else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
576 handled := true;
577
578 if (si_type == RSL_SYSTEM_INFO_5) {
579 if (not isbound(data)) {
580 si.si5 := omit;
581 } else {
582 si.si5 := dec_SystemInformation(data).payload.si5;
583 }
584 } else if (si_type == RSL_SYSTEM_INFO_5bis) {
585 if (not isbound(data)) {
586 si.si5bis := omit;
587 } else {
588 si.si5bis := dec_SystemInformation(data).payload.si5bis;
589 }
590 } else if (si_type == RSL_SYSTEM_INFO_5ter) {
591 if (not isbound(data)) {
592 si.si5ter := omit;
593 } else {
594 si.si5ter := dec_SystemInformation(data).payload.si5ter;
595 }
596 } else if (si_type == RSL_SYSTEM_INFO_6) {
597 if (not isbound(data)) {
598 si.si6 := omit;
599 } else {
600 si.si6 := dec_SystemInformation(data).payload.si6;
601 }
602 } else {
603 handled := false;
604 }
605 }
606
607 if (not handled) {
608 setverdict(fail, "Unexpected SI type in ", rsl.msg_type, " message: ", si_type);
609 }
610}
611
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +0100612friend function gen_l3_valid_payload(hexstring imsi := ''H) return octetstring {
613 var octetstring l3_payload;
614 if (lengthof(imsi) == 0) {
615 imsi := f_rnd_imsi('00101'H);
616 }
617 l3_payload := enc_PDU_ML3_MS_NW(valueof(ts_LU_REQ(LU_Type_IMSI_Attach, ts_MI_LV(ts_MI_IMSI(imsi)))));
618 return l3_payload;
619}
620
Harald Weltea4ca4462018-02-09 00:17:14 +0100621type component test_CT extends CTRL_Adapter_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600622 /* Array of per-BTS/TRX state */
623 var BTS_State bts[NUM_BTS][NUM_TRX];
Harald Welte89ab1912018-02-23 18:56:29 +0100624 /* RSL common Channel Port (for RSL_Emulation) */
625 port RSL_CCHAN_PT RSL_CCHAN[NUM_BTS];
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600626 /* array of per-BTS/TRX RSL test ports */
627 port IPA_RSL_PT IPA_RSL[NUM_BTS][NUM_TRX];
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100628 port IPA_CODEC_PT IPA; /* Required for compilation of TC_rsl_unknown_unit_id() */
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +0200629 /* CTRL muxed over IPA in SCCPlite conn BSC<->MSC (or BSC-NAT) */
630 port IPA_CTRL_PT SCCPLITE_IPA_CTRL;
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200631 /* Configure/manage IPA_Emulation per-BTS/TRX port: */
632 port IPA_CFG_PT IPA_CFG_PORT[NUM_BTS][NUM_TRX];
Harald Weltea5d2ab22017-12-09 14:21:42 +0100633
Pau Espin Pedrol3c630532022-10-20 19:00:11 +0200634 var MGCP_Emulation_CT vc_MGCP[NUM_MGW];
635 var integer g_nr_mgw; /* number of vc_MGCP to initialize */
Harald Weltebc03c762018-02-12 18:09:38 +0100636 port TELNETasp_PT BSCVTY;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100637
Daniel Willmannebdecc02020-08-12 15:30:17 +0200638 /* StatsD */
639 var StatsD_Checker_CT vc_STATSD;
640
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200641 var RAN_Adapter g_bssap[NUM_MSC];
Harald Welte47cd0e32020-08-21 12:39:11 +0200642 var BSSAP_LE_Adapter g_bssap_le;
Harald Weltea4ca4462018-02-09 00:17:14 +0100643 /* for old legacy-tests only */
644 port BSSAP_CODEC_PT BSSAP;
Harald Welte47cd0e32020-08-21 12:39:11 +0200645 port BSSAP_LE_CODEC_PT BSSAP_LE;
Harald Weltea4ca4462018-02-09 00:17:14 +0100646
Harald Welte21b46bd2017-12-17 19:46:32 +0100647 /* are we initialized yet */
Harald Welte28d943e2017-11-25 15:00:50 +0100648 var boolean g_initialized := false;
Harald Welte21b46bd2017-12-17 19:46:32 +0100649
Neels Hofmeyr38632aa2023-04-05 03:50:51 +0200650 var boolean g_handler_mode := false;
651
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200652 /* Osmux is enabled through VTY */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200653 var boolean g_osmux_enabled_cn := false;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +0200654 var boolean g_osmux_enabled_bts := false;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200655
Pau Espin Pedrolc675b612020-01-09 19:55:40 +0100656 /*Configure T(tias) over VTY, seconds */
657 var integer g_bsc_sccp_timer_ias := 7 * 60;
658 /*Configure T(tiar) over VTY, seconds */
659 var integer g_bsc_sccp_timer_iar := 15 * 60;
660
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +0200661 /* global test case guard timer (actual timeout value is set in f_init()) */
Harald Welteae026692017-12-09 01:03:01 +0100662 timer T_guard := 30.0;
663
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200664 var CounterNameValsList g_ctr_msc;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000665 var CounterNameValsList g_ctr_bsc;
666 var CounterNameValsList g_ctr_bts;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200667
668 /* System Information bytes as received during RSL startup, for each RSL[idx]. */
669 var SystemInformationConfig_list g_system_information := {};
Harald Welte28d943e2017-11-25 15:00:50 +0100670}
671
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200672type record of charstring phys_chan_configs;
Harald Welte28d943e2017-11-25 15:00:50 +0100673modulepar {
Harald Welte21b46bd2017-12-17 19:46:32 +0100674 /* IP address at which the BSC can be reached */
Harald Welte696ddb62017-12-08 14:01:43 +0100675 charstring mp_bsc_ip := "127.0.0.1";
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100676 /* port number to which to establish the IPA OML connections */
677 integer mp_bsc_oml_port := 3002;
Harald Welte21b46bd2017-12-17 19:46:32 +0100678 /* port number to which to establish the IPA RSL connections */
Harald Welte696ddb62017-12-08 14:01:43 +0100679 integer mp_bsc_rsl_port := 3003;
Harald Welte21b46bd2017-12-17 19:46:32 +0100680 /* port number to which to establish the IPA CTRL connection */
Harald Welte96c94412017-12-09 03:12:45 +0100681 integer mp_bsc_ctrl_port := 4249;
Daniel Willmannebdecc02020-08-12 15:30:17 +0200682 /* port number to which to listen for STATSD metrics */
683 integer mp_bsc_statsd_port := 8125;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100684 /* IP address at which the test binds */
685 charstring mp_test_ip := "127.0.0.1";
Harald Weltea4ca4462018-02-09 00:17:14 +0100686
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200687 RAN_Configurations mp_bssap_cfg := {
688 {
689 transport := BSSAP_TRANSPORT_AoIP,
690 sccp_service_type := "mtp3_itu",
691 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
692 own_pc := 185, /* 0.23.1 first MSC emulation */
693 own_ssn := 254,
694 peer_pc := 187, /* 0.23.3 osmo-bsc */
695 peer_ssn := 254,
696 sio := '83'O,
Harald Weltecb0cc432020-06-21 19:42:31 +0200697 rctx := 1
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200698 },
699 {
700 transport := BSSAP_TRANSPORT_AoIP,
701 sccp_service_type := "mtp3_itu",
702 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
703 own_pc := 2, /* 0.0.2 second MSC emulation */
704 own_ssn := 254,
705 peer_pc := 187, /* 0.23.3 osmo-bsc */
706 peer_ssn := 254,
707 sio := '83'O,
708 rctx := 2
709 },
710 {
711 transport := BSSAP_TRANSPORT_AoIP,
712 sccp_service_type := "mtp3_itu",
713 sctp_addr := { 23907, "127.0.0.1", 2905, "127.0.0.1" },
714 own_pc := 3, /* 0.0.3 third MSC emulation */
715 own_ssn := 254,
716 peer_pc := 187, /* 0.23.3 osmo-bsc */
717 peer_ssn := 254,
718 sio := '83'O,
719 rctx := 3
720 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100721 };
Pau Espin Pedrol58cf6822019-05-28 18:11:33 +0200722
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200723 /* Must match per BTS config in osmo-bsc.cfg */
724 phys_chan_configs phys_chan_config := {
725 "CCCH+SDCCH4+CBCH",
726 "TCH/F",
727 "TCH/F",
728 "TCH/F",
729 "TCH/F",
Vadim Yanitskiy343c9eb2021-07-16 18:36:01 +0600730 "TCH/H",
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200731 "PDCH",
732 "PDCH"
733 };
734
Harald Welte47cd0e32020-08-21 12:39:11 +0200735 BSSAP_LE_Configuration mp_bssap_le_cfg := {
736 sccp_service_type := "mtp3_itu",
737 sctp_addr := { 23908, "127.0.0.1", 2905, "127.0.0.1" },
Neels Hofmeyrac086c12020-09-18 23:46:42 +0200738 own_pc := 190, /* 0.23.6 SMLC emulation */
Harald Welte47cd0e32020-08-21 12:39:11 +0200739 own_ssn := 252, /* SMLC side SSN */
740 peer_pc := 187, /* 0.23.3 osmo-bsc */
741 peer_ssn := 250, /* BSC side SSN */
742 sio := '83'O,
743 rctx := 6
744 };
Neels Hofmeyrcfe44062020-10-15 02:28:08 +0200745 boolean mp_enable_lcs_tests := true;
Harald Welte47cd0e32020-08-21 12:39:11 +0200746
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100747 /* Value set in osmo-bsc.cfg "ms max power" */
748 uint8_t mp_exp_ms_power_level := 7;
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600749
750 /* Whether to check for memory leaks */
751 boolean mp_verify_talloc_count := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100752}
753
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200754friend function f_gen_test_hdlr_pars(integer bssap_idx := 0) return TestHdlrParams {
Philipp Maier48604732018-10-09 15:00:37 +0200755
756 var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200757 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier48604732018-10-09 15:00:37 +0200758 pars.aoip := true;
759 } else {
760 pars.aoip := false;
761 }
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100762 pars.exp_ms_power_level := mp_exp_ms_power_level;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200763 pars.mscpool.bssap_idx := bssap_idx;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600764 pars.expect_tsc := c_BtsParams[0].tsc;
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300765 pars.imsi := f_rnd_imsi('00101'H);
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +0100766 pars.imei := f_rnd_imei('00101'H);
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300767
768 log(testcasename(), ": using IMSI ", pars.imsi);
Neels Hofmeyrb5b7a6e2021-06-04 19:03:45 +0200769
Philipp Maier48604732018-10-09 15:00:37 +0200770 return pars;
771}
772
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200773/* Convenience functions for rate counters using g_ctr_msc. */
774
775private function f_ctrs_msc_init(integer mscs_count := NUM_MSC, CounterNameVals counternames := counternames_msc_mscpool) runs on test_CT {
776 g_ctr_msc := f_counter_name_vals_get_n(IPA_CTRL, "msc", mscs_count, counternames);
777 log("initial msc rate counters: ", g_ctr_msc);
778}
779
780private function f_ctrs_msc_add(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr9656e922020-06-30 01:27:01 +0200781 f_counter_name_vals_list_add(g_ctr_msc, msc_nr, countername, val);
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200782}
783
784/* f_ctrs_msc_init();
785 * f_do_thing(on_msc := 0);
786 * f_do_thing(on_msc := 0);
787 * f_do_other(on_msc := 1);
788 * f_ctrs_msc_add(0, "thing", 2);
789 * f_ctrs_msc_add(1, "other");
790 * f_ctrs_msc_verify();
791 */
792private function f_ctrs_msc_verify() runs on test_CT {
793 log("verifying msc rate counters: ", g_ctr_msc);
794 f_counter_name_vals_expect_n(IPA_CTRL, "msc", g_ctr_msc);
795}
796
797/* convenience: f_ctrs_msc_add() and f_ctrs_msc_verify() in one call.
798 * f_ctrs_msc_init();
799 * f_do_thing(on_msc := 0);
800 * f_do_thing(on_msc := 0);
801 * f_do_thing(on_msc := 0);
802 * f_ctrs_msc_expect(0, "thing", 3);
803 */
804private function f_ctrs_msc_expect(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
805 f_ctrs_msc_add(msc_nr, countername, val);
806 f_ctrs_msc_verify();
807}
808
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000809/* Convenience functions for rate counters using g_ctr_bts, always also including g_ctr_bsc. */
810
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100811private 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 +0000812 g_ctr_bts := f_counter_name_vals_get_n(IPA_CTRL, "bts", bts_count, counternames);
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100813 log("initial bts rate counters: ", g_ctr_bts);
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100814}
815
816function f_ctrs_bsc_and_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
817 f_ctrs_bts_init(bts_count, counternames);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000818 f_ctrs_bsc_init(counternames);
819}
820
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100821private function f_ctrs_bsc_and_bts_handover_init(integer bts_count := NUM_BTS) runs on test_CT {
822 var CounterNameVals bts_names := counternames_bsc_bts_handover & counternames_bts_handover;
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100823 f_ctrs_bts_init(bts_count, bts_names);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100824 f_ctrs_bsc_init(counternames_bsc_bts_handover);
825}
826
827private function f_ctrs_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000828 f_counter_name_vals_list_add(g_ctr_bts, bts_nr, countername, val);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100829}
830
831private function f_ctrs_bsc_and_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
832 f_ctrs_bts_add(bts_nr, countername, val);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000833 f_ctrs_bsc_add(countername, val);
834}
835
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100836function f_ctrs_bts_verify() runs on test_CT {
837 f_counter_name_vals_expect_n(IPA_CTRL, "bts", g_ctr_bts);
838}
839
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000840/* f_ctrs_bsc_and_bts_init();
841 * f_do_thing(on_bts := 0);
842 * f_do_thing(on_bts := 0);
843 * f_do_other(on_bts := 1);
844 * f_ctrs_bsc_and_bts_add(0, "thing", 2);
845 * f_ctrs_bsc_and_bts_add(1, "other");
846 * f_ctrs_bsc_and_bts_verify();
847 */
848private function f_ctrs_bsc_and_bts_verify() runs on test_CT {
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100849 f_ctrs_bts_verify();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000850 f_ctrs_bsc_verify();
851}
852
853/* convenience: f_ctrs_bsc_and_bts_add() and f_ctrs_bsc_and_bts_verify() in one call.
854 * f_ctrs_bsc_and_bts_init();
855 * f_do_thing(on_bts := 0);
856 * f_do_thing(on_bts := 0);
857 * f_do_thing(on_bts := 0);
858 * f_ctrs_bsc_and_bts_expect(0, "thing", 3);
859 */
860private function f_ctrs_bsc_and_bts_expect(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
861 f_ctrs_bsc_and_bts_add(bts_nr, countername, val);
862 f_ctrs_bsc_and_bts_verify();
863}
864
865
866/* Convenience functions for rate counters using g_ctr_bsc. */
867
868private function f_ctrs_bsc_init(CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
869 g_ctr_bsc := f_counter_name_vals_get_n(IPA_CTRL, "bsc", 1, counternames);
870 log("initial bsc rate counters: ", g_ctr_bsc);
871}
872
873private function f_ctrs_bsc_add(charstring countername, integer val := 1) runs on test_CT {
874 f_counter_name_vals_list_add(g_ctr_bsc, 0, countername, val);
875}
876
877/* f_ctrs_bsc_init();
878 * f_do_thing();
879 * f_do_thing();
880 * f_do_other();
881 * f_ctrs_bsc_add("thing", 2);
882 * f_ctrs_bsc_add("other");
883 * f_ctrs_bsc_verify();
884 */
885private function f_ctrs_bsc_verify() runs on test_CT {
886 f_counter_name_vals_expect_n(IPA_CTRL, "bsc", g_ctr_bsc);
887}
888
889/* convenience: f_ctrs_bsc_add() and f_ctrs_bsc_verify() in one call.
890 * f_ctrs_bsc_init();
891 * f_do_thing();
892 * f_ctrs_bsc_expect("thing", 1);
893 */
894private function f_ctrs_bsc_expect(charstring countername, integer val := 1) runs on test_CT {
895 f_ctrs_bsc_add(countername, val);
896 f_ctrs_bsc_verify();
897}
898
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200899
Oliver Smith39f53072022-10-27 14:44:04 +0200900friend function f_shutdown_helper(boolean ho := false) runs on test_CT {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100901 /* Run the subscr and conn leak test only when the VTY is initialized */
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600902 if (BSCVTY.checkstate("Mapped") and mp_verify_talloc_count) {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100903 f_verify_talloc_count(BSCVTY, {"struct bsc_subscr", "struct gsm_subscriber_connection"});
904 }
905
Oliver Smith39f53072022-10-27 14:44:04 +0200906 /* Reset handover related configuration */
907 if (ho) {
908 f_bts_0_cfg(BSCVTY,
909 {"no neighbors",
910 "neighbor-list mode manual-si5",
911 "neighbor-list add arfcn 100",
912 "neighbor-list add arfcn 200",
913 "si5 neighbor-list add arfcn 10",
914 "si5 neighbor-list add arfcn 20",
915 "handover algorithm 1"});
916 }
917
Daniel Willmann637ef6c2018-07-25 10:49:09 +0200918 all component.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100919 setverdict(pass);
Daniel Willmannafce8662018-07-06 23:11:32 +0200920 mtc.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100921}
922
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200923private function f_legacy_bssap_reset(integer bssap_idx := 0) runs on test_CT {
Harald Weltea4ca4462018-02-09 00:17:14 +0100924 var BSSAP_N_UNITDATA_ind ud_ind;
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200925 var boolean reset_received := false;
Harald Weltea4ca4462018-02-09 00:17:14 +0100926 timer T := 5.0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200927 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 +0200928 ts_BSSMAP_Reset(0, g_osmux_enabled_cn)));
Harald Weltea4ca4462018-02-09 00:17:14 +0100929 T.start;
930 alt {
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200931 [] 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 +0200932 tr_BSSMAP_ResetAck(g_osmux_enabled_cn))) {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200933 log("BSSMAP: Received RESET-ACK in response to RESET, we're ready to go!");
Harald Weltea4ca4462018-02-09 00:17:14 +0100934 }
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200935 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200936 log("BSSMAP: Respoding to inbound RESET with RESET-ACK");
Harald Weltea4ca4462018-02-09 00:17:14 +0100937 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200938 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200939 reset_received := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100940 repeat;
941 }
942 [] BSSAP.receive { repeat; }
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200943 [] T.timeout {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200944 log("BSSMAP: Timeout waiting for RESET-ACK after sending RESET");
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200945 /* If we received a RESET after ours was sent, it
946 may be a race condition where the other peer beacame
947 available after we sent it, but we are in a desired
948 state anyway, so go forward. */
949 if (not reset_received) {
950 setverdict(fail);
951 }
952 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100953 }
Harald Welte28d943e2017-11-25 15:00:50 +0100954}
955
Harald Welteae026692017-12-09 01:03:01 +0100956type record IPA_Client {
Harald Welte21b46bd2017-12-17 19:46:32 +0100957 /* IPA Emulation component reference */
Harald Welteae026692017-12-09 01:03:01 +0100958 IPA_Emulation_CT vc_IPA,
Harald Welte21b46bd2017-12-17 19:46:32 +0100959 /* Unit-ID and other CCM parameters to use for IPA client emulation */
Harald Welteae026692017-12-09 01:03:01 +0100960 IPA_CCM_Parameters ccm_pars,
Harald Welte21b46bd2017-12-17 19:46:32 +0100961 /* String identifier for this IPA Client */
Harald Welte624f9632017-12-16 19:26:04 +0100962 charstring id,
Harald Welte21b46bd2017-12-17 19:46:32 +0100963 /* Associated RSL Emulation Component (if any). Only used in "Handler mode" */
Harald Welte624f9632017-12-16 19:26:04 +0100964 RSL_Emulation_CT vc_RSL optional
Harald Welte28d943e2017-11-25 15:00:50 +0100965}
966
Harald Welte21b46bd2017-12-17 19:46:32 +0100967/*! Start the IPA/RSL related bits for one IPA_Client.
968 * \param clnt IPA_Client for which to establish
969 * \param bsc_host IP address / hostname of the BSC
970 * \param bsc_port TCP port number of the BSC
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600971 * \param idx BTS/TRX index values
Harald Welte21b46bd2017-12-17 19:46:32 +0100972 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600973function f_ipa_rsl_start(inout IPA_Client clnt, charstring bsc_host, PortNumber bsc_port,
974 BtsTrxIdx idx := {0, 0}, boolean handler_mode := false)
Harald Welte28d943e2017-11-25 15:00:50 +0100975runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +0100976 timer T := 10.0;
977
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600978 clnt.id := "IPA-BTS" & int2str(idx.bts) & "-TRX" & int2str(idx.trx) & "-RSL";
Harald Welte71389132021-12-09 21:58:18 +0100979 clnt.vc_IPA := IPA_Emulation_CT.create(clnt.id & "-IPA") alive;
Harald Welteae026692017-12-09 01:03:01 +0100980 clnt.ccm_pars := c_IPA_default_ccm_pars;
981 clnt.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600982 clnt.ccm_pars.unit_id := int2str(1234 + idx.bts) & "/0/" & int2str(idx.trx);
Harald Welte624f9632017-12-16 19:26:04 +0100983 if (handler_mode) {
Harald Welte71389132021-12-09 21:58:18 +0100984 clnt.vc_RSL := RSL_Emulation_CT.create(clnt.id & "-RSL") alive;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600985 connect(clnt.vc_RSL:CCHAN_PT, self:RSL_CCHAN[idx.bts]);
Harald Welte624f9632017-12-16 19:26:04 +0100986 }
Harald Welteae026692017-12-09 01:03:01 +0100987
988 map(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200989 connect(clnt.vc_IPA:CFG_PORT, self:IPA_CFG_PORT[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100990 if (handler_mode) {
991 connect(clnt.vc_IPA:IPA_RSL_PORT, clnt.vc_RSL:IPA_PT);
992 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600993 connect(clnt.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100994 }
Harald Welteae026692017-12-09 01:03:01 +0100995
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600996 var integer local_port := 10000 + idx.bts * 1000 + idx.trx;
997 clnt.vc_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", local_port, clnt.ccm_pars));
Harald Welte624f9632017-12-16 19:26:04 +0100998 if (handler_mode) {
999 clnt.vc_RSL.start(RSL_Emulation.main());
1000 return;
1001 }
Harald Welteae026692017-12-09 01:03:01 +01001002
1003 /* wait for IPA RSL link to connect and send ID ACK */
1004 T.start;
1005 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001006 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) {
Harald Welteae026692017-12-09 01:03:01 +01001007 T.stop;
Harald Welteae026692017-12-09 01:03:01 +01001008 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001009 [] IPA_RSL[idx.bts][idx.trx].receive(ASP_IPA_Event:?) { repeat }
1010 [] IPA_RSL[idx.bts][idx.trx].receive { repeat }
Harald Welteae026692017-12-09 01:03:01 +01001011 [] T.timeout {
Harald Welte96c94412017-12-09 03:12:45 +01001012 setverdict(fail, "Timeout RSL waiting for ASP_IPA_EVENT_ID_ACK");
Daniel Willmannafce8662018-07-06 23:11:32 +02001013 mtc.stop;
Harald Welteae026692017-12-09 01:03:01 +01001014 }
1015 }
1016}
1017
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001018function f_ipa_rsl_stop(inout IPA_Client clnt, BtsTrxIdx idx := {0, 0}) runs on test_CT {
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001019 var IPL4asp_Types.Result res := {
1020 errorCode := omit,
1021 connId := omit,
1022 os_error_code := omit,
1023 os_error_text := omit
1024 };
1025
Harald Welte12055472018-03-17 20:10:08 +01001026 if (not isbound(clnt) or not isbound(clnt.vc_IPA)) {
1027 return;
1028 }
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001029
1030 /* Alive components don't finish sockets (TCP FIN) when they are
1031 * stopped. Hence, we need to manually call close() on them to make sure
1032 * the IUT knows about it. */
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001033 f_ipa_cfg_disconnect(IPA_CFG_PORT[idx.bts][idx.trx], res);
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001034
Harald Welte12055472018-03-17 20:10:08 +01001035 clnt.vc_IPA.stop;
1036 if (isbound(clnt.vc_RSL)) {
1037 clnt.vc_RSL.stop;
1038 }
1039}
1040
Harald Welte21b46bd2017-12-17 19:46:32 +01001041/* Wait for the OML connection to be brought up by the external osmo-bts-omldummy */
Harald Weltea5d2ab22017-12-09 14:21:42 +01001042function f_wait_oml(integer bts_nr, charstring status, float secs_max) runs on test_CT {
1043 timer T := secs_max;
1044 T.start;
1045 while (true) {
1046 if (f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-connection-state") == status) {
1047 T.stop;
Harald Weltebd868bd2017-12-10 18:28:40 +01001048 /* the 'degraded' state exists from OML connection time, and we have to wait
1049 * until all MO's are initialized */
1050 T.start(1.0);
1051 T.timeout;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001052 return;
1053 }
Harald Weltef0d6ac62017-12-17 17:02:21 +01001054 f_sleep(0.1);
Harald Weltea5d2ab22017-12-09 14:21:42 +01001055 if (not T.running) {
Max99253902018-11-16 17:57:39 +01001056 setverdict(fail, "Timeout waiting for BTS" & int2str(bts_nr) & " oml-connection-state ", status);
Daniel Willmannafce8662018-07-06 23:11:32 +02001057 mtc.stop;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001058 }
1059 }
1060}
1061
Harald Welte21b46bd2017-12-17 19:46:32 +01001062/* global altstep for global guard timer; also takes care of responding RESET witH RESET-ACK */
Harald Welteae026692017-12-09 01:03:01 +01001063altstep as_Tguard() runs on test_CT {
Harald Welte60e823a2017-12-10 14:10:59 +01001064 var BSSAP_N_UNITDATA_ind ud_ind;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001065 [] T_guard.timeout {
1066 setverdict(fail, "Timeout of T_guard");
Daniel Willmannafce8662018-07-06 23:11:32 +02001067 mtc.stop;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001068 }
Harald Welte60e823a2017-12-10 14:10:59 +01001069 /* always respond with RESET ACK to RESET */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001070 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Harald Welte60e823a2017-12-10 14:10:59 +01001071 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001072 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Harald Welte69c1c262017-12-13 21:02:08 +01001073 repeat;
Harald Welte60e823a2017-12-10 14:10:59 +01001074 }
Harald Welte28d943e2017-11-25 15:00:50 +01001075}
1076
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001077altstep no_bssmap_reset() runs on test_CT {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001078 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001079 setverdict(fail, "unexpected BSSMAP Reset");
Daniel Willmannafce8662018-07-06 23:11:32 +02001080 mtc.stop;
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001081 }
1082}
1083
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001084function f_init_mgcp(integer mgw_nr, charstring id) runs on test_CT {
1085 id := id & "-MGCP-" & int2str(mgw_nr);
Daniel Willmann191e0d92018-01-17 12:44:35 +01001086
1087 var MGCPOps ops := {
1088 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
1089 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
1090 };
1091 var MGCP_conn_parameters mgcp_pars := {
1092 callagent_ip := mp_bsc_ip,
Harald Welte9e4273e2018-01-29 22:01:22 +01001093 callagent_udp_port := -1,
Daniel Willmann191e0d92018-01-17 12:44:35 +01001094 mgw_ip := mp_test_ip,
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001095 mgw_udp_port := 2427 + mgw_nr,
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02001096 /* Enable it for SCCPlite, since we have 2 MGCP sockets towards MGW (UDP one +
Pau Espin Pedrol36eeaf72022-10-20 16:50:31 +02001097 the one with MGCP over IPA forwarded from MSC one) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001098 multi_conn_mode := (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER)
Daniel Willmann191e0d92018-01-17 12:44:35 +01001099 };
1100
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001101 vc_MGCP[mgw_nr] := MGCP_Emulation_CT.create(id) alive;
1102 vc_MGCP[mgw_nr].start(MGCP_Emulation.main(ops, mgcp_pars, id));
Daniel Willmann191e0d92018-01-17 12:44:35 +01001103}
1104
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001105/* Enable or disable (current default) Osmux. When enabling, BSSMAP Reset
1106 * contains extra IE (OsmuxSupport) and osmo-bsc will handle AssignReq with
1107 * OsmuxCID IE.
1108 */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001109private function f_vty_allow_osmux_cn(boolean allow) runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001110 f_vty_enter_cfg_msc(BSCVTY, 0);
1111 if (allow) {
1112 f_vty_transceive(BSCVTY, "osmux on");
1113 } else {
1114 f_vty_transceive(BSCVTY, "osmux off");
1115 }
1116 f_vty_transceive(BSCVTY, "exit");
1117 f_vty_transceive(BSCVTY, "exit");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001118}
1119
Max2253c0b2018-11-06 19:28:05 +01001120function f_init_vty(charstring id := "foo") runs on test_CT {
Harald Welte94e0c342018-04-07 11:33:23 +02001121 if (BSCVTY.checkstate("Mapped")) {
1122 /* skip initialization if already executed once */
1123 return;
1124 }
Harald Weltebc03c762018-02-12 18:09:38 +01001125 map(self:BSCVTY, system:BSCVTY);
1126 f_vty_set_prompts(BSCVTY);
1127 f_vty_transceive(BSCVTY, "enable");
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01001128 f_cs7_inst_0_cfg(BSCVTY, {"sccp-timer ias " & int2str(g_bsc_sccp_timer_ias),
1129 "sccp-timer iar " & int2str(g_bsc_sccp_timer_iar)});
Harald Weltebc03c762018-02-12 18:09:38 +01001130}
1131
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +02001132friend function f_logp(TELNETasp_PT pt, charstring log_msg)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001133{
1134 // log on TTCN3 log output
1135 log(log_msg);
1136 // log in stderr log
Neels Hofmeyr8bdafe52021-12-14 17:25:48 +01001137 if (pt.checkstate("Mapped")) {
1138 f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
1139 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001140}
1141
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001142private function f_sysinfo_seen(integer rsl_idx, RSL_Message rsl) runs on test_CT
1143{
1144 if (rsl_idx >= lengthof(g_system_information)) {
1145 g_system_information[rsl_idx] := SystemInformationConfig_omit
1146 }
1147 f_sysinfo_dec_raw(g_system_information[rsl_idx], rsl);
1148}
1149
1150altstep as_catch_RSL_sysinfo(integer rsl_idx) runs on test_CT {
1151 var ASP_RSL_Unitdata rx_rsl_ud;
1152
1153 /* For handler_mode := false, receiving the RSL bootstrap messages directly on IPA_RSL */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001154 [] 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 +02001155 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1156 repeat;
1157 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001158 [] 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 +02001159 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1160 repeat;
1161 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001162 [] 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 +02001163 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1164 repeat;
1165 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001166 [] 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 +02001167 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1168 repeat;
1169 }
1170
1171 /* For handler_mode := true, receiving the RSL bootstrap messages via RSL_Emulation */
1172 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
1173 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1174 repeat;
1175 }
1176 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
1177 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1178 repeat;
1179 }
1180 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
1181 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1182 repeat;
1183 }
1184 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
1185 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1186 repeat;
1187 }
1188}
1189
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001190/* TODO: use BooleanList from COMMON/src/General_Types.ttcn */
1191private type record of boolean my_BooleanList;
1192
1193private function f_vty_msc_allow_attach(TELNETasp_PT pt, my_BooleanList allow_attach_list)
1194{
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001195 var charstring config := f_vty_transceive_ret(pt, "show running-config");
1196
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001197 for (var integer msc_nr := 0; msc_nr < sizeof(allow_attach_list); msc_nr := msc_nr+1) {
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001198 if (f_strstr(config, "\nmsc " & int2str(msc_nr) & "\n") < 0) {
1199 /* There is no 'msc N' for this msc_nr in the running config, so don't create an empty msc by
1200 * stepping into that config node. */
1201 log("msc ", msc_nr, " is not configured, skipping");
1202 continue;
1203 }
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001204 f_vty_enter_cfg_msc(pt, msc_nr);
1205 if (allow_attach_list[msc_nr]) {
1206 /* strict := false: ignore if osmo-bsc does not support this config option (latest build) */
1207 f_vty_transceive(pt, "allow-attach", strict := false);
1208 } else {
1209 f_vty_transceive(pt, "no allow-attach", strict := false);
1210 }
1211 f_vty_transceive(pt, "exit");
1212 f_vty_transceive(pt, "exit");
1213 }
1214}
1215
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02001216private function f_bssap_idx_init(integer bssap_idx) runs on test_CT {
1217 /* Call a function of our 'parent component' RAN_Adapter_CT to start the
1218 * MSC-side BSSAP emulation */
1219 if (g_handler_mode) {
1220 var RanOps ranops := MSC_RanOps;
1221 ranops.use_osmux := g_osmux_enabled_cn;
1222 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", ranops);
1223 connect(self:SCCPLITE_IPA_CTRL, g_bssap[bssap_idx].vc_RAN:CTRL_CLIENT);
1224 f_ran_adapter_start(g_bssap[bssap_idx]);
1225 } else {
1226 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", omit);
1227 connect(self:BSSAP, g_bssap[bssap_idx].vc_SCCP:SCCP_SP_PORT);
1228 f_ran_adapter_start(g_bssap[bssap_idx]);
1229 f_legacy_bssap_reset();
1230 }
1231}
1232
1233private function f_bssap_idx_disconnect(integer bssap_idx) runs on test_CT {
1234 f_ran_adapter_cleanup(g_bssap[bssap_idx]);
1235}
1236
Harald Welte21b46bd2017-12-17 19:46:32 +01001237/* global initialization function
1238 * \param nr_bts Number of BTSs we should start/bring up
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001239 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false).
1240 * \param nr_msc Number of virtual MSCs to bring up to connect to osmo-bsc.
1241 */
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001242function f_init(integer nr_bts := NUM_BTS, boolean handler_mode := false,
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001243 integer nr_msc := 1, integer nr_mgw := 1, float guard_timeout := 30.0) runs on test_CT {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001244 var integer bssap_idx;
Harald Welte28d943e2017-11-25 15:00:50 +01001245
Harald Welteae026692017-12-09 01:03:01 +01001246 if (g_initialized) {
1247 return;
Harald Welte28d943e2017-11-25 15:00:50 +01001248 }
Harald Welteae026692017-12-09 01:03:01 +01001249 g_initialized := true;
1250
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +02001251 T_guard.start(guard_timeout);
Daniel Willmanne68f9272018-11-27 15:15:28 +01001252 activate(as_Tguard());
1253
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001254 f_init_vty("VirtMSC");
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001255 f_vty_allow_osmux_cn(g_osmux_enabled_cn);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001256
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001257 var my_BooleanList allow_attach := { false, false, false };
Daniel Willmannebdecc02020-08-12 15:30:17 +02001258 f_init_statsd("VirtMSC", vc_STATSD, mp_test_ip, mp_bsc_statsd_port);
1259
Neels Hofmeyr9db8e0e2021-08-23 20:45:58 +02001260 /* Make sure each MSC's internal state is "DISCONNECTED" at first */
1261 for (bssap_idx := 0; bssap_idx < NUM_MSC; bssap_idx := bssap_idx+1) {
1262 f_vty_transceive(BSCVTY, "msc " & int2str(bssap_idx) & " bssmap reset", strict := false);
1263 }
1264
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02001265 g_handler_mode := handler_mode;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001266 for (bssap_idx := 0; bssap_idx < nr_msc; bssap_idx := bssap_idx+1) {
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001267 allow_attach[bssap_idx] := true;
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02001268 f_bssap_idx_init(bssap_idx);
Harald Welte67089ee2018-01-17 22:19:03 +01001269 }
Harald Welted5833a82018-05-27 16:52:56 +02001270
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02001271 if (mp_enable_lcs_tests) {
1272 if (handler_mode) {
1273 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", SMLC_BssapLeOps);
1274 } else {
1275 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", omit);
1276 connect(self:BSSAP_LE, g_bssap_le.vc_SCCP:SCCP_SP_PORT);
1277 }
1278 f_bssap_le_adapter_start(g_bssap_le);
Harald Welte47cd0e32020-08-21 12:39:11 +02001279 }
Harald Welte47cd0e32020-08-21 12:39:11 +02001280
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001281 /* start the test with exactly all enabled MSCs allowed to attach */
1282 f_vty_msc_allow_attach(BSCVTY, allow_attach);
1283
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01001284 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Harald Welte28d943e2017-11-25 15:00:50 +01001285
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001286 g_nr_mgw := nr_mgw;
1287 for (var integer i := 0; i < g_nr_mgw; i := i+1) {
1288 f_init_mgcp(i, "VirtMGW");
1289 }
Daniel Willmann191e0d92018-01-17 12:44:35 +01001290
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001291 for (var integer i := 0; i < nr_bts; i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001292 f_init_bts(i, c_BtsParams[i].trx_num, handler_mode);
Harald Welte696ddb62017-12-08 14:01:43 +01001293 }
Neels Hofmeyr9c0f9c82022-01-23 01:20:28 +01001294
1295 /* Emit a marker to appear in the SUT's own logging output */
1296 f_logp(BSCVTY, testcasename() & "() start");
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001297}
Harald Welte696ddb62017-12-08 14:01:43 +01001298
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001299function f_init_bts(integer bts_idx := 0,
1300 integer trx_num := NUM_TRX_CFG,
1301 boolean handler_mode := false)
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001302runs on test_CT {
1303 /* wait until osmo-bts-omldummy has respawned */
1304 f_wait_oml(bts_idx, "degraded", 5.0);
1305
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001306 /* start RSL connection(s) */
1307 for (var integer trx_idx := 0; trx_idx < trx_num; trx_idx := trx_idx + 1) {
1308 f_ipa_rsl_start(bts[bts_idx][trx_idx].rsl,
1309 mp_bsc_ip, mp_bsc_rsl_port,
1310 {bts_idx, trx_idx}, handler_mode);
1311 }
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001312 /* wait until BSC tells us "connected" */
1313 f_wait_oml(bts_idx, "connected", 5.0);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001314
1315 /* Set up BTS with VTY commands: */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01001316 f_vty_enter_cfg_bts(BSCVTY, bts_idx);
1317 if (g_osmux_enabled_bts) {
1318 f_vty_transceive(BSCVTY, "osmux on");
1319 } else {
1320 f_vty_transceive(BSCVTY, "osmux off");
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001321 }
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01001322 f_vty_transceive(BSCVTY, "end");
Harald Welte28d943e2017-11-25 15:00:50 +01001323}
1324
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001325function f_init_bts_and_check_sysinfo(integer bts_idx := 0,
1326 integer trx_num := NUM_TRX_CFG,
1327 boolean handler_mode := false,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001328 template SystemInformationConfig expect_si)
1329runs on test_CT {
1330 var default sysinfo := activate(as_catch_RSL_sysinfo(bts_idx));
1331
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001332 f_init_bts(bts_idx, trx_num, handler_mode);
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001333
1334 /* Give some time to (hopefully/most likely) collect all system informations from RSL startup.
1335 * We could stop as soon as all expected SI are received, but then we might miss SI that we don't expect and
1336 * that might be sent afterwards. So rather give a generous timeout and be quite sure to catch all SI.
1337 */
1338 f_sleep(5.0);
1339 log("RSL ", bts_idx, " SYSTEM INFORMATION: ", g_system_information[bts_idx]);
1340
1341 deactivate(sysinfo);
1342
1343 if (match(g_system_information[bts_idx], expect_si)) {
1344 setverdict(pass);
1345 } else {
1346 log("RSL ", bts_idx, ": EXPECTED SI: ", expect_si);
1347 log("RSL ", bts_idx, ": GOT SI: ", g_system_information[bts_idx]);
1348 setverdict(fail, "received SI does not match expectations");
1349 return;
1350 }
1351}
1352
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001353/* expect to receive a RSL message matching a specified template on a given BTS / TRX */
1354function f_exp_ipa_rx(template (present) RSL_Message t_rx,
1355 BtsTrxIdx idx := {0, 0},
1356 float Tval := 2.0)
Harald Welteae026692017-12-09 01:03:01 +01001357runs on test_CT return RSL_Message {
1358 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001359 timer T := Tval;
Harald Welteae026692017-12-09 01:03:01 +01001360
1361 T.start;
1362 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001363 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Harald Welteae026692017-12-09 01:03:01 +01001364 T.stop;
1365 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001366 [] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
Harald Welteb2917702017-12-10 15:48:52 +01001367 [] T.timeout {
1368 setverdict(fail, "Timeout expecting ", t_rx);
Daniel Willmannafce8662018-07-06 23:11:32 +02001369 mtc.stop;
Harald Welteb2917702017-12-10 15:48:52 +01001370 }
Harald Welteae026692017-12-09 01:03:01 +01001371 }
1372 return rx_rsl_ud.rsl;
1373}
1374
Harald Welte21b46bd2017-12-17 19:46:32 +01001375/* helper function to transmit RSL on a given BTS/stream */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001376function f_ipa_tx(template (value) RSL_Message t_tx,
1377 BtsTrxIdx idx := {0, 0},
1378 IpaStreamId sid := IPAC_PROTO_RSL_TRX0)
Harald Welteae026692017-12-09 01:03:01 +01001379runs on test_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001380 IPA_RSL[idx.bts][idx.trx].send(ts_ASP_RSL_UD(t_tx, sid));
Harald Welteae026692017-12-09 01:03:01 +01001381}
1382
1383
Harald Welte4003d112017-12-09 22:35:39 +01001384/* verify we get a CHAN_ACT after CHAN RQD */
Harald Welteae026692017-12-09 01:03:01 +01001385testcase TC_chan_act_noreply() runs on test_CT {
1386 var BSSAP_N_UNITDATA_ind ud_ind;
Harald Welte930d0a72018-03-22 22:08:40 +01001387 var RSL_Message rsl_unused;
Harald Welte28d943e2017-11-25 15:00:50 +01001388
Harald Welte89d42e82017-12-17 16:42:41 +01001389 f_init(1);
Harald Welte28d943e2017-11-25 15:00:50 +01001390
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001391 f_ipa_tx(ts_RSL_CHAN_RQD('23'O, 23));
1392 rsl_unused := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001393 f_shutdown_helper();
Harald Welte28d943e2017-11-25 15:00:50 +01001394}
1395
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001396const CounterNameVals counternames_bts_chreq := {
1397 { "chreq:total", 0 },
1398 { "chreq:attempted_emerg", 0 },
1399 { "chreq:attempted_call", 0 },
1400 { "chreq:attempted_location_upd", 0 },
1401 { "chreq:attempted_pag", 0 },
1402 { "chreq:attempted_pdch", 0 },
1403 { "chreq:attempted_other", 0 },
1404 { "chreq:attempted_unknown", 0 },
1405 { "chreq:successful", 0 },
1406 { "chreq:successful_emerg", 0 },
1407 { "chreq:successful_call", 0 },
1408 { "chreq:successful_location_upd", 0 },
1409 { "chreq:successful_pag", 0 },
1410 { "chreq:successful_pdch", 0 },
1411 { "chreq:successful_other", 0 },
1412 { "chreq:successful_unknown", 0 },
1413 { "chreq:no_channel", 0 },
1414 { "chreq:max_delay_exceeded", 0 }
1415};
1416
1417/* verify the "chreq:*" counters */
1418private function f_chan_act_counter(OCT1 ra, charstring chreq_ctr_suffix) runs on test_CT
1419{
1420 var GsmFrameNumber fn := 23;
1421
1422 f_logp(BSCVTY, "f_chan_act_counter(" & chreq_ctr_suffix & ")");
1423
1424 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001425 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn));
1426 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001427 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1428
1429 f_ctrs_bts_add(0, "chreq:total");
1430 f_ctrs_bts_add(0, "chreq:attempted_" & chreq_ctr_suffix);
1431 f_ctrs_bts_verify();
1432
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001433 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
1434 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001435
1436 f_ctrs_bts_add(0, "chreq:successful");
1437 f_ctrs_bts_add(0, "chreq:successful_" & chreq_ctr_suffix);
1438 f_ctrs_bts_verify();
1439
1440 /* test is done, release RSL Conn Fail Ind to clean up */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001441 f_ipa_tx(ts_RSL_CONN_FAIL_IND(chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1442 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
1443 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001444 f_sleep(1.0);
1445}
1446
Harald Welte4003d112017-12-09 22:35:39 +01001447testcase TC_chan_act_counter() runs on test_CT {
1448 var BSSAP_N_UNITDATA_ind ud_ind;
1449 var integer chreq_total;
Harald Welte930d0a72018-03-22 22:08:40 +01001450 var RSL_Message rsl_unused;
Harald Welte4003d112017-12-09 22:35:39 +01001451
Harald Welte89d42e82017-12-17 16:42:41 +01001452 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001453
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001454 f_vty_allow_emerg_bts(true, 0);
1455
1456 f_ctrs_bts_init(1, counternames_bts_chreq);
1457
1458 /* emergency call: RA & 0xe0 == 0xa0 --> CHREQ_T_EMERG_CALL */
1459 f_chan_act_counter('a3'O, "emerg");
1460
1461 /* voice TCH/H: RA & 0xf0 == 0x40 --> CHREQ_T_VOICE_CALL_TCH_H */
1462 f_chan_act_counter('43'O, "call");
1463
1464 /* LU: RA & 0xf0 == 0x00 --> CHREQ_T_LOCATION_UPD */
1465 f_chan_act_counter('03'O, "location_upd");
1466
1467 /* Paging: RA & 0xf0 == 0x20 --> CHREQ_T_PAG_R_TCH_F */
1468 f_chan_act_counter('23'O, "pag");
1469 /* Paging: RA & 0xf0 == 0x30 --> CHREQ_T_PAG_R_TCH_FH */
1470 f_chan_act_counter('33'O, "pag");
1471
1472 /* LU: RA & 0xfc == 0x78 --> CHREQ_T_PDCH_TWO_PHASE */
1473 /* no PCU, so PDCH not allowed. Skip this test for now. */
1474 /* f_chan_act_counter('7b'O, "pdch"); */
1475
1476 /* LU: RA & 0xf0 == 0x10 --> CHREQ_T_SDCCH */
1477 f_chan_act_counter('13'O, "other");
Harald Welte4003d112017-12-09 22:35:39 +01001478
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001479 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001480}
1481
Harald Welteae026692017-12-09 01:03:01 +01001482/* CHAN RQD -> CHAN ACT -> CHAN ACT ACK -> RF CHAN REL */
Philipp Maier9c60a622020-07-09 15:08:46 +02001483private function f_TC_chan_act_ack_noest(OCT1 ra := '23'O) runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +01001484 var RSL_Message rx_rsl;
1485
Harald Welteae026692017-12-09 01:03:01 +01001486 /* Send CHAN RQD and wait for allocation; acknowledge it */
Philipp Maier9c60a622020-07-09 15:08:46 +02001487 var RslChannelNr chan_nr := f_chreq_act_ack(ra);
Harald Welteae026692017-12-09 01:03:01 +01001488
1489 /* expect BSC to disable the channel again if there's no RLL EST IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001490 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := T3101_MAX);
Harald Welteae026692017-12-09 01:03:01 +01001491
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001492 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001493}
1494
Philipp Maier9c60a622020-07-09 15:08:46 +02001495/* Normal variant */
1496testcase TC_chan_act_ack_noest() runs on test_CT {
Philipp Maieraf58db22020-08-12 17:24:40 +02001497 f_init(1);
Philipp Maier9c60a622020-07-09 15:08:46 +02001498 f_TC_chan_act_ack_noest();
1499}
1500
1501/* Emergency call variant */
1502testcase TC_chan_act_ack_noest_emerg() runs on test_CT {
1503 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
Philipp Maieraf58db22020-08-12 17:24:40 +02001504 f_init(1);
1505 f_vty_allow_emerg_bts(true, 0);
Philipp Maier9c60a622020-07-09 15:08:46 +02001506 f_TC_chan_act_ack_noest(ra := 'A5'O);
1507}
1508
Philipp Maier606f07d2020-08-12 17:21:58 +02001509/* Emergency call variant, but emergency calls are not allowed */
1510testcase TC_chan_rqd_emerg_deny() runs on test_CT {
1511 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
1512
1513 var RSL_Message rx_rsl;
1514 var GsmRrMessage rr;
1515
1516 f_init(1);
1517 f_vty_allow_emerg_bts(false, 0);
1518
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001519 IPA_RSL[0][0].clear;
1520 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier606f07d2020-08-12 17:21:58 +02001521
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001522 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Philipp Maier606f07d2020-08-12 17:21:58 +02001523 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
1524 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1525 setverdict(pass);
1526 } else {
1527 setverdict(fail, "immediate assignment not rejected");
1528 }
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01001529
1530 f_shutdown_helper();
Philipp Maier606f07d2020-08-12 17:21:58 +02001531}
1532
Harald Welteae026692017-12-09 01:03:01 +01001533/* Test behavior if MSC never answers to CR */
1534testcase TC_chan_act_ack_est_ind_noreply() runs on test_CT {
Harald Weltef77aef62018-01-28 15:35:42 +01001535 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
1536 var IpaStreamId sid := IPAC_PROTO_RSL_TRX0;
Harald Welteae026692017-12-09 01:03:01 +01001537 var RSL_Message rx_rsl;
Harald Weltef77aef62018-01-28 15:35:42 +01001538 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001539 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welteae026692017-12-09 01:03:01 +01001540
Harald Welte89d42e82017-12-17 16:42:41 +01001541 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001542
1543 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001544 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001545
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001546 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welteae026692017-12-09 01:03:01 +01001547
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001548 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload)));
Harald Welteae026692017-12-09 01:03:01 +01001549
1550 /* expect BSC to disable the channel again if there's no response from MSC */
Harald Weltef77aef62018-01-28 15:35:42 +01001551 /* MS waits 20s (T3210) at LU; 10s (T3230) at CM SERV REQ and 5s (T3220) AT detach */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001552 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001553 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001554}
1555
1556/* Test behavior if MSC answers with CREF to CR */
1557testcase TC_chan_act_ack_est_ind_refused() runs on test_CT {
1558 var BSSAP_N_CONNECT_ind rx_c_ind;
1559 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001560 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welteae026692017-12-09 01:03:01 +01001561
Harald Welte89d42e82017-12-17 16:42:41 +01001562 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001563
1564 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001565 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001566
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001567 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welteae026692017-12-09 01:03:01 +01001568
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001569 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Harald Welteae026692017-12-09 01:03:01 +01001570 BSSAP.send(ts_BSSAP_DISC_req(rx_c_ind.connectionId, 0));
1571
1572 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001573 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001574 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001575}
1576
Harald Welte618ef642017-12-14 14:58:20 +01001577/* CHAN RQD -> CHAN ACT -> CHAN ACT NACK -> RF CHAN REL */
1578testcase TC_chan_act_nack() runs on test_CT {
1579 var RSL_Message rx_rsl;
1580 var integer chact_nack;
1581
Harald Welte89d42e82017-12-17 16:42:41 +01001582 f_init(1);
Harald Welte618ef642017-12-14 14:58:20 +01001583
1584 chact_nack := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack");
1585
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001586 f_ipa_tx(ts_RSL_CHAN_RQD('33'O, 33));
1587 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Harald Welte618ef642017-12-14 14:58:20 +01001588 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1589
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001590 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte618ef642017-12-14 14:58:20 +01001591
1592 /* wait for some time to hope the NACK arrives before the CTRL GET below */
1593 f_sleep(0.5);
1594
1595 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack", chact_nack+1);
1596
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001597 f_shutdown_helper();
Harald Welte618ef642017-12-14 14:58:20 +01001598}
1599
Harald Welte799c97b2017-12-14 17:50:30 +01001600/* Test for channel exhaustion due to RACH overload */
1601testcase TC_chan_exhaustion() runs on test_CT {
1602 var ASP_RSL_Unitdata rsl_ud;
1603 var integer i;
1604 var integer chreq_total, chreq_nochan;
1605
Harald Welte89d42e82017-12-17 16:42:41 +01001606 f_init(1);
Harald Welte799c97b2017-12-14 17:50:30 +01001607
1608 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
1609 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
1610
Neels Hofmeyr85fa37f2021-10-06 13:50:38 +02001611 /* GSM 44.018 Table 9.1.8.2:
Pau Espin Pedrolfe200d72018-12-10 12:41:04 +01001612 * RA = '33'O -> Establishment cause = 0011xxxx (MS dual rate capable and asks for "TCH/H or TCH/F").
1613 * With current setup, expect 4xSDCCH + 4xTCH/F + 1xTCH/H to succeed */
Philipp Maiercb6cc482018-03-26 13:08:00 +02001614 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 +01001615 var RslChannelNr chan_nr := f_chreq_act_ack('33'O, i);
Harald Welte799c97b2017-12-14 17:50:30 +01001616 }
1617
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001618 IPA_RSL[0][0].clear;
Harald Welte799c97b2017-12-14 17:50:30 +01001619
Harald Weltedd8cbf32018-01-28 12:07:52 +01001620 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001621 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
Harald Welte799c97b2017-12-14 17:50:30 +01001622
1623 /* now expect additional channel activations to fail */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001624 f_ipa_tx(ts_RSL_CHAN_RQD('42'O, 42));
Harald Welte799c97b2017-12-14 17:50:30 +01001625
1626 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001627 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV))) {
Harald Welte799c97b2017-12-14 17:50:30 +01001628 setverdict(fail, "Received CHAN ACT ACK without resources?!?");
1629 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001630 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) -> value rsl_ud {
Harald Welte799c97b2017-12-14 17:50:30 +01001631 var GsmRrMessage rr;
1632 /* match on IMM ASS REJ */
1633 rr := dec_GsmRrMessage(rsl_ud.rsl.ies[1].body.full_imm_ass_info.payload);
1634 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1635 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001636 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS+1);
Harald Welte799c97b2017-12-14 17:50:30 +01001637 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel",
1638 chreq_nochan+1);
1639 setverdict(pass);
1640 } else {
1641 repeat;
1642 }
1643 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001644 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte799c97b2017-12-14 17:50:30 +01001645 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001646 f_shutdown_helper();
Harald Welte799c97b2017-12-14 17:50:30 +01001647}
1648
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001649/* Test channel deactivation due to silence from MS */
1650testcase TC_chan_deact_silence() runs on test_CT {
1651 var RslChannelNr chan_nr;
1652
1653 f_init(1);
1654
1655 /* Request for a dedicated channel */
1656 chan_nr := f_chreq_act_ack('23'O);
1657
1658 /* Wait some time until the channel is released */
1659 f_sleep(2.0);
1660
1661 /* Expect CHANnel RELease */
1662 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001663 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001664 log("Received CHANnel RELease");
1665 setverdict(pass);
1666 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001667 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001668 /* See OS#3709, OsmoBSC should not send Immediate
1669 * Assignment Reject since a dedicated channel was
1670 * already allocated, and Immediate Assignment was
1671 * already sent. */
1672 setverdict(fail, "Unexpected Immediate Assignment!");
1673 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001674 [] IPA_RSL[0][0].receive {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001675 setverdict(fail, "Unexpected RSL message!");
1676 }
1677 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001678 f_shutdown_helper();
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001679}
1680
Harald Weltecfe2c962017-12-15 12:09:32 +01001681/***********************************************************************
1682 * Assignment Testing
1683 ***********************************************************************/
1684
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02001685/* Verify that the BSC refuses any BSSAP connection from the MSC (They are all BSC->MSC direction,
1686 * except for the inter-BSC handover, MT side) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001687testcase TC_outbound_connect(integer bssap_idx := 0) runs on test_CT {
Harald Welte89d42e82017-12-17 16:42:41 +01001688 f_init(1);
Harald Weltecfe2c962017-12-15 12:09:32 +01001689
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001690 BSSAP.send(ts_BSSAP_CONNECT_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
1691 2342, ts_BSSMAP_AssignmentReq));
Harald Weltecfe2c962017-12-15 12:09:32 +01001692 BSSAP.receive(tr_BSSAP_DISC_ind(2342, ?, ?));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001693 f_shutdown_helper();
Harald Weltecfe2c962017-12-15 12:09:32 +01001694}
1695
Harald Welte16a4adf2017-12-14 18:54:01 +01001696/* Test behavior if MSC answers with CREF to CR */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001697testcase TC_assignment_cic_only(integer bssap_idx := 0) runs on test_CT {
Harald Welte16a4adf2017-12-14 18:54:01 +01001698 var BSSAP_N_CONNECT_ind rx_c_ind;
1699 var RSL_Message rx_rsl;
1700 var DchanTuple dt;
1701
Harald Welte89d42e82017-12-17 16:42:41 +01001702 f_init(1);
Harald Welte16a4adf2017-12-14 18:54:01 +01001703
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001704 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001705 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte17b27da2018-05-25 20:33:53 +02001706 /* send assignment without AoIP IEs */
1707 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(ts_BSSMAP_IE_CIC(0, 1))));
1708 } else {
Pau Espin Pedrol35609792023-01-03 16:56:59 +01001709 /* Send assignment without CIC in IPA case */
Harald Welte17b27da2018-05-25 20:33:53 +02001710 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
1711 valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
1712 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(omit, tla)));
1713 }
Harald Welte16a4adf2017-12-14 18:54:01 +01001714 alt {
1715 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1716 setverdict(fail, "AoIP BSC cannot accept ASSIGNMENT without AoIP Transport IE");
1717 }
Harald Welte235ebf12017-12-15 14:18:16 +01001718 /* TODO: Actually expect GSM0808_CAUSE_REQ_A_IF_TYPE_NOT_SUPP */
Harald Welte16a4adf2017-12-14 18:54:01 +01001719 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1720 setverdict(pass);
1721 }
1722 [] BSSAP.receive { repeat; }
1723 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001724 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001725 f_shutdown_helper();
Harald Welte16a4adf2017-12-14 18:54:01 +01001726}
1727
Harald Welteed848512018-05-24 22:27:58 +02001728/* generate an assignment request for either AoIP or SCCPlite */
Pau Espin Pedrolb522e1c2023-09-28 13:38:50 +02001729function f_gen_ass_req(boolean osmux_enabled := false, uint8_t ass_cid := 0, integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4") return PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001730 var PDU_BSSAP ass_cmd;
Pau Espin Pedrolb522e1c2023-09-28 13:38:50 +02001731 var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(ass_cid));
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001732 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welteed848512018-05-24 22:27:58 +02001733 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001734 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001735 if (osmux_enabled) {
1736 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla, osmux_cid));
1737 } else {
1738 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla));
1739 }
Harald Welteed848512018-05-24 22:27:58 +02001740 } else {
Pau Espin Pedrolb522e1c2023-09-28 13:38:50 +02001741 var BIT8 ass_cid_bit := int2bit(ass_cid, 8);
1742 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(bit2int(ass_cid_bit >> 5),
1743 bit2int(ass_cid_bit and4b '00011111'B)));
Pau Espin Pedrol096d73d2019-06-06 12:49:17 +02001744 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(cic, omit));
Harald Welteed848512018-05-24 22:27:58 +02001745 }
1746 return ass_cmd;
1747}
1748
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02001749function f_gen_handover_req(integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4",
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001750 template (value) BSSMAP_IE_CellIdentifier cell_id_source := ts_CellID_LAC_CI(1, 1),
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001751 template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit,
1752 template (omit) TestHdlrEncrParams enc := omit) return PDU_BSSAP {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001753 var PDU_BSSAP ho_req;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001754
1755 var BSSMAP_IE_EncryptionInformation encryptionInformation :=
1756 valueof(ts_BSSMAP_IE_EncrInfo('0000000000000000'O,'01'O));
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03001757 var template (omit) BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := omit;
1758 var template (omit) BSSMAP_IE_KC128 kc128 := omit;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001759 if (ispresent(enc)) {
1760 var TestHdlrEncrParams v_enc := valueof(enc);
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01001761 encryptionInformation := valueof(ts_BSSMAP_IE_EncrInfo(v_enc.enc_key, v_enc.enc_alg_permitted));
1762 if (ispresent(v_enc.enc_alg_chosen)) {
1763 chosenEncryptionAlgorithm := valueof(
1764 ts_BSSMAP_IE_ChosenEncryptionAlgorithm(int2oct(enum2int(
1765 f_cipher_mode_bssmap_to_rsl(v_enc.enc_alg_chosen)), 1)));
1766 }
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001767 if (ispresent(v_enc.enc_kc128)) {
1768 kc128 := ts_BSSMAP_IE_Kc128(v_enc.enc_kc128);
1769 }
1770 }
1771
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001772 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001773 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001774 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001775 ho_req := valueof(ts_BSSMAP_HandoverRequest(omit, tla,
1776 cell_id_source := cell_id_source,
1777 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001778 encryptionInformation := encryptionInformation,
1779 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
Neels Hofmeyr9fe13202022-03-04 00:05:43 +01001780 kC128 := kc128,
1781 /* on AoIP, allow "all" codecs (until we add more concise
1782 * tests) */
1783 codecList := ts_BSSMAP_IE_CodecList(
1784 {ts_CodecAMR_F, ts_CodecAMR_H,
1785 ts_CodecEFR, ts_CodecFR, ts_CodecHR})));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001786 } else {
1787 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001788 ho_req := valueof(ts_BSSMAP_HandoverRequest(cic, omit,
1789 cell_id_source := cell_id_source,
1790 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001791 encryptionInformation := encryptionInformation,
1792 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
1793 kC128 := kc128));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001794 }
1795 return ho_req;
1796}
1797
Harald Welteed848512018-05-24 22:27:58 +02001798/* generate an assignment complete template for either AoIP or SCCPlite */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001799function f_gen_exp_compl(integer bssap_idx := 0)
1800runs on MSC_ConnHdlr return template PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001801 var template PDU_BSSAP exp_compl;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001802 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001803 var template BSSMAP_IE_Osmo_OsmuxCID exp_osmux_cid := omit;
1804 if (g_pars.use_osmux_cn) {
1805 var template (present) INT1 exp_cid := ?;
1806 if (isbound(g_media.mgcp_conn[0].local_osmux_cid) and isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1807 exp_cid := (g_media.mgcp_conn[0].local_osmux_cid, g_media.mgcp_conn[1].local_osmux_cid);
1808 } else if (isbound(g_media.mgcp_conn[0].local_osmux_cid)) {
1809 exp_cid := g_media.mgcp_conn[0].local_osmux_cid;
1810 } else if (isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1811 exp_cid := g_media.mgcp_conn[1].local_osmux_cid;
1812 }
1813 exp_osmux_cid := tr_OsmuxCID(exp_cid);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001814 }
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001815 exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, exp_osmux_cid);
Harald Welteed848512018-05-24 22:27:58 +02001816 } else {
1817 /* CIC is optional "*" as the MSC allocated it */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001818 exp_compl := tr_BSSMAP_AssignmentComplete(*, omit, omit);
Harald Welteed848512018-05-24 22:27:58 +02001819 }
1820 return exp_compl;
1821}
1822
Harald Welte235ebf12017-12-15 14:18:16 +01001823/* Run everything required up to sending a caller-specified assignment command and expect response */
1824function f_assignment_exp(PDU_BSSAP ass_cmd, template PDU_BSSAP exp, charstring fail_text)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001825runs on test_CT return DchanTuple {
Harald Welte235ebf12017-12-15 14:18:16 +01001826 var BSSAP_N_CONNECT_ind rx_c_ind;
1827 var RSL_Message rx_rsl;
1828 var DchanTuple dt;
1829
Harald Welte89d42e82017-12-17 16:42:41 +01001830 f_init(1);
Harald Welte235ebf12017-12-15 14:18:16 +01001831
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001832 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte235ebf12017-12-15 14:18:16 +01001833 /* send assignment without AoIP IEs */
1834 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
1835 alt {
1836 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1837 if (ischosen(exp.pdu.bssmap.assignmentComplete)) {
1838 setverdict(pass);
1839 } else {
1840 setverdict(fail, fail_text);
1841 }
1842 }
1843 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1844 if (ischosen(exp.pdu.bssmap.assignmentFailure)) {
1845 setverdict(pass);
1846 } else {
1847 setverdict(fail, fail_text);
1848 }
1849 }
1850 [] BSSAP.receive { repeat; }
1851 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001852 return dt;
Harald Welte235ebf12017-12-15 14:18:16 +01001853}
Oliver Smithdd002752023-02-21 13:35:00 +01001854
Oliver Smith545492d2023-04-19 13:05:30 +02001855private function f_tc_assignment_csd(charstring data_rate_str, OCT1 data_rate, boolean transp := true) runs on MSC_ConnHdlr {
Oliver Smithdd002752023-02-21 13:35:00 +01001856 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welteed848512018-05-24 22:27:58 +02001857 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Oliver Smithbc392a82023-04-17 14:06:42 +02001858 var SDP_FIELD_PayloadType pt_csd := PT_CSD;
Oliver Smithdd002752023-02-21 13:35:00 +01001859
Harald Welte235ebf12017-12-15 14:18:16 +01001860 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smithdd002752023-02-21 13:35:00 +01001861 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecCSData}));
1862
Oliver Smith545492d2023-04-19 13:05:30 +02001863 /* Non-transparent service (3GPP TS 48.008 § 3.2.2.11, oct 5, bit 7) */
1864 if (not transp) {
1865 data_rate := data_rate or4b '40'O;
1866 }
1867
Oliver Smithcb617912023-04-18 11:29:10 +02001868 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := data_rate;
1869
1870 log("-----------------------------------------------");
1871 log("Assignment req with data rate: " & data_rate_str);
1872 log("-----------------------------------------------");
Oliver Smithdd002752023-02-21 13:35:00 +01001873
1874 f_establish_fully(ass_cmd, exp_compl);
Oliver Smithbc392a82023-04-17 14:06:42 +02001875
1876 if (g_media.bts.rtp_pt != enum2int(pt_csd)) {
1877 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("unexpected RTP payload type: ", g_media.bts.rtp_pt));
1878 }
1879
Oliver Smithdd002752023-02-21 13:35:00 +01001880 f_perform_clear();
Oliver Smithace447a2023-05-08 14:07:21 +02001881 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Oliver Smithdd002752023-02-21 13:35:00 +01001882}
Oliver Smithcb617912023-04-18 11:29:10 +02001883private function f_tc_assignment_csd_all(charstring id) runs on MSC_ConnHdlr {
1884 /* Data rates that require multi-slot HSCSD assignment are not tested
Oliver Smith545492d2023-04-19 13:05:30 +02001885 * on purpose (not supported): T_32k0, T_28k8, NT_43k5, NT_29k0 */
Oliver Smithcb617912023-04-18 11:29:10 +02001886 f_tc_assignment_csd("T_14k4", GSM0808_DATA_RATE_TRANSP_14k4);
1887 f_tc_assignment_csd("T_9k6", GSM0808_DATA_RATE_TRANSP_9k6);
1888 f_tc_assignment_csd("T_4k8", GSM0808_DATA_RATE_TRANSP_4k8);
1889 f_tc_assignment_csd("T_2k4", GSM0808_DATA_RATE_TRANSP_2k4);
1890 f_tc_assignment_csd("T_1k2", GSM0808_DATA_RATE_TRANSP_1k2);
1891 f_tc_assignment_csd("T_600", GSM0808_DATA_RATE_TRANSP_600);
1892 f_tc_assignment_csd("T_1200_75", GSM0808_DATA_RATE_TRANSP_1200_75);
Oliver Smith545492d2023-04-19 13:05:30 +02001893
1894 f_tc_assignment_csd("NT_12000_6000", GSM0808_DATA_RATE_NON_TRANSP_12000_6000, false);
1895 f_tc_assignment_csd("NT_14k5", GSM0808_DATA_RATE_NON_TRANSP_14k5, false);
1896 f_tc_assignment_csd("NT_12k0", GSM0808_DATA_RATE_NON_TRANSP_12k0, false);
1897 f_tc_assignment_csd("NT_6k0", GSM0808_DATA_RATE_NON_TRANSP_6k0, false);
Oliver Smithcb617912023-04-18 11:29:10 +02001898}
Oliver Smithdd002752023-02-21 13:35:00 +01001899testcase TC_assignment_csd() runs on test_CT {
Vadim Yanitskiy02c086f2023-09-22 15:32:41 +07001900 var MSC_ConnHdlr vc_conn;
1901 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Oliver Smithdd002752023-02-21 13:35:00 +01001902
Vadim Yanitskiy02c086f2023-09-22 15:32:41 +07001903 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
1904
1905 f_init(1, true, guard_timeout := 120.0);
1906 f_sleep(1.0);
1907 vc_conn := f_start_handler(refers(f_tc_assignment_csd_all), pars);
1908 vc_conn.done;
1909
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001910 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001911}
1912
1913testcase TC_assignment_ctm() runs on test_CT {
1914 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001915 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001916 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
1917 //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 +01001918 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
1919 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001920 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001921}
1922
Harald Welte4003d112017-12-09 22:35:39 +01001923type record DchanTuple {
1924 integer sccp_conn_id,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001925 RslChannelNr rsl_chan_nr,
1926 BtsTrxIdx idx
Harald Weltea5d2ab22017-12-09 14:21:42 +01001927}
1928
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +02001929type record of DchanTuple DchanTuples;
1930
Harald Welted6939652017-12-13 21:02:46 +01001931/* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001932private function f_chreq_act_ack(OCT1 ra := '23'O,
1933 GsmFrameNumber fn := 23,
1934 BtsTrxIdx idx := {0, 0})
Harald Welted6939652017-12-13 21:02:46 +01001935runs on test_CT return RslChannelNr {
1936 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001937 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
1938 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Harald Welted6939652017-12-13 21:02:46 +01001939 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001940 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10), idx);
1941 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Harald Welted6939652017-12-13 21:02:46 +01001942 return chan_nr;
1943}
1944
Harald Welte4003d112017-12-09 22:35:39 +01001945/* helper function to establish a dedicated channel via BTS and MSC */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001946function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1947 BtsTrxIdx idx := {0, 0})
Harald Welte4003d112017-12-09 22:35:39 +01001948runs on test_CT return DchanTuple {
1949 var BSSAP_N_CONNECT_ind rx_c_ind;
Harald Welte4003d112017-12-09 22:35:39 +01001950 var DchanTuple dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001951
Harald Welte4003d112017-12-09 22:35:39 +01001952 /* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001953 dt.rsl_chan_nr := f_chreq_act_ack(ra, fn, idx);
Harald Welte4003d112017-12-09 22:35:39 +01001954
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001955 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 +01001956
1957 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1958 dt.sccp_conn_id := rx_c_ind.connectionId;
1959 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1960
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001961 dt.idx := idx;
Harald Welte4003d112017-12-09 22:35:39 +01001962 return dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001963}
1964
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001965/* 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 +06001966function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1967 BtsTrxIdx idx := {0, 0})
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001968runs on test_CT return DchanTuple {
1969 var BSSAP_N_CONNECT_ind rx_c_ind;
1970 var DchanTuple dt;
1971
1972 /* Send CHAN RQD */
1973 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001974 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001975
1976 /* The dyn TS first deactivates PDCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001977 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 +02001978 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001979 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001980
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001981 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001982 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1983
1984 /* Now activates the signalling channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001985 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10), idx);
1986 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001987
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001988 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 +02001989
1990 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1991 dt.sccp_conn_id := rx_c_ind.connectionId;
1992 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1993
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001994 dt.idx := idx;
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001995 return dt;
1996}
1997
Harald Welte641fcbe2018-06-14 10:58:35 +02001998/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001999private function f_exp_chan_rel_and_clear(DchanTuple dt)
2000runs on test_CT {
Harald Welte641fcbe2018-06-14 10:58:35 +02002001 var RSL_Message rx_rsl;
2002 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002003 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 +02002004 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002005 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), dt.idx);
Harald Welte641fcbe2018-06-14 10:58:35 +02002006
2007 /* expect Clear Complete from BSC */
2008 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2009
2010 /* MSC disconnects as instructed. */
2011 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2012}
2013
Harald Welte4003d112017-12-09 22:35:39 +01002014/* Test behavior of channel release after unilateral RLL REL IND (DISC from MS) */
2015testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002016 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002017 var DchanTuple dt;
Harald Welte96c94412017-12-09 03:12:45 +01002018
Harald Welte89d42e82017-12-17 16:42:41 +01002019 f_init(1);
Harald Welte96c94412017-12-09 03:12:45 +01002020
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002021 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002022
2023 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002024 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Harald Welte4003d112017-12-09 22:35:39 +01002025
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002026 /* expect Clear Request on MSC side */
2027 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2028
2029 /* Instruct BSC to clear channel */
2030 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2031 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2032
Harald Welte4003d112017-12-09 22:35:39 +01002033 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002034 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002035
2036 /* wait for SCCP emulation to do its job */
2037 f_sleep(1.0);
Harald Welte4003d112017-12-09 22:35:39 +01002038
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002039 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002040}
2041
2042/* Test behavior of channel release after CONN FAIL IND from BTS */
2043testcase TC_chan_rel_conn_fail() runs on test_CT {
2044 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002045 var DchanTuple dt;
2046
Harald Welte89d42e82017-12-17 16:42:41 +01002047 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002048
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002049 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002050
Vadim Yanitskiy01d0a902022-12-14 22:41:42 +07002051 /* Sending CONN FAIL IND immediately may trigger a race condition.
2052 * Give the BSC some time to process a new SCCP connection (OS#5823). */
2053 f_sleep(0.2);
2054
Harald Welte4003d112017-12-09 22:35:39 +01002055 /* simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002056 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte4003d112017-12-09 22:35:39 +01002057 /* TODO: different cause values? */
2058
Harald Welte4003d112017-12-09 22:35:39 +01002059 /* expect Clear Request from BSC */
2060 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2061
2062 /* Instruct BSC to clear channel */
2063 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2064 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2065
Harald Welte6ff76ea2018-01-28 13:08:01 +01002066 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002067 f_exp_chan_rel_and_clear(dt);
Harald Welte4003d112017-12-09 22:35:39 +01002068
2069 /* wait for SCCP emulation to do its job */
2070 f_sleep(1.0);
2071
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002072 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002073}
2074
Harald Welte99f3ca02018-06-14 13:40:29 +02002075/* Test behavior of early CONN FAIL IND from BTS (before EST IND!) */
2076/* See also https://www.osmocom.org/issues/3182 */
2077testcase TC_early_conn_fail() runs on test_CT {
2078 var RSL_Message rx_rsl;
2079 var DchanTuple dt;
2080
2081 f_init(1);
2082
2083 /* BTS->BSC: Send CHAN RQD and wait for allocation; acknowledge it */
Harald Weltec46ea3c2020-10-10 18:46:12 +02002084 dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_ra_cs(), 23);
Harald Welte99f3ca02018-06-14 13:40:29 +02002085
2086 /* BTS->BSC: simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002087 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002088
2089 /* BTS->BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002090 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002091
2092 /* BTS<-BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002093 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002094
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002095 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002096}
2097
2098/* Test behavior of late CONN FAIL IND from BTS (ater REL IND!) */
2099/* See also https://www.osmocom.org/issues/3182 */
2100testcase TC_late_conn_fail() runs on test_CT {
2101 var RSL_Message rx_rsl;
2102 var DchanTuple dt;
2103
2104 f_init(1);
2105
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002106 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99f3ca02018-06-14 13:40:29 +02002107
2108 /* BSC<-MSC: Instruct BSC to clear connection */
2109 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(0)));
2110
2111 /* BTS->BSC: expect BSC to deactivate SACCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002112 rx_rsl := f_exp_ipa_rx(tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002113
2114 /* BTS->BSC: simulate a late CONN FAIL IND from BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002115 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002116
2117 /* BTS<-BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002118 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002119 /* BTS->BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002120 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002121
2122 /* BSC->MSC: expect Clear Complete from BSC */
2123 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2124
2125 /* BSC<-MSC: MSC disconnects as requested. */
2126 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2127
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002128 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002129}
2130
Oliver Smithaf03bef2021-08-24 15:34:51 +02002131private function f_TC_stats_conn_fail(charstring id) runs on MSC_ConnHdlr {
2132 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
2133 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2134
2135 f_statsd_reset();
2136
Oliver Smith15890b42023-03-08 14:12:28 +01002137 /* Establish SDCCH (invalid DataIndicator for exp_fail) */
Oliver Smithaf03bef2021-08-24 15:34:51 +02002138 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smith15890b42023-03-08 14:12:28 +01002139 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := 'ff'O;
Oliver Smithaf03bef2021-08-24 15:34:51 +02002140 f_establish_fully(ass_cmd, exp_fail);
2141
2142 /* Expect stats to be 0 */
2143 var StatsDExpects expect := {
2144 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
2145 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
2146 };
2147 f_statsd_expect(expect);
2148
2149 /* Simulate CONN FAIL IND on SDCCH */
2150 RSL.send(ts_ASP_RSL_UD(
2151 ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
2152 IPAC_PROTO_RSL_TRX0));
2153
Neels Hofmeyr58be48a2021-09-07 18:39:21 +02002154 f_sleep(1.0);
2155
Oliver Smithaf03bef2021-08-24 15:34:51 +02002156 /* Expect stats to be 1 */
2157 expect := {
2158 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
2159 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
2160 };
2161 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002162 BSSAP.receive(tr_BSSMAP_ClearRequest);
2163 f_perform_clear();
Oliver Smithaf03bef2021-08-24 15:34:51 +02002164}
2165testcase TC_stats_conn_fail() runs on test_CT {
2166 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2167 var MSC_ConnHdlr vc_conn;
2168
2169 f_init(1, true);
2170 f_sleep(1.0);
2171
2172 vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
2173 vc_conn.done;
2174
2175 f_shutdown_helper();
2176}
2177
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002178function f_expect_chan_rel(RslChannelNr rsl_chan_nr,
2179 BtsTrxIdx idx := {0, 0},
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002180 boolean expect_deact_sacch := true,
2181 boolean expect_rr_chan_rel := true,
2182 boolean expect_rll_rel_req := true,
Harald Welte99787102019-02-04 10:41:36 +01002183 boolean handle_rll_rel := true,
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002184 template CellSelIndValue expect_cells := omit,
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002185 template (present) RR_Cause expect_rr_cause := ?
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002186 ) runs on test_CT {
Harald Welte91d54a52018-01-28 15:35:07 +01002187
2188 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002189 var boolean got_deact_sacch := false;
2190 var boolean got_rr_chan_rel := false;
2191 var boolean got_rll_rel_req := false;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002192 var ASP_RSL_Unitdata ud;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002193 var RSL_IE_Body l3_ie;
2194 var PDU_ML3_NW_MS l3;
2195 var RR_Cause got_cause;
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002196 log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
2197 " expect_rll_rel_req=", expect_rll_rel_req);
Harald Welte91d54a52018-01-28 15:35:07 +01002198 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002199 [] 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 +01002200 got_deact_sacch := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002201 repeat;
2202 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002203 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_DATA_REQ(rsl_chan_nr, ?, decmatch tr_RRM_RR_RELEASE))) -> value ud {
Harald Welte99787102019-02-04 10:41:36 +01002204 got_rr_chan_rel := true;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002205
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002206 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2207 setverdict(fail, "cannot find L3");
2208 mtc.stop;
2209 }
2210 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2211
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002212 if (not istemplatekind(expect_cells, "omit")) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002213 var CellSelIndValue cells := dec_CellSelIndValue(
2214 l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
2215
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002216 log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
2217 if (match(cells, expect_cells)) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002218 setverdict(pass);
2219 } else {
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002220 log("EXPECTED CELLS: ", expect_cells);
2221 setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002222 }
2223 }
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002224
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002225 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2226 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2227 if (match(got_cause, expect_rr_cause)) {
2228 setverdict(pass);
2229 } else {
2230 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2231 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002232 }
Harald Welte99787102019-02-04 10:41:36 +01002233 repeat;
2234 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002235 [] 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 +01002236 got_rll_rel_req := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002237 /* FIXME: Why are we getting this for LinkID SACCH? */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002238 if (handle_rll_rel) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002239 f_ipa_tx(ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002240 }
Harald Welte91d54a52018-01-28 15:35:07 +01002241 repeat;
2242 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002243 [] 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 +01002244 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002245 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
Harald Welte91d54a52018-01-28 15:35:07 +01002246 }
2247 /* ignore any user data */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002248 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002249 repeat;
2250 }
2251 }
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002252
2253 log("f_expect_chan_rel() summary: got_deact_sacch=", got_deact_sacch, " got_rr_chan_rel=", got_rr_chan_rel,
2254 " got_rll_rel_req=", got_rll_rel_req);
2255
2256 if (expect_deact_sacch != got_deact_sacch) {
2257 setverdict(fail, "f_expect_chan_rel(): expect_deact_sacch=", expect_deact_sacch, " got_deact_sacch=", got_deact_sacch);
2258 }
2259 if (expect_rr_chan_rel != got_rr_chan_rel) {
2260 setverdict(fail, "f_expect_chan_rel(): expect_rr_chan_rel=", expect_rr_chan_rel, " got_rr_chan_rel=", got_rr_chan_rel);
2261 }
2262 if (expect_rll_rel_req != got_rll_rel_req) {
2263 setverdict(fail, "f_expect_chan_rel(): expect_rll_rel_req=", expect_rll_rel_req, " got_rll_rel_req=", got_rll_rel_req);
2264 }
Harald Welte91d54a52018-01-28 15:35:07 +01002265}
2266
Harald Welte4003d112017-12-09 22:35:39 +01002267/* Test behavior of channel release after hard Clear Command from MSC */
2268testcase TC_chan_rel_hard_clear() runs on test_CT {
2269 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002270 var DchanTuple dt;
Harald Welte4003d112017-12-09 22:35:39 +01002271
Harald Welte89d42e82017-12-17 16:42:41 +01002272 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002273
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002274 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002275
2276 /* Instruct BSC to clear channel */
2277 var BssmapCause cause := 0;
2278 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2279
2280 /* expect Clear Complete from BSC on A */
2281 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2282 /* release the SCCP connection */
2283 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2284 }
2285
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002286 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002287 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002288}
2289
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002290function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
2291 var BSSAP_N_DATA_ind rx_di;
2292 var DchanTuple dt;
2293
2294 f_init(1);
2295
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002296 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002297 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2298 /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
2299 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
2300
2301 /* Instruct BSC to clear channel */
2302 var BssmapCause cause := 0;
2303 if (tx_csfb_ind) {
2304 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2305 } else {
2306 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2307 }
2308
2309 /* expect Clear Complete from BSC on A */
2310 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2311 /* release the SCCP connection */
2312 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2313 }
2314
2315 /* 1 neighbor is added by default in osmo-bts.cfg and
2316 SystemInformationConfig_default, use that: */
2317 var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
2318
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002319 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 +02002320 f_shutdown_helper();
2321}
2322
2323/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
2324 from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
2325 PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2326 EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
2327 Indicator or not shouldn't matter at all. */
2328testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
2329 f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
2330}
2331
2332/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
2333 MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
2334 Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2335 EUTRAN neighbor list sent later on by BSC in RR Channel. */
2336testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
2337 f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
2338}
2339
2340/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
2341 MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
2342 Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
2343 CSFB Indicator should not be used anymore, and hence, there should be no
2344 EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
2345 Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
Harald Welte99787102019-02-04 10:41:36 +01002346testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
2347 var BSSAP_N_DATA_ind rx_di;
2348 var DchanTuple dt;
2349
2350 f_init(1);
2351
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002352 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99787102019-02-04 10:41:36 +01002353
2354 /* Instruct BSC to clear channel */
2355 var BssmapCause cause := 0;
2356 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2357
2358 /* expect Clear Complete from BSC on A */
2359 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2360 /* release the SCCP connection */
2361 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2362 }
2363
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002364 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002365 f_shutdown_helper();
Harald Welte99787102019-02-04 10:41:36 +01002366}
2367
Harald Welted8c36cd2017-12-09 23:05:31 +01002368/* Test behavior of channel release after hard RLSD from MSC */
2369testcase TC_chan_rel_hard_rlsd() runs on test_CT {
Harald Welted8c36cd2017-12-09 23:05:31 +01002370 var DchanTuple dt;
Harald Welted8c36cd2017-12-09 23:05:31 +01002371
Harald Welte89d42e82017-12-17 16:42:41 +01002372 f_init(1);
Harald Welted8c36cd2017-12-09 23:05:31 +01002373
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002374 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welted8c36cd2017-12-09 23:05:31 +01002375
2376 /* release the SCCP connection */
2377 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2378
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002379 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002380 f_shutdown_helper();
Harald Welted8c36cd2017-12-09 23:05:31 +01002381}
2382
Harald Welte550daf92018-06-11 19:22:13 +02002383/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
2384testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
2385 var DchanTuple dt;
2386
2387 f_init(1);
2388
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002389 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte550daf92018-06-11 19:22:13 +02002390
2391 /* release the SCCP connection */
2392 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2393
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();
Harald Welte550daf92018-06-11 19:22:13 +02002396}
2397
Harald Welte85804d42017-12-10 14:11:58 +01002398/* Test behavior of channel release after BSSMAP RESET from MSC */
2399testcase TC_chan_rel_a_reset() runs on test_CT {
Harald Welte85804d42017-12-10 14:11:58 +01002400 var DchanTuple dt;
Harald Welte85804d42017-12-10 14:11:58 +01002401
Harald Welte89d42e82017-12-17 16:42:41 +01002402 f_init(1);
Harald Welte85804d42017-12-10 14:11:58 +01002403
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002404 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte85804d42017-12-10 14:11:58 +01002405
2406 /* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002407 IPA_RSL[0][0].clear;
Harald Welte85804d42017-12-10 14:11:58 +01002408
2409 /* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002410 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 +01002411 interleave {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002412 [] 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 +01002413 [] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
2414 }
2415
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002416 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002417 f_shutdown_helper();
Harald Welte85804d42017-12-10 14:11:58 +01002418}
2419
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002420/* Verify T(iar) triggers and releases the channel */
2421testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
2422 var DchanTuple dt;
2423
2424 /* Set T(iar) in BSC low enough that it will trigger before other side
2425 has time to keep alive with a T(ias). Keep recommended ratio of
2426 T(iar) >= T(ias)*2 */
2427 g_bsc_sccp_timer_ias := 2;
2428 g_bsc_sccp_timer_iar := 5;
2429
2430 f_init(1);
2431
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002432 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002433 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002434 f_shutdown_helper();
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002435}
2436
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002437private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause,
2438 template (present) RR_Cause expect_rr_cause)
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002439runs on test_CT
2440{
2441 var DchanTuple dt;
2442
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002443 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002444 var BssmapCause cause := 0;
2445 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
2446 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2447 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2448 }
2449
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002450 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 +02002451}
2452
2453/* Test that Clear Command cause codes affect the RR Channel Release cause code */
2454testcase TC_chan_rel_rr_cause() runs on test_CT {
2455 f_init(1);
2456
2457 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
2458 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
2459 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
2460 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
2461 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
2462 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
Vadim Yanitskiye18aebb2021-01-03 13:10:43 +01002463
2464 f_shutdown_helper();
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002465}
2466
Harald Welte5cd20ed2017-12-13 21:03:20 +01002467/* Test behavior if RSL EST IND for non-active channel */
2468testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
2469 timer T := 2.0;
2470
Harald Welte89d42e82017-12-17 16:42:41 +01002471 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002472
Harald Welte5cd20ed2017-12-13 21:03:20 +01002473 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002474 var octetstring l3_payload := gen_l3_valid_payload();
2475 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002476
2477 T.start;
2478 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002479 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002480 setverdict(fail, "MSC received COMPL L3 for non-active lchan");
2481 }
2482 [] BSSAP.receive {}
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002483 [] IPA_RSL[0][0].receive {}
Harald Welte5cd20ed2017-12-13 21:03:20 +01002484 [] T.timeout {}
2485 }
2486
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002487 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002488}
2489
2490/* Test behavior if RSL EST IND for invalid SAPI */
2491testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
2492 var RslChannelNr chan_nr;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002493 var octetstring l3_payload;
Harald Welte5cd20ed2017-12-13 21:03:20 +01002494
Harald Welte89d42e82017-12-17 16:42:41 +01002495 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002496
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002497 chan_nr := f_chreq_act_ack();
2498 l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002499
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002500 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002501
2502 timer T := 2.0;
2503 T.start;
2504 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002505 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002506 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
2507 }
2508 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002509 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002510 [] T.timeout {}
2511 }
2512
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002513 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002514}
2515
2516/* Test behavior if RSL EST IND for invalid SAPI */
2517testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
2518 timer T := 2.0;
2519
Harald Welte89d42e82017-12-17 16:42:41 +01002520 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002521
2522 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002523 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002524
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002525 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002526
2527 T.start;
2528 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002529 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002530 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
2531 }
2532 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002533 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002534 [] T.timeout {}
2535 }
2536
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002537 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002538}
2539
2540/* Test behavior if RSL EST IND for invalid SACCH */
2541testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
2542 timer T := 2.0;
2543
Harald Welte89d42e82017-12-17 16:42:41 +01002544 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002545
2546 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002547 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002548
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002549 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002550
2551 T.start;
2552 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002553 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002554 setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
2555 }
2556 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002557 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002558 [] T.timeout {}
2559 }
2560
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002561 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002562}
2563
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002564/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
2565private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
2566 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
2567 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2568
2569 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
2570 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
2571
2572 f_establish_fully(ass_cmd, exp_compl);
2573
2574 /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
2575 RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
2576 /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
2577 BSSAP.receive(PDU_BSSAP:{
2578 discriminator := '1'B,
2579 spare := '0000000'B,
2580 dlci := 'C3'O,
2581 lengthIndicator := ?,
2582 pdu := { dtap := '0904'O }
2583 });
2584
2585 /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
2586 for (var integer i := 0; i < 32; i := i + 1) {
2587 var octetstring l3 := '09'O & f_rnd_octstring(14);
2588 var template (value) RslLinkId link_id;
2589 var template (value) OCT1 dlci;
2590
2591 if (i mod 2 == 0) {
2592 /* SAPI0 on FACCH or SDCCH */
2593 link_id := ts_RslLinkID_DCCH(0);
2594 dlci := '80'O;
2595 } else {
2596 /* SAPI3 on SACCH */
2597 link_id := ts_RslLinkID_SACCH(3);
2598 dlci := 'C3'O;
2599 }
2600
2601 /* Send MO message: RSL -> BSSAP */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002602 f_mo_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002603 /* Send MT message: BSSAP -> RSL */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002604 f_mt_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002605 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002606 f_perform_clear();
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002607}
2608testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
2609 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2610 var MSC_ConnHdlr vc_conn;
2611
2612 f_init(1, true);
2613 f_sleep(1.0);
2614
2615 vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
2616 vc_conn.done;
2617
2618 f_shutdown_helper();
2619}
2620
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002621private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002622 template (present) myBSSMAP_Cause cause := ?,
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002623 template (present) BIT2 cc := ?,
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002624 float T_val := 2.0)
2625runs on test_CT {
2626 var BSSAP_N_DATA_ind rx_di;
2627 timer T;
2628
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002629 var template (present) BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
2630 var template (present) PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002631
2632 T.start(T_val);
2633 alt {
2634 [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
2635 var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
2636 if (not match(rx_cause, tr_cause)) {
2637 setverdict(fail, "Rx unexpected Cause IE: ",
2638 rx_cause, " vs expected ", tr_cause);
2639 }
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002640
2641 /* Who ever on the earth decided to define this field as two separate bits?!? */
2642 var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
2643 & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
2644 if (not match(rx_cc, cc)) {
2645 setverdict(fail, "Rx unexpected Control Channel type: ",
2646 rx_cc, " vs expected ", cc);
2647 }
2648
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002649 setverdict(pass);
2650 }
2651 [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
2652 setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
2653 }
2654 [] T.timeout {
2655 setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
2656 }
2657 }
2658}
2659
2660/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
2661testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002662 var RSL_Message rx_rsl;
2663 var DchanTuple dt;
2664
2665 f_init(1);
2666
2667 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002668 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002669
2670 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002671 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 +07002672 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002673 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 +07002674
2675 /* MS sends unexpected RELease INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002676 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002677 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2678 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
2679
2680 /* Clean up the connection */
2681 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002682 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002683
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002684 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002685}
2686
2687/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
2688testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002689 var RSL_Message rx_rsl;
2690 var DchanTuple dt;
2691
2692 f_init(1);
2693
2694 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002695 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002696
2697 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002698 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 +07002699 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002700 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 +07002701
2702 /* BTS sends unexpected ERROR INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002703 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002704 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2705 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
2706
2707 /* Clean up the connection */
2708 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002709 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002710
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002711 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002712}
2713
2714/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
2715testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002716 var RSL_Message rx_rsl;
2717 var DchanTuple dt;
2718
2719 f_init(1);
2720
2721 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002722 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002723
2724 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002725 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 +07002726 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002727 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 +07002728
2729 /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
2730 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
2731
2732 /* Clean up the connection */
2733 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002734 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002735
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002736 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002737}
2738
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002739/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
2740testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002741 var RSL_Message rx_rsl;
2742 var DchanTuple dt;
2743
2744 f_init(1);
2745
2746 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002747 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002748
2749 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002750 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 +07002751 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002752 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 +07002753
2754 /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002755 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Pau Espin Pedrol121f27f2022-01-12 12:02:10 +01002756 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, '10'B);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002757
2758 /* Clean up the connection */
2759 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002760 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002761
2762 f_shutdown_helper();
2763}
2764
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002765testcase TC_si_default() runs on test_CT {
2766 f_init(0);
2767 f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002768 f_shutdown_helper();
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002769}
Harald Welte4003d112017-12-09 22:35:39 +01002770
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002771/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
2772 * the entire value range. This function provides the same EARFCN numbers for the same earfcn_index */
2773private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uint16_t
2774{
2775 select (earfcn_index) {
2776 case (0) {
2777 /* E-ARFCN 111 is already added in the osmo-bsc.cfg */
2778 return 111;
2779 }
2780 case (1) {
2781 return 1;
2782 }
2783 case (2) {
2784 return 0;
2785 }
2786 case (3) {
2787 return 65535;
2788 }
2789 case else {
2790 return 23 * (earfcn_index - 3);
2791 }
2792 }
2793}
2794
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002795function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
2796 template CellSelIndValue expect_cells := omit) runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002797
2798 f_init(0);
2799
2800 /* E-ARFCN 111 is already added in the osmo-bsc.cfg, so only add more arfcns if total_earfcns > 1 */
2801 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002802 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2803 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002804 }
2805
2806 f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
2807
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002808 if (not istemplatekind(expect_cells, "omit")) {
2809 /* Also check that RR Channel Release contains these EARFCNs.
2810 * (copied code from TC_chan_rel_hard_clear_csfb) */
2811 var BSSAP_N_DATA_ind rx_di;
2812 var DchanTuple dt;
2813
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002814 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrold0046312021-04-19 16:35:58 +02002815 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2816 * yet when generating the EUTRAN neigh list in RR CHannel Release) */
2817 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002818
2819 /* Instruct BSC to clear channel */
2820 var BssmapCause cause := 0;
2821 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2822
2823 /* expect Clear Complete from BSC on A */
2824 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2825 /* release the SCCP connection */
2826 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2827 }
2828
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002829 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := expect_cells);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002830 }
2831
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002832 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002833 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 +02002834 }
2835}
2836
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002837private function f_tr_si2quater_earfcns(integer count) return template SI2quaterRestOctetsList
2838{
2839 var template SI2quaterRestOctetsList si2quater := {};
2840 var integer si2quater_count := (count + 2) / 3;
2841
2842 for (var integer i := 0; i < count; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002843 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002844 var integer index := i / 3;
2845 var integer earfcn_index := i mod 3;
2846 if (index >= lengthof(si2quater)) {
2847 si2quater[index] := tr_SI2quaterRestOctets_EUTRAN(index := index, count := si2quater_count - 1);
2848 }
2849 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);
2850 }
2851
2852 return si2quater;
2853}
2854
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002855private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
2856{
2857 var template CellSelIndValue_EUTRAN_Descrs cells := {};
2858
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002859 /* the lte neighbors must match the config & vty to pass this test */
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002860 for (var integer i := 0; i < count; i := i + 1) {
2861 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002862 cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002863 }
2864
2865 return tr_CellSelIndValue_EUTRAN(cells);
2866}
2867
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002868private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
2869{
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002870 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrol8ab62e42020-12-18 16:19:11 +01002871 sic.si2quater := f_tr_si2quater_earfcns(n);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002872 var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
2873 f_test_si2quater(n, sic, cells);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002874}
2875
2876testcase TC_si2quater_2_earfcns() runs on test_CT {
2877 f_tc_si2quater_n_earfcns(2);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002878 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002879}
2880
2881testcase TC_si2quater_3_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002882 f_tc_si2quater_n_earfcns(3);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002883 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002884}
2885
2886testcase TC_si2quater_4_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002887 f_tc_si2quater_n_earfcns(4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002888 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002889}
2890
2891testcase TC_si2quater_5_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002892 f_tc_si2quater_n_earfcns(5);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002893 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002894}
2895
2896testcase TC_si2quater_6_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002897 f_tc_si2quater_n_earfcns(6);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002898 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002899}
2900
2901testcase TC_si2quater_12_earfcns() runs on test_CT {
2902 f_tc_si2quater_n_earfcns(12);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002903 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002904}
2905
2906testcase TC_si2quater_23_earfcns() runs on test_CT {
2907 f_tc_si2quater_n_earfcns(23);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002908 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002909}
2910
2911testcase TC_si2quater_32_earfcns() runs on test_CT {
2912 f_tc_si2quater_n_earfcns(32);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002913 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002914}
2915
2916testcase TC_si2quater_33_earfcns() runs on test_CT {
2917 f_tc_si2quater_n_earfcns(33);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002918 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002919}
2920
2921testcase TC_si2quater_42_earfcns() runs on test_CT {
2922 f_tc_si2quater_n_earfcns(42);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002923 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002924}
2925
2926testcase TC_si2quater_48_earfcns() runs on test_CT {
2927 f_tc_si2quater_n_earfcns(48);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002928 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002929}
2930
2931/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
2932 * 48 EARFCNs. */
2933testcase TC_si2quater_49_earfcns() runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002934 var template SystemInformationConfig sic := SystemInformationConfig_default;
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002935 sic.si2quater := f_tr_si2quater_earfcns(48); /* 48, not 49! */
2936 f_init(0);
2937
2938 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002939 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2940 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002941 }
2942
2943 /* The 49th EARFCN no longer fits, expect VTY error */
2944 f_vty_enter_cfg_bts(BSCVTY, 0);
2945 var charstring vty_error;
2946 vty_error := f_vty_transceive_ret(BSCVTY,
2947 "si2quater neighbor-list add earfcn 70 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3")
2948 f_vty_transceive(BSCVTY, "end");
2949
2950 if (f_strstr(vty_error, "Unable to add ARFCN 70") >= 0) {
2951 log("Got expected VTY error: ", vty_error);
2952 setverdict(pass);
2953 } else {
2954 setverdict(fail, "Expected the 49th EUTRAN ARFCN to be rejected by vty config, got: ", vty_error);
2955 }
2956
2957 f_init_bts_and_check_sysinfo(0, expect_si := sic);
2958
2959 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002960 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 +02002961 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002962 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002963}
2964
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002965private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
2966{
2967 var uint8_t count := 0;
2968 for (var integer i := 5; i < 16; i := i + 1) {
2969 if (acc[i] == '0'B) { /* the list marks barred, we count allowed */
2970 count := count + 1;
2971 }
2972 }
2973 return count;
2974}
2975
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002976private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return SystemInformationType1
2977{
2978 var ASP_RSL_Unitdata rx_rsl_ud;
2979 var SystemInformationType1 last_si1;
2980
2981 timer T := 30.0;
2982 T.start;
2983 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002984 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
2985 tr_RSL_BCCH_INFO,
2986 tr_RSL_NO_SACCH_FILL,
2987 tr_RSL_SACCH_FILL))) -> value rx_rsl_ud {
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002988 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
2989 if (g_system_information[rsl_idx].si1 == omit) {
2990 repeat;
2991 }
2992 last_si1 := g_system_information[rsl_idx].si1;
2993 g_system_information[rsl_idx].si1 := omit;
2994 T.stop;
2995 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002996 [] IPA_RSL[rsl_idx][0].receive { repeat; }
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002997 [] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
2998 }
2999 return last_si1;
3000}
3001
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003002/* verify ACC rotate feature */
3003testcase TC_si_acc_rotate() runs on test_CT {
3004 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003005 var SystemInformationType1 last_si1;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003006 var AccessControlClass acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003007 var uint8_t count;
3008 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3009
3010 f_init(0, guard_timeout := 60.0);
3011
3012 f_bts_0_cfg(BSCVTY, {"rach access-control-class 5 barred",
3013 "access-control-class-rotate 3",
3014 "access-control-class-rotate-quantum 1"});
3015
3016 /* Init and get first sysinfo */
3017 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3018
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003019 for (var integer i:= 0; i < 20; i := i + 1) {
3020 last_si1 := f_recv_next_si1(0);
3021 acc := last_si1.rach_control.acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003022 count := f_acc09_count_allowed(acc);
3023 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3024
3025 if (count != 3) {
3026 log("RSL: EXPECTED SI ACC len=3");
3027 setverdict(fail, "received SI does not match expectations");
3028 break;
3029 }
3030
3031 for (var integer j := 0; j < 10; j := j + 1) {
3032 if (acc[16 - 1 - j] == '0'B) { /* the list marks barred, we count allowed */
3033 times_allowed[j] := times_allowed[j] + 1;
3034 }
3035 }
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003036 }
3037
3038 for (var integer j := 0; j < 10; j := j + 1) {
3039 log("ACC", j, " allowed ", times_allowed[j], " times" );
3040 if (j != 5 and times_allowed[j] < 3) {
3041 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " < 1 times");
3042 } else if (j == 5 and times_allowed[j] > 0) {
3043 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " > 0 times");
3044 }
3045 }
3046
3047 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3048 "rach access-control-class 5 allowed"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003049 f_shutdown_helper();
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003050}
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02003051
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003052/* verify ACC startup ramp+rotate feature */
3053testcase TC_si_acc_ramp_rotate() runs on test_CT {
3054 var template SystemInformationConfig sic := SystemInformationConfig_default;
3055 var SystemInformationType1 last_si1;
3056 var AccessControlClass acc;
3057 var ASP_RSL_Unitdata rx_rsl_ud;
3058 var uint8_t count;
3059 var uint8_t prev_count;
3060 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3061
3062 f_init(0, guard_timeout := 80.0);
3063
3064 f_bts_0_cfg(BSCVTY, {"rach access-control-class 4 barred",
3065 "access-control-class-rotate 0",
3066 "access-control-class-rotate-quantum 1",
3067 "access-control-class-ramping",
3068 "access-control-class-ramping-step-interval 5",
3069 "access-control-class-ramping-step-size 5"});
3070
3071 /* Init and get first sysinfo */
3072 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3073 last_si1 := g_system_information[0].si1;
3074 acc := last_si1.rach_control.acc;
3075 count := f_acc09_count_allowed(acc);
3076 /* Adm subset size was set to 0 above, so wait until all ACC are barred */
3077 while (count > 0) {
3078 last_si1 := f_recv_next_si1(0);
3079 acc := last_si1.rach_control.acc;
3080 count := f_acc09_count_allowed(acc);
3081 log("RSL: wait len()=0: GOT SI1 ACC len=", count, ": ", acc);
3082 }
3083
3084 /* Increase adm subset size, we should see ramping start up */
3085 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10"});
3086 prev_count := 0;
3087 while (true) {
3088 last_si1 := f_recv_next_si1(0);
3089 acc := last_si1.rach_control.acc;
3090 count := f_acc09_count_allowed(acc);
3091 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3092
3093 if (prev_count > count) {
3094 setverdict(fail, "ACC allowed count dropped while expecting grow: ", prev_count, " -> ", count);
3095 break;
3096 }
3097
3098 if (count == 9) {
3099 break; /* Maximum reached (10 - 1 perm barred), done here */
3100 }
3101
3102 prev_count := count;
3103 }
3104
3105 setverdict(pass);
3106
3107 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3108 "rach access-control-class 4 allowed",
3109 "no access-control-class-ramping"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003110 f_shutdown_helper();
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003111}
3112
Oliver Smith45a6dd32023-09-27 10:52:50 +02003113/* Verify NCC Permitted in System Information Type 2
3114 * 3GPP TS 44.018 § 10.5.2.27 */
3115testcase TC_si2_ncc_permitted() runs on test_CT {
3116 var ASP_RSL_Unitdata rx_rsl_ud;
3117 timer T := 5.0;
3118 var BIT8 exp;
3119
3120 f_init_vty();
3121
3122 /* Set NCC Permitted to 6 7 8 */
3123 f_vty_enter_cfg_bts(BSCVTY, 0);
3124 f_vty_transceive(BSCVTY, "ncc-permitted 6 7 8");
3125 f_vty_transceive(BSCVTY, "end");
3126 exp := '11100000'B;
3127
3128 f_init(1);
3129 T.start;
3130
3131 /* Check value in SI 2 */
3132 alt {
3133 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO(RSL_SYSTEM_INFO_2))) -> value rx_rsl_ud {
3134 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
3135 var SystemInformation si := dec_SystemInformation(ie.other.payload);
3136
3137 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_2) {
3138 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
3139 repeat;
3140 }
3141
3142 if (si.payload.si2.ncc_permitted != exp) {
3143 setverdict(fail, "NCC Permitted is ", si.payload.si2.ncc_permitted, " but expected ", exp);
3144 break;
3145 }
3146
3147 }
3148 [] IPA_RSL[0][0].receive { repeat; }
3149 [] T.timeout {
3150 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI2)");
3151 }
3152 }
3153
3154 /* Reset NCC Permitted to default (all permitted). This is already
3155 * getting tested in TC_si_default(). */
3156 f_vty_enter_cfg_bts(BSCVTY, 0);
3157 f_vty_transceive(BSCVTY, "ncc-permitted all");
3158 f_vty_transceive(BSCVTY, "end");
3159
3160 f_shutdown_helper();
3161}
3162
Harald Welte4003d112017-12-09 22:35:39 +01003163testcase TC_ctrl_msc_connection_status() runs on test_CT {
3164 var charstring ctrl_resp;
3165
Harald Welte89d42e82017-12-17 16:42:41 +01003166 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003167
3168 /* See https://osmocom.org/issues/2729 */
3169 f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003170 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01003171}
3172
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003173testcase TC_ctrl_msc0_connection_status() runs on test_CT {
3174 var charstring ctrl_resp;
3175
3176 f_init(1);
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003177
3178 f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003179 f_shutdown_helper();
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003180}
3181
Neels Hofmeyr0bc470d2021-08-21 13:37:13 +02003182/* Verify correct stats on the number of configured and connected MSCs */
3183private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
3184 g_pars := f_gen_test_hdlr_pars();
3185 var StatsDExpects expect := {
3186 { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
3187 { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
3188 };
3189 f_statsd_expect(expect);
3190}
3191
3192private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
3193{
3194 var MSC_ConnHdlr vc_conn;
3195
3196 f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
3197 f_sleep(1.0);
3198 vc_conn := f_start_handler(tc_fn);
3199 vc_conn.done;
3200
3201 /* Also verify stat exposed on CTRL interface */
3202 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
3203 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
3204
3205 f_shutdown_helper();
3206}
3207
3208/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
3209private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
3210 f_tc_stat_num_msc_connected_msc_connhdlr(1);
3211}
3212testcase TC_stat_num_msc_connected_1() runs on test_CT {
3213 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
3214}
3215
3216/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
3217private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
3218 f_tc_stat_num_msc_connected_msc_connhdlr(2);
3219}
3220testcase TC_stat_num_msc_connected_2() runs on test_CT {
3221 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
3222}
3223
3224/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
3225private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
3226 f_tc_stat_num_msc_connected_msc_connhdlr(3);
3227}
3228testcase TC_stat_num_msc_connected_3() runs on test_CT {
3229 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
3230}
3231
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003232/* Verify correct stats on the number of configured and connected MSCs */
3233private 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 +06003234 var integer num_trx_connected := 0;
3235 var integer num_trx_total := 0;
3236
3237 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3238 var integer trx_num := c_BtsParams[i].trx_num;
3239 num_trx_total := num_trx_total + trx_num;
3240 if (i < expect_num_bts_connected) {
3241 num_trx_connected := num_trx_connected + trx_num;
3242 }
3243 }
3244
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003245 var StatsDExpects expect := {
3246 { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
3247 { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3248 { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003249 { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := num_trx_connected, max := num_trx_connected },
3250 { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := num_trx_total, max := num_trx_total }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003251 };
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003252
3253 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003254 f_statsd_expect(expect);
3255}
3256
3257private 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 +06003258 var integer num_trx_connected := 0;
3259 var integer num_trx_total := 0;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003260 var MSC_ConnHdlr vc_conn;
3261
3262 f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
3263 f_sleep(1.0);
3264 vc_conn := f_start_handler(tc_fn);
3265 vc_conn.done;
3266
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003267 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3268 var integer trx_num := c_BtsParams[i].trx_num;
3269 num_trx_total := num_trx_total + trx_num;
3270 if (i < nr_bts) {
3271 num_trx_connected := num_trx_connected + trx_num;
3272 }
3273 }
3274
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003275 /* Also verify stat exposed on CTRL interface */
3276 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
3277 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 +06003278 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(num_trx_connected));
3279 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 +02003280
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003281 /* Verify rf_states exposed on CTRL interface */
3282 var charstring expect_net_rf_states := "";
3283 for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003284 var charstring expect_bts_rf_states := "";
3285
3286 for (var integer j := 0; j < c_BtsParams[i].trx_num; j := j + 1) {
3287 expect_bts_rf_states := expect_bts_rf_states &
3288 int2str(i) & "," & int2str(j) & ",";
3289 if (i < NUM_BTS) {
3290 /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
3291 expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
3292 } else {
3293 /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
3294 expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
3295 }
3296 /* The RF policy is still global in osmo-bsc, i.e. always "on" */
3297 expect_bts_rf_states := expect_bts_rf_states & "on,";
3298 if (i < nr_bts) {
3299 /* For BTS where RSL is connected, the RSL state will be "up" */
3300 expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
3301 } else {
3302 expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
3303 }
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003304 }
3305
3306 f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
3307 expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
3308 }
3309 f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
3310
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003311 f_shutdown_helper();
3312}
3313
3314/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
3315private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
3316 f_tc_stat_num_bts_connected_msc_connhdlr(1);
3317}
3318testcase TC_stat_num_bts_connected_1() runs on test_CT {
3319 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
3320}
3321
3322/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
3323private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
3324 f_tc_stat_num_bts_connected_msc_connhdlr(2);
3325}
3326testcase TC_stat_num_bts_connected_2() runs on test_CT {
3327 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
3328}
3329
3330/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
3331private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
3332 f_tc_stat_num_bts_connected_msc_connhdlr(3);
3333}
3334testcase TC_stat_num_bts_connected_3() runs on test_CT {
3335 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
3336}
3337
Harald Welte4003d112017-12-09 22:35:39 +01003338testcase TC_ctrl() runs on test_CT {
3339 var charstring ctrl_resp;
3340
Harald Welte89d42e82017-12-17 16:42:41 +01003341 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003342
3343 /* all below values must match the osmo-bsc.cfg config file used */
3344
Harald Welte6a129692018-03-17 17:30:14 +01003345 f_ctrl_get_exp(IPA_CTRL, "mcc", "001");
3346 f_ctrl_get_exp(IPA_CTRL, "mnc", "01");
Oliver Smith75aa0202019-08-19 14:17:50 +02003347 f_ctrl_get_exp(IPA_CTRL, "number-of-bts", "4");
Harald Welte4003d112017-12-09 22:35:39 +01003348
3349 var integer bts_nr := 0;
3350 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "location-area-code", "1");
3351 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "cell-identity", "0");
3352 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "oml-connection-state", "connected");
3353 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "gprs-mode", "gprs");
3354 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "rf_state", "operational,unlocked,on");
3355 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "arfcn", "871");
3356 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "max-power-reduction", "20");
3357
3358 var integer uptime := str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime"));
3359 f_sleep(2.0);
3360 if (str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime")) < uptime+1) {
3361 setverdict(fail, "oml-uptime not incrementing as expected");
3362 }
3363 /* TODO: Disconnect RSL, imply that OML is disconnected and check for uptime zero? */
3364
3365 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
3366
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003367 f_shutdown_helper();
Harald Welte96c94412017-12-09 03:12:45 +01003368}
3369
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003370/* Verify that Upon receival of SET "location", BSC forwards a TRAP
3371 "location-state" over the SCCPlite IPA conn */
3372testcase TC_ctrl_location() runs on test_CT {
3373 var MSC_ConnHdlr vc_conn;
3374 var integer bts_nr := 0;
3375
3376 f_init(1, true);
3377 f_sleep(1.0);
3378
3379 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234567,fix3d,0.340000,0.560000,0.780000");
3380 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3381 "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
3382
3383 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "1");
3384 f_sleep(2.0);
3385
3386 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234888,fix3d,0.350000,0.570000,0.790000");
3387 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3388 "1234888,fix3d,0.350000,0.570000,0.790000,operational,locked,off,001,01");
3389
3390 /* should match the one from config */
3391 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
3392
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003393 f_shutdown_helper();
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003394}
3395
Harald Welte6f521d82017-12-11 19:52:02 +01003396
3397/***********************************************************************
3398 * Paging Testing
3399 ***********************************************************************/
3400
3401type record Cell_Identity {
3402 GsmMcc mcc,
3403 GsmMnc mnc,
3404 GsmLac lac,
3405 GsmCellId ci
3406};
Harald Welte24135bd2018-03-17 19:27:53 +01003407private const Cell_Identity cid := { '001'H, '01'H, 1, 0 };
Stefan Sperling049a86e2018-03-20 15:51:00 +01003408private const Cell_Identity unknown_cid := { '678'H, 'f90'H, 1, 0 };
Harald Welte6f521d82017-12-11 19:52:02 +01003409
Harald Welte5d1a2202017-12-13 19:51:29 +01003410type set of integer BtsIdList;
3411
3412private function f_bts_in_list(integer bts_id, BtsIdList bts_ids) return boolean {
3413 for (var integer j := 0; j < sizeof(bts_ids); j := j + 1) {
3414 if (bts_id == bts_ids[j]) {
3415 return true;
3416 }
3417 }
3418 return false;
3419}
Harald Welte6f521d82017-12-11 19:52:02 +01003420
3421/* core paging test helper function; used by most paging test cases */
3422private function f_pageing_helper(hexstring imsi,
3423 template BSSMAP_FIELD_CellIdentificationList cid_list,
Harald Welte5d1a2202017-12-13 19:51:29 +01003424 BtsIdList bts_ids := { 0 },
Harald Welte6f521d82017-12-11 19:52:02 +01003425 template RSL_ChanNeeded rsl_chneed := omit,
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003426 template (omit) OCT4 tmsi := omit) runs on test_CT
Harald Welte6f521d82017-12-11 19:52:02 +01003427{
3428 var template BSSMAP_IE_ChannelNeeded bssmap_chneed;
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003429 var template MobileIdentityV mi;
Harald Welte6f521d82017-12-11 19:52:02 +01003430 var RSL_Message rx_rsl;
3431 var integer paging_group := hex2int(imsi[lengthof(imsi)-1]);
Harald Welte5d1a2202017-12-13 19:51:29 +01003432 var integer i;
Harald Welte6f521d82017-12-11 19:52:02 +01003433
3434 f_init();
Harald Welte6f521d82017-12-11 19:52:02 +01003435
3436 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Harald Weltec3068592018-03-17 19:55:31 +01003437 for (i := 0; i < NUM_BTS; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003438 IPA_RSL[i][0].clear;
Harald Welte5d1a2202017-12-13 19:51:29 +01003439 }
Harald Welte6f521d82017-12-11 19:52:02 +01003440
3441 if (isvalue(rsl_chneed)) {
3442 /* The values of 08.08 3.2.2.36 and 08.58 9.3.40 are luckily identical */
3443 bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
3444 } else {
3445 bssmap_chneed := omit;
3446 }
3447
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003448 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
3449 ts_BSSMAP_Paging(imsi, cid_list, tmsi, bssmap_chneed)));
Harald Welte6f521d82017-12-11 19:52:02 +01003450
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003451 if (not istemplatekind(tmsi, "omit")) {
3452 mi := t_MI_TMSI(tmsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003453 } else {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003454 mi := tr_MI_IMSI(imsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003455 }
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003456
Harald Welte5d1a2202017-12-13 19:51:29 +01003457 for (i := 0; i < sizeof(bts_ids); i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003458 rx_rsl := f_exp_ipa_rx(tr_RSL_PAGING_CMD(mi), idx := {bts_ids[i], 0});
Harald Welte5d1a2202017-12-13 19:51:29 +01003459 /* check channel type, paging group */
3460 if (rx_rsl.ies[1].body.paging_group != paging_group) {
3461 setverdict(fail, "Paging for wrong paging group");
3462 }
3463 if (ispresent(rsl_chneed) and
3464 rx_rsl.ies[3].body.chan_needed.chan_needed != valueof(rsl_chneed)) {
3465 setverdict(fail, "RSL Channel Needed != BSSMAP Channel Needed");
3466 }
Harald Welte6f521d82017-12-11 19:52:02 +01003467 }
Harald Welte2fccd982018-01-31 15:48:19 +01003468 f_sleep(2.0);
Harald Welte5d1a2202017-12-13 19:51:29 +01003469 /* do a quick check on all not-included BTSs if they received paging */
3470 for (i := 0; i < NUM_BTS; i := i + 1) {
3471 timer T := 0.1;
3472 if (f_bts_in_list(i, bts_ids)) {
3473 continue;
3474 }
3475 T.start;
3476 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003477 [] IPA_RSL[i][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003478 setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
3479 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003480 [] IPA_RSL[i][0].receive { repeat; }
Harald Welte5d1a2202017-12-13 19:51:29 +01003481 [] T.timeout { }
3482 }
Harald Welte6f521d82017-12-11 19:52:02 +01003483 }
3484
3485 setverdict(pass);
3486}
3487
Harald Welte5d1a2202017-12-13 19:51:29 +01003488const BtsIdList c_BtsId_all := { 0, 1, 2 };
Harald Welte751d3eb2018-01-31 15:51:06 +01003489const BtsIdList c_BtsId_none := { };
Harald Welte5d1a2202017-12-13 19:51:29 +01003490const BtsIdList c_BtsId_LAC1 := { 0, 1 };
3491const BtsIdList c_BtsId_LAC2 := { 2 };
3492
Harald Welte6f521d82017-12-11 19:52:02 +01003493/* PAGING by IMSI + TMSI */
3494testcase TC_paging_imsi_nochan() runs on test_CT {
3495 var BSSMAP_FIELD_CellIdentificationList cid_list;
3496 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Philipp Maier8c04b0a2018-02-23 13:48:48 +01003497 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, omit);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003498 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003499}
3500
3501/* PAGING by IMSI + TMSI */
3502testcase TC_paging_tmsi_nochan() runs on test_CT {
3503 var BSSMAP_FIELD_CellIdentificationList cid_list;
3504 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003505 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, 'A1B2C301'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003506 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003507}
3508
3509/* Paging with different "channel needed' values */
3510testcase TC_paging_tmsi_any() runs on test_CT {
3511 var BSSMAP_FIELD_CellIdentificationList cid_list;
3512 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003513 f_pageing_helper('001010100000002'H, cid_list, c_BtsId_all, RSL_CHANNEED_ANY, 'A1B2C302'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003514 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003515}
3516testcase TC_paging_tmsi_sdcch() runs on test_CT {
3517 var BSSMAP_FIELD_CellIdentificationList cid_list;
3518 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003519 f_pageing_helper('001010100000003'H, cid_list, c_BtsId_all, RSL_CHANNEED_SDCCH, 'A1B2C303'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003520 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003521}
3522testcase TC_paging_tmsi_tch_f() runs on test_CT {
3523 var BSSMAP_FIELD_CellIdentificationList cid_list;
3524 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003525 f_pageing_helper('001010000000004'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_F, 'A1B2C304'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003526 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003527}
3528testcase TC_paging_tmsi_tch_hf() runs on test_CT {
3529 var BSSMAP_FIELD_CellIdentificationList cid_list;
3530 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003531 f_pageing_helper('001010000000005'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_ForH, 'A1B2C305'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003532 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003533}
3534
3535/* Paging by CGI */
3536testcase TC_paging_imsi_nochan_cgi() runs on test_CT {
3537 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3538 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(cid.mcc, cid.mnc, cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003539 f_pageing_helper('001010000000006'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003540 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003541}
3542
3543/* Paging by LAC+CI */
3544testcase TC_paging_imsi_nochan_lac_ci() runs on test_CT {
3545 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3546 cid_list := { cIl_LAC_CI := { ts_BSSMAP_CI_LAC_CI(cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003547 f_pageing_helper('001010000000007'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003548 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003549}
3550
3551/* Paging by CI */
3552testcase TC_paging_imsi_nochan_ci() runs on test_CT {
3553 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3554 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003555 f_pageing_helper('001010000000008'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003556 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003557}
3558
3559/* Paging by LAI */
3560testcase TC_paging_imsi_nochan_lai() runs on test_CT {
3561 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3562 cid_list := { cIl_LAI := { ts_BSSMAP_CI_LAI(cid.mcc, cid.mnc, cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003563 f_pageing_helper('001010000000009'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003564 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003565}
3566
3567/* Paging by LAC */
3568testcase TC_paging_imsi_nochan_lac() runs on test_CT {
3569 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3570 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003571 f_pageing_helper('001010000000010'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003572 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003573}
3574
3575/* Paging by "all in BSS" */
3576testcase TC_paging_imsi_nochan_all() runs on test_CT {
3577 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3578 cid_list := { cIl_allInBSS := ''O };
Harald Welte5d1a2202017-12-13 19:51:29 +01003579 f_pageing_helper('001010000000011'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003580 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003581}
3582
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003583/* Paging by PLMN+LAC+RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003584testcase TC_paging_imsi_nochan_plmn_lac_rnc() runs on test_CT {
3585 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3586 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 +01003587 f_pageing_helper('001010000000012'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003588 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003589}
Harald Welte6f521d82017-12-11 19:52:02 +01003590
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003591/* Paging by RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003592testcase TC_paging_imsi_nochan_rnc() runs on test_CT {
3593 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3594 cid_list := { cIl_RNC := { int2oct(13, 2) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003595 f_pageing_helper('001010000000013'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003596 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003597}
3598
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003599/* Paging by LAC+RNC; We do not implement; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003600testcase TC_paging_imsi_nochan_lac_rnc() runs on test_CT {
3601 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3602 cid_list := { cIl_LAC_RNC := { ts_BSSMAP_CI_LAC_RNC(cid.lac, 14) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003603 f_pageing_helper('001010000000014'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003604 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003605}
3606
Harald Welte6f521d82017-12-11 19:52:02 +01003607/* Paging on multiple cells (multiple entries in list): Verify all of them page */
Harald Welte751d3eb2018-01-31 15:51:06 +01003608testcase TC_paging_imsi_nochan_lacs() runs on test_CT {
3609 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3610 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(1), ts_BSSMAP_CI_LAC(2) } };
3611 f_pageing_helper('001010000000015'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003612 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003613}
3614
3615/* Paging on empty list: Verify none of them page */
3616testcase TC_paging_imsi_nochan_lacs_empty() runs on test_CT {
3617 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3618 cid_list := { cIl_LAC := { } };
3619 f_pageing_helper('001010000000016'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003620 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003621}
3622
Stefan Sperling049a86e2018-03-20 15:51:00 +01003623/* Paging by CGI with unknown MCC/MNC: Verify nothing is paged. */
3624testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
3625 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3626 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(unknown_cid.mcc, unknown_cid.mnc, unknown_cid.lac, unknown_cid.ci) } };
3627 f_pageing_helper('001010000000006'H, cid_list, c_BtsId_none);
3628 f_shutdown_helper();
3629}
3630
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +01003631/* Send paging response containing invalid (wrongly formatted) MobileIdentity IE. */
3632testcase TC_paging_imsi_nochan_ci_resp_invalid_mi() runs on test_CT {
3633 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3634 var BSSAP_N_CONNECT_ind rx_c_ind;
3635 var DchanTuple dt;
3636 var octetstring rr_pag_resp := '06270003535992617965720000'O;
3637 /* { 06 27 } is { GSM48_PDISC_RR, GSM48_MT_RR_PAG_RESP }
3638 * see 3GPP TS 44.018, table 9.1.25.1
3639 * { 00 } or { 01 } is CKSN + Spare Half Octet, not important
3640 * { 03 53 59 92 } is Mobile Station Classmark
3641 * { 61 79 65 72 00 00 } is the invalid Mobile Identity IE (3GPP TS 24.008, 10.5.1.4),
3642 * Length is 0x61 (97 in decimal).
3643 */
3644
3645 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
3646 f_pageing_helper('001010000000008'H, cid_list, { 0 });
3647
3648 /* Send CHAN RQD and wait for allocation; acknowledge it */
3649 dt.rsl_chan_nr := f_chreq_act_ack();
3650 dt.idx := {0, 0};
3651
3652 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
3653 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), rr_pag_resp));
3654
3655 /* Expevct a CR with a matching Paging response on the A-Interface */
3656 timer T := 5.0;
3657 T.start;
3658 alt {
3659 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
3660 setverdict(pass);
3661 dt.sccp_conn_id := rx_c_ind.connectionId;
3662 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
3663 }
3664 [] BSSAP.receive {
3665 setverdict(fail, "Received unexpected message on A-Interface!");
3666 }
3667 [] T.timeout {
3668 setverdict(fail, "Received nothing on A-Interface!");
3669 }
3670 }
3671
3672 f_perform_clear_test_ct(dt);
3673 f_shutdown_helper();
3674}
3675
Harald Welte6f521d82017-12-11 19:52:02 +01003676/* Verify paging retransmission interval + count */
3677/* Verify paging stops after channel establishment */
Harald Welte6f521d82017-12-11 19:52:02 +01003678/* Test behavior under paging overload */
Harald Welteae026692017-12-09 01:03:01 +01003679
Harald Weltee65d40e2017-12-13 00:09:06 +01003680/* Verify PCH load */
3681testcase TC_paging_imsi_load() runs on test_CT {
3682 var BSSMAP_FIELD_CellIdentificationList cid_list;
3683 timer T := 4.0;
Harald Welte2caa1062018-03-17 18:19:05 +01003684 timer T_retrans := 1.0;
Harald Weltee65d40e2017-12-13 00:09:06 +01003685 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003686 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Weltee65d40e2017-12-13 00:09:06 +01003687
3688 /* tell BSC there is no paging space anymore */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003689 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte3b57ab52018-03-17 18:01:10 +01003690 f_sleep(0.2);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003691 IPA_RSL[0][0].clear;
Harald Weltee65d40e2017-12-13 00:09:06 +01003692
3693 /* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
3694 * there would be 8 retransmissions during 4 seconds */
3695 T.start;
Harald Welte2caa1062018-03-17 18:19:05 +01003696 T_retrans.start;
Harald Weltee65d40e2017-12-13 00:09:06 +01003697 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003698 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Weltee65d40e2017-12-13 00:09:06 +01003699 setverdict(fail, "Received PAGING after LOAD_IND(0)");
Daniel Willmannafce8662018-07-06 23:11:32 +02003700 mtc.stop;
Harald Weltee65d40e2017-12-13 00:09:06 +01003701 }
Harald Welte2caa1062018-03-17 18:19:05 +01003702 [] T_retrans.timeout {
3703 /* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003704 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte2caa1062018-03-17 18:19:05 +01003705 T_retrans.start;
3706 repeat;
3707 }
Harald Weltee65d40e2017-12-13 00:09:06 +01003708 [] T.timeout {
3709 setverdict(pass);
3710 }
3711 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003712
3713 f_shutdown_helper();
Harald Weltee65d40e2017-12-13 00:09:06 +01003714}
3715
Harald Welte235ebf12017-12-15 14:18:16 +01003716/* Verify Paging Counter */
Harald Welte1ff69992017-12-14 12:31:17 +01003717testcase TC_paging_counter() runs on test_CT {
3718 var BSSMAP_FIELD_CellIdentificationList cid_list;
3719 timer T := 4.0;
3720 var integer i;
3721 var integer paging_attempted_bsc;
3722 var integer paging_attempted_bts[NUM_BTS];
Oliver Smith8b343d32021-11-26 13:01:42 +01003723 var integer paging_expired_bsc;
Harald Welte1ff69992017-12-14 12:31:17 +01003724 var integer paging_expired_bts[NUM_BTS];
3725 cid_list := valueof(ts_BSSMAP_CIL_noCell);
3726
3727 f_init();
3728
3729 /* read counters before paging */
3730 paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003731 paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
Harald Welte1ff69992017-12-14 12:31:17 +01003732 for (i := 0; i < NUM_BTS; i := i+1) {
3733 paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
3734 paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
3735 }
3736
3737 f_pageing_helper('001230000000001'H, cid_list, c_BtsId_all);
3738
3739 /* expect the attempted pages on BSC and each BTSs to have incremented by one */
3740 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", paging_attempted_bsc+1);
3741 for (i := 0; i < NUM_BTS; i := i+1) {
3742 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted",
3743 paging_attempted_bts[i]+1);
3744 }
3745
3746 /* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
3747 f_sleep(12.0);
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003748 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
Harald Welte1ff69992017-12-14 12:31:17 +01003749 for (i := 0; i < NUM_BTS; i := i+1) {
3750 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
3751 paging_expired_bts[i]+1);
3752 }
Harald Welte1ff69992017-12-14 12:31:17 +01003753
Philipp Maier282ca4b2018-02-27 17:17:00 +01003754 f_shutdown_helper();
Harald Welte1ff69992017-12-14 12:31:17 +01003755}
3756
3757
Harald Welte10985002017-12-12 09:29:15 +01003758/* Verify paging stops after A-RESET */
3759testcase TC_paging_imsi_a_reset() runs on test_CT {
3760 var BSSMAP_FIELD_CellIdentificationList cid_list;
3761 timer T := 3.0;
3762 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003763 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Welte10985002017-12-12 09:29:15 +01003764
3765 /* Perform a BSSMAP Reset and wait for ACK */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003766 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 +01003767 alt {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003768 [] 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 +01003769 [] BSSAP.receive { repeat; }
3770 }
3771
Daniel Willmanncbef3982018-07-30 09:22:40 +02003772 /* Wait to avoid a possible race condition if a paging message is
3773 * received right before the reset ACK. */
3774 f_sleep(0.2);
3775
Harald Welte10985002017-12-12 09:29:15 +01003776 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Philipp Maier1e6b4422018-02-23 14:02:13 +01003777 for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003778 IPA_RSL[i][0].clear;
Philipp Maier1e6b4422018-02-23 14:02:13 +01003779 }
Harald Welte10985002017-12-12 09:29:15 +01003780
3781 /* Wait for 3 seconds if any more PAGING CMD are received on RSL */
3782 T.start;
3783 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003784 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte10985002017-12-12 09:29:15 +01003785 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003786 mtc.stop;
Harald Welte10985002017-12-12 09:29:15 +01003787 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003788 [] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003789 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003790 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003791 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003792 [] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003793 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003794 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003795 }
Harald Welte10985002017-12-12 09:29:15 +01003796 [] T.timeout {
3797 setverdict(pass);
3798 }
3799 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003800
3801 f_shutdown_helper();
Harald Welte10985002017-12-12 09:29:15 +01003802}
Harald Welteae026692017-12-09 01:03:01 +01003803
Philipp Maierf45824a2019-08-14 14:44:10 +02003804/* Verify how we handle unsolicited Paging Response. In case of an unsolicit
3805 * paging response we can not know which MSC is in charge, so we will blindly
3806 * pick the first configured MSC. This behavior is required in order to make
3807 * MT-CSFB calls working because in those cases the BSC can not know that the
3808 * MSC has already paged the subscriver via SGs. So any MT-CSFB call will look
3809 * like an unsolicited Paging Response to the MSC.
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003810 */
3811testcase TC_paging_resp_unsol() runs on test_CT {
3812
3813 f_init(1);
Philipp Maierf45824a2019-08-14 14:44:10 +02003814 timer T := 5.0;
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003815
3816 var BSSAP_N_CONNECT_ind rx_c_ind;
3817 var DchanTuple dt;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02003818 var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010008880018'H)));
Philipp Maierf45824a2019-08-14 14:44:10 +02003819 var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003820
3821 /* Send CHAN RQD and wait for allocation; acknowledge it */
3822 dt.rsl_chan_nr := f_chreq_act_ack();
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003823 dt.idx := {0, 0};
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003824
3825 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
Pau Espin Pedrole8a51012023-01-03 11:59:59 +01003826 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 +01003827
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003828
Philipp Maierf45824a2019-08-14 14:44:10 +02003829 /* Expevct a CR with a matching Paging response on the A-Interface */
3830 T.start;
3831 alt {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003832 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
Philipp Maierf45824a2019-08-14 14:44:10 +02003833 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003834 dt.sccp_conn_id := rx_c_ind.connectionId;
3835 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
Philipp Maierf45824a2019-08-14 14:44:10 +02003836 }
3837 [] BSSAP.receive {
3838 setverdict(fail, "Received unexpected message on A-Interface!");
3839 }
3840 [] T.timeout {
3841 setverdict(fail, "Received nothing on A-Interface!");
3842 }
3843 }
3844
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003845 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003846 f_shutdown_helper();
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003847}
3848
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003849/* Verify BSC can schedule N paging requests under one minute if BTS buffer is good enough */
3850function f_TC_paging_Nreq(integer num_subscribers, boolean send_pag_load_ind) runs on test_CT {
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003851 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003852 var Hexstrings imsis := {};
3853 var Booleans rx_paging_done := {};
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003854 var integer rx_paging_num := 0;
3855 var integer i;
3856 timer T_rx := 60.0;
3857 timer T_load_ind := 1.0;
3858
3859 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003860 imsis := imsis & {f_gen_imsi(i)};
3861 rx_paging_done := rx_paging_done & { false };
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003862 }
3863
3864 f_init(1, guard_timeout := 100.0);
3865
3866 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003867 IPA_RSL[0][0].clear;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003868 if (send_pag_load_ind) {
3869 /* Tell there's plenty of space at the BTS (UINT16_MAX): */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003870 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(65535));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003871 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003872
3873 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003874 /* Page on LAC-CI of BTS0: */
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003875 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 +02003876 ts_BSSMAP_Paging(imsis[i], valueof(ts_BSSMAP_CIL_LAC_CI({ts_BSSMAP_CI_LAC_CI(1, 0)})),
3877 omit, omit)));
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003878 }
3879
3880 T_rx.start;
3881 T_load_ind.start;
3882 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003883 [] 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 +02003884 var hexstring imsi := rx_rsl_ud.rsl.ies[2].body.ms_identity.mobileIdentityV.oddEvenInd_identity.imsi.digits;
3885 var hexstring imsi_suffix := substr(imsi, lengthof(imsi)-6, 6);
3886 var charstring imsi_str := hex2str(imsi_suffix);
3887 var integer imsi_idx := str2int(imsi_str);
3888 if (rx_paging_done[imsi_idx] == false) {
3889 rx_paging_done[imsi_idx] := true;
3890 rx_paging_num := rx_paging_num + 1;
Pau Espin Pedrolef7ef632022-04-25 13:34:57 +02003891 } else {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003892 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 +02003893 mtc.stop;
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003894 }
3895 if (rx_paging_num < num_subscribers) {
3896 repeat;
3897 }
3898 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003899 [] IPA_RSL[0][0].receive { repeat; }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003900 [] T_load_ind.timeout {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003901 log("[CCH Load Ind timer] received paging requests so far: ", rx_paging_num);
3902 if (send_pag_load_ind) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003903 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(40));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003904 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003905 T_load_ind.start;
3906 repeat;
3907 }
3908 [] T_rx.timeout {
3909 setverdict(fail, "Timeout expecting paging requests, so far ", rx_paging_num);
3910 mtc.stop;
3911 }
3912 }
3913
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003914 /* Drop OML connection to have all paging requests flushed: */
3915 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
3916
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003917 f_shutdown_helper();
3918}
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003919/* Verify BSC can schedule 500 paging requests under one minute if BTS buffer is good enough */
3920testcase TC_paging_500req() runs on test_CT {
3921 f_TC_paging_Nreq(500, true);
3922}
3923/* Same as TC_paging_500req, but without sending CCCH Load Indication, which
3924 * means BTS is always under CCH Load Threshold, aka capable of sending tons of requests.
3925 * Since No CCCH Load Ind, BSC uses a conservative estimation of BTS load, which
3926 * for current config yields ~8req/sec, so 480req/min maximum. */
3927testcase TC_paging_450req_no_paging_load_ind() runs on test_CT {
3928 f_TC_paging_Nreq(450, false);
3929}
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003930
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003931/* Test RSL link drop causes counter increment */
3932testcase TC_rsl_drop_counter() runs on test_CT {
3933 var integer rsl_fail;
3934
Harald Welte89d42e82017-12-17 16:42:41 +01003935 f_init(1);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003936
3937 rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
3938
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003939 f_ipa_rsl_stop(bts[0][0].rsl);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003940
3941 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
3942
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003943 f_shutdown_helper();
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003944}
3945
3946/* TODO: Test OML link drop causes counter increment */
3947
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003948/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
3949function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003950 var IPA_Client client;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003951 timer T := 10.0;
3952
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003953 client.id := "IPA-BTS0-TRX0-RSL";
3954 client.vc_IPA := IPA_Emulation_CT.create(client.id & "-IPA") alive;
3955 client.ccm_pars := c_IPA_default_ccm_pars;
3956 client.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
3957 client.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003958
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01003959 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003960
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003961 f_init_mgcp(0, "VirtMGW");
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003962
3963 /* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003964 map(client.vc_IPA:IPA_PORT, system:IPA);
3965 connect(client.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0][0]);
3966 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 +01003967
3968 /* wait for IPA OML link to connect and then disconnect */
3969 T.start;
3970 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003971 [] IPA_RSL[0][0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003972 T.stop;
3973 return true;
3974 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003975 [] IPA_RSL[0][0].receive { repeat }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003976 [] T.timeout {
Daniel Willmannafce8662018-07-06 23:11:32 +02003977 return false;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003978 }
3979 }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003980 return false;
3981}
3982
3983/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3984testcase TC_rsl_unknown_unit_id() runs on test_CT {
3985 if (f_ipa_unknown_unit_id(mp_bsc_rsl_port)) {
3986 setverdict(pass);
3987 } else {
3988 setverdict(fail, "Timeout RSL waiting for connection to close");
3989 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003990 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003991}
3992
3993
3994/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3995testcase TC_oml_unknown_unit_id() runs on test_CT {
3996 if (f_ipa_unknown_unit_id(mp_bsc_oml_port)) {
3997 setverdict(pass);
3998 } else {
3999 setverdict(fail, "Timeout OML waiting for connection to close");
4000 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004001 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01004002}
4003
4004
Harald Weltec1a2fff2017-12-17 11:06:19 +01004005/***********************************************************************
Harald Welte6811d102019-04-14 22:23:14 +02004006 * "New world" test cases using RSL_Emulation + RAN_Emulation
Harald Weltec1a2fff2017-12-17 11:06:19 +01004007 ***********************************************************************/
4008
Harald Welte6811d102019-04-14 22:23:14 +02004009import from RAN_Emulation all;
Harald Welte47cd0e32020-08-21 12:39:11 +02004010import from BSSAP_LE_Emulation all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01004011import from RSL_Emulation all;
4012import from MSC_ConnectionHandler all;
4013
4014type function void_fn(charstring id) runs on MSC_ConnHdlr;
4015
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06004016/* helper function to create and connect a MSC_ConnHdlr component
4017 * TODO: allow connecting to TRX1..N, not only TRX0 */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004018private 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 +02004019 connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06004020 connect(vc_conn:RSL, bts[0][0].rsl.vc_RSL:CLIENT_PT);
4021 connect(vc_conn:RSL_PROC, bts[0][0].rsl.vc_RSL:RSL_PROC);
4022 if (isvalue(bts[1][0])) {
4023 connect(vc_conn:RSL1, bts[1][0].rsl.vc_RSL:CLIENT_PT);
4024 connect(vc_conn:RSL1_PROC, bts[1][0].rsl.vc_RSL:RSL_PROC);
Philipp Maier956a92f2018-02-16 10:58:07 +01004025 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06004026 if (isvalue(bts[2][0])) {
4027 connect(vc_conn:RSL2, bts[2][0].rsl.vc_RSL:CLIENT_PT);
4028 connect(vc_conn:RSL2_PROC, bts[2][0].rsl.vc_RSL:RSL_PROC);
Neels Hofmeyr91401012019-07-11 00:42:35 +02004029 }
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004030 connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02004031 if (mp_enable_lcs_tests) {
4032 connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
4033 connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
4034 }
Daniel Willmannebdecc02020-08-12 15:30:17 +02004035 connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004036 connect(vc_conn:MGCP_PROC, vc_MGCP[mgwpool_idx]:MGCP_PROC);
4037 connect(vc_conn:MGCP, vc_MGCP[mgwpool_idx]:MGCP_CLIENT);
4038 connect(vc_conn:MGCP_MULTI, vc_MGCP[mgwpool_idx]:MGCP_CLIENT_MULTI);
Harald Welte336820c2018-05-31 20:34:52 +02004039}
4040
Neels Hofmeyrda436782021-07-20 22:09:06 +02004041function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
Harald Welte336820c2018-05-31 20:34:52 +02004042runs on test_CT return MSC_ConnHdlr {
4043 var charstring id := testcasename();
4044 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004045 var integer bssap_idx := 0;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004046 var integer mgwpool_idx := 0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004047 if (isvalue(pars)) {
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004048 var TestHdlrParams pars_val := valueof(pars);
4049 bssap_idx := pars_val.mscpool.bssap_idx;
4050 mgwpool_idx := pars_val.mgwpool_idx;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004051 }
Harald Welte336820c2018-05-31 20:34:52 +02004052 vc_conn := MSC_ConnHdlr.create(id);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004053 f_connect_handler(vc_conn, bssap_idx, mgwpool_idx);
Neels Hofmeyrda436782021-07-20 22:09:06 +02004054 return vc_conn;
4055}
4056
4057function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
4058runs on test_CT return MSC_ConnHdlr {
4059 var charstring id := testcasename();
Harald Weltea0630032018-03-20 21:09:55 +01004060 vc_conn.start(f_handler_init(fn, id, pars));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004061 return vc_conn;
4062}
4063
Neels Hofmeyrda436782021-07-20 22:09:06 +02004064function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
4065runs on test_CT return MSC_ConnHdlr {
4066 return f_start_handler_run(f_start_handler_create(pars), fn, pars);
4067}
4068
Harald Weltea0630032018-03-20 21:09:55 +01004069/* first function inside ConnHdlr component; sets g_pars + starts function */
4070private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
4071runs on MSC_ConnHdlr {
4072 if (isvalue(pars)) {
4073 g_pars := valueof(pars);
4074 }
4075 fn.apply(id);
4076}
4077
Oliver Smith26a3db72021-07-09 13:51:29 +02004078private function f_vty_encryption_a5(charstring options) runs on test_CT {
4079 f_vty_transceive(BSCVTY, "configure terminal");
4080 f_vty_transceive(BSCVTY, "network");
4081 f_vty_transceive(BSCVTY, "encryption a5 " & options);
4082 f_vty_transceive(BSCVTY, "exit");
4083 f_vty_transceive(BSCVTY, "exit");
4084}
4085
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004086const charstring VTY_A5_DEFAULT := "0 1 3";
4087
Oliver Smith26a3db72021-07-09 13:51:29 +02004088private function f_vty_encryption_a5_reset() runs on test_CT {
4089 /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004090 f_vty_encryption_a5(VTY_A5_DEFAULT);
Oliver Smith26a3db72021-07-09 13:51:29 +02004091}
4092
Harald Welte3c86ea02018-05-10 22:28:05 +02004093/* Establish signalling channel (non-assignment case) followed by cipher mode */
4094private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004095 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4096 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte3c86ea02018-05-10 22:28:05 +02004097 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Philipp Maier23000732018-05-18 11:25:37 +02004098 ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode := omit;
4099 ass_cmd.pdu.bssmap.assignmentRequest.aoIPTransportLayer := omit;
4100 exp_compl.pdu.bssmap.assignmentComplete.circuitIdentityCode := omit;
4101 exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
Harald Welte3c86ea02018-05-10 22:28:05 +02004102
Philipp Maier23000732018-05-18 11:25:37 +02004103 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004104 f_perform_clear();
Harald Welte3c86ea02018-05-10 22:28:05 +02004105}
4106testcase TC_ciph_mode_a5_0() runs on test_CT {
4107 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004108 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004109 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
4110
4111 f_init(1, true);
4112 f_sleep(1.0);
4113 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4114 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004115 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004116}
4117testcase TC_ciph_mode_a5_1() runs on test_CT {
4118 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004119 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004120 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
4121
4122 f_init(1, true);
4123 f_sleep(1.0);
4124 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4125 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004126 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004127}
Oliver Smith50b98122021-07-09 15:00:28 +02004128/* OS#4975: verify that A5/2 is preferred over A5/0 */
4129testcase TC_ciph_mode_a5_2_0() runs on test_CT {
4130 var MSC_ConnHdlr vc_conn;
4131 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4132
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004133 pars.encr := f_encr_params('05'O, '04'O); /* A5/0 and A5/2 (0x01|0x04)*/
Oliver Smith50b98122021-07-09 15:00:28 +02004134
4135 f_init(1, true);
4136 f_vty_encryption_a5("0 1 2 3");
4137 f_sleep(1.0);
4138 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4139 vc_conn.done;
4140 f_vty_encryption_a5_reset();
4141 f_shutdown_helper();
4142}
Oliver Smith1dff88d2021-07-09 08:45:51 +02004143/* OS#4975: verify that A5/1 is preferred over A5/2 */
4144testcase TC_ciph_mode_a5_2_1() runs on test_CT {
4145 var MSC_ConnHdlr vc_conn;
4146 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4147
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004148 pars.encr := f_encr_params('06'O, '02'O); /* A5/1 and A5/2 (0x02|0x04)*/
Oliver Smith1dff88d2021-07-09 08:45:51 +02004149
4150 f_init(1, true);
4151 f_vty_encryption_a5("1 2");
4152 f_sleep(1.0);
4153 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4154 vc_conn.done;
4155 f_vty_encryption_a5_reset();
4156 f_shutdown_helper();
4157}
Harald Welte3c86ea02018-05-10 22:28:05 +02004158testcase TC_ciph_mode_a5_3() runs on test_CT {
4159 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004160 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004161 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
4162
4163 f_init(1, true);
4164 f_sleep(1.0);
4165 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4166 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004167 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004168}
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004169/* Establish a Signalling channel with A5/4 encryption. */
4170testcase TC_ciph_mode_a5_4() runs on test_CT {
4171 var MSC_ConnHdlr vc_conn;
4172 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4173 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Harald Welte3c86ea02018-05-10 22:28:05 +02004174
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004175 f_init(1, true);
Oliver Smith26a3db72021-07-09 13:51:29 +02004176 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004177 f_sleep(1.0);
4178 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4179 vc_conn.done;
Oliver Smith26a3db72021-07-09 13:51:29 +02004180 f_vty_encryption_a5_reset();
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004181 f_shutdown_helper();
4182}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004183/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
4184private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
4185 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4186 var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
4187 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4188 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4189
4190 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004191 f_perform_clear();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004192}
4193testcase TC_assignment_aoip_tla_v6() runs on test_CT {
4194 var MSC_ConnHdlr vc_conn;
4195 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4196
4197 f_init(1, true);
4198 f_sleep(1.0);
4199 vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
4200 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004201 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004202}
4203
Harald Welte3c86ea02018-05-10 22:28:05 +02004204
4205/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
Harald Welte651fcdc2018-05-10 20:23:16 +02004206private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004207 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4208 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004209
Harald Welte552620d2017-12-16 23:21:36 +01004210 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4211 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte73cd2712017-12-17 00:44:52 +01004212
Harald Weltea0630032018-03-20 21:09:55 +01004213 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004214 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004215}
Harald Welte552620d2017-12-16 23:21:36 +01004216testcase TC_assignment_fr_a5_0() runs on test_CT {
4217 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004218 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004219 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
Harald Welte552620d2017-12-16 23:21:36 +01004220
Harald Welte89d42e82017-12-17 16:42:41 +01004221 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004222 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004223 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004224 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004225 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004226}
Harald Welte552620d2017-12-16 23:21:36 +01004227testcase TC_assignment_fr_a5_1() runs on test_CT {
Harald Weltec1a2fff2017-12-17 11:06:19 +01004228 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004229 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004230 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004231
Harald Welte89d42e82017-12-17 16:42:41 +01004232 f_init(1, true);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004233 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004234 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4235 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004236 f_shutdown_helper();
Harald Welte651fcdc2018-05-10 20:23:16 +02004237}
4238testcase TC_assignment_fr_a5_3() runs on test_CT {
4239 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004240 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004241 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004242
Harald Welte651fcdc2018-05-10 20:23:16 +02004243 f_init(1, true);
4244 f_sleep(1.0);
4245 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004246 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004247 f_shutdown_helper();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004248}
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004249/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
4250testcase TC_assignment_fr_a5_4() runs on test_CT {
4251 var MSC_ConnHdlr vc_conn;
4252 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4253 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
4254
4255 f_init(1, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02004256 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004257 f_sleep(1.0);
4258 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4259 vc_conn.done;
Oliver Smith7eabd312021-07-12 14:18:56 +02004260 f_vty_encryption_a5_reset();
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004261 f_shutdown_helper();
4262}
Harald Weltec1a2fff2017-12-17 11:06:19 +01004263
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +02004264/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
4265testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
4266 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4267 var MSC_ConnHdlr vc_conn;
4268
4269 f_init(1, true);
4270 f_sleep(1.0);
4271
4272 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
4273 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
4274 vc_conn.done;
4275 f_shutdown_helper();
4276}
4277
Harald Welte552620d2017-12-16 23:21:36 +01004278/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
4279private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004280 g_pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004281 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02004282 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004283
4284 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02004285 /* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
4286
Harald Weltea0630032018-03-20 21:09:55 +01004287 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004288 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004289}
Harald Welte552620d2017-12-16 23:21:36 +01004290testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
4291 var MSC_ConnHdlr vc_conn;
4292
Harald Welte89d42e82017-12-17 16:42:41 +01004293 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004294 f_sleep(1.0);
4295
Harald Welte8863fa12018-05-10 20:15:27 +02004296 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
Harald Welte552620d2017-12-16 23:21:36 +01004297 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004298 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004299}
4300
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004301private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
4302 var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
4303 var PDU_BSSAP exp_ass_req := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004304
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004305 exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4306 exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4307
4308 /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
4309
4310 var BSSMAP_FIELD_CodecType codecType;
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004311
4312 codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
4313 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
4314
4315 f_create_chan_and_exp();
4316 /* we should now have a COMPL_L3 at the MSC */
4317
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004318 /* Start ciphering, expect Cipher Mode Reject */
Neels Hofmeyr6c388f22021-06-11 02:36:56 +02004319 f_cipher_mode(g_pars.encr, exp_fail := true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004320 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004321}
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004322testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
4323 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004324 var MSC_ConnHdlr vc_conn;
4325
Harald Welte89d42e82017-12-17 16:42:41 +01004326 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004327 f_sleep(1.0);
4328
Neels Hofmeyr0588cad2021-06-11 01:38:18 +02004329 pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004330 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004331 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004332 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004333}
4334
4335
Harald Welte4532e0a2017-12-23 02:05:44 +01004336private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004337 g_pars := f_gen_test_hdlr_pars();
Harald Welte4532e0a2017-12-23 02:05:44 +01004338 var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
Philipp Maier48604732018-10-09 15:00:37 +02004339 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte4532e0a2017-12-23 02:05:44 +01004340 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004341
4342 f_statsd_reset();
Harald Weltea0630032018-03-20 21:09:55 +01004343 f_establish_fully(ass_cmd, exp_compl);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004344
4345 var StatsDExpects expect := {
Daniel Willmannc5398f72020-09-21 10:41:35 +02004346 { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
4347 { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
Daniel Willmannebdecc02020-08-12 15:30:17 +02004348 { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
4349 { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
4350 };
4351 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004352 f_perform_clear();
Harald Welte4532e0a2017-12-23 02:05:44 +01004353}
4354
4355testcase TC_assignment_sign() runs on test_CT {
4356 var MSC_ConnHdlr vc_conn;
4357
4358 f_init(1, true);
4359 f_sleep(1.0);
4360
Harald Welte8863fa12018-05-10 20:15:27 +02004361 vc_conn := f_start_handler(refers(f_tc_assignment_sign));
Harald Welte4532e0a2017-12-23 02:05:44 +01004362 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004363 f_shutdown_helper();
Harald Welte4532e0a2017-12-23 02:05:44 +01004364}
4365
Harald Welte60aa5762018-03-21 19:33:13 +01004366/***********************************************************************
4367 * Codec (list) testing
4368 ***********************************************************************/
4369
4370/* check if the given rsl_mode is compatible with the a_elem */
4371private function f_match_codec(BSSMAP_FIELD_CodecElement a_elem, RSL_IE_ChannelMode rsl_mode)
4372return boolean {
4373 select (a_elem.codecType) {
4374 case (GSM_FR) {
4375 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1))) {
4376 return true;
4377 }
4378 }
4379 case (GSM_HR) {
4380 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1))) {
4381 return true;
4382 }
4383 }
4384 case (GSM_EFR) {
4385 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2))) {
4386 return true;
4387 }
4388 }
4389 case (FR_AMR) {
4390 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3))) {
4391 return true;
4392 }
4393 }
4394 case (HR_AMR) {
4395 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3))) {
4396 return true;
4397 }
4398 }
4399 case else { }
4400 }
4401 return false;
4402}
4403
4404/* check if the given rsl_mode is compatible with the a_list */
4405private function f_match_codecs(BSSMAP_IE_SpeechCodecList a_list, RSL_IE_ChannelMode rsl_mode)
4406return boolean {
4407 for (var integer i := 0; i < sizeof(a_list); i := i+1) {
4408 if (f_match_codec(a_list.codecElements[i], rsl_mode)) {
4409 return true;
4410 }
4411 }
4412 return false;
4413}
4414
4415/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
Philipp Maier61f6b572018-07-06 14:03:38 +02004416function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
Harald Welte60aa5762018-03-21 19:33:13 +01004417return BSSMAP_IE_ChannelType {
4418 /* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
4419 var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
4420 select (a_elem.codecType) {
4421 case (GSM_FR) {
4422 ret.channelRateAndType := ChRate_TCHF;
4423 ret.speechId_DataIndicator := Spdi_TCHF_FR;
4424 }
4425 case (GSM_HR) {
4426 ret.channelRateAndType := ChRate_TCHH;
4427 ret.speechId_DataIndicator := Spdi_TCHH_HR;
4428 }
4429 case (GSM_EFR) {
4430 ret.channelRateAndType := ChRate_TCHF;
4431 ret.speechId_DataIndicator := Spdi_TCHF_EFR;
4432 }
4433 case (FR_AMR) {
4434 ret.channelRateAndType := ChRate_TCHF;
4435 ret.speechId_DataIndicator := Spdi_TCHF_AMR;
4436 }
4437 case (HR_AMR) {
4438 ret.channelRateAndType := ChRate_TCHH;
4439 ret.speechId_DataIndicator := Spdi_TCHH_AMR;
4440 }
4441 case else {
4442 setverdict(fail, "Unsupported codec ", a_elem);
Daniel Willmannafce8662018-07-06 23:11:32 +02004443 mtc.stop;
Harald Welte60aa5762018-03-21 19:33:13 +01004444 }
4445 }
4446 return ret;
4447}
4448
Harald Weltea63b9102018-03-22 20:36:16 +01004449private function f_rsl_chmod_tmpl_from_codec(BSSMAP_FIELD_CodecElement a_elem)
4450return template RSL_IE_Body {
4451 var template RSL_IE_Body mode_ie := {
4452 chan_mode := {
4453 len := ?,
4454 reserved := ?,
4455 dtx_d := ?,
4456 dtx_u := ?,
4457 spd_ind := RSL_SPDI_SPEECH,
4458 ch_rate_type := -,
Oliver Smith0033b122023-02-28 13:30:53 +01004459 u := { speech := - }
Harald Weltea63b9102018-03-22 20:36:16 +01004460 }
4461 }
4462
4463 select (a_elem.codecType) {
4464 case (GSM_FR) {
4465 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004466 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004467 }
4468 case (GSM_HR) {
4469 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004470 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004471 }
4472 case (GSM_EFR) {
4473 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004474 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM2;
Harald Weltea63b9102018-03-22 20:36:16 +01004475 }
4476 case (FR_AMR) {
4477 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004478 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004479 }
4480 case (HR_AMR) {
4481 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004482 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004483 }
4484 }
4485 return mode_ie;
4486}
4487
Harald Welte60aa5762018-03-21 19:33:13 +01004488type record CodecListTest {
4489 BSSMAP_IE_SpeechCodecList codec_list,
4490 charstring id
4491}
4492type record of CodecListTest CodecListTests
4493
4494private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004495 f_assignment_codec(id);
4496}
4497
4498private function f_assignment_codec(charstring id, boolean do_perform_clear := true) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02004499 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02004500 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welte60aa5762018-03-21 19:33:13 +01004501
4502 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004503 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte79f3f542018-05-25 20:02:37 +02004504 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4505 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
4506 g_pars.ass_codec_list.codecElements[0];
Philipp Maierd0e64b02019-03-13 14:15:23 +01004507 if (isvalue(g_pars.expect_mr_s0_s7)) {
4508 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
4509 g_pars.expect_mr_s0_s7;
4510 }
Harald Welte79f3f542018-05-25 20:02:37 +02004511 }
Harald Welte60aa5762018-03-21 19:33:13 +01004512 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4513 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
Harald Welte60aa5762018-03-21 19:33:13 +01004514 log("expecting ASS COMPL like this: ", exp_compl);
4515
4516 f_establish_fully(ass_cmd, exp_compl);
Harald Weltea63b9102018-03-22 20:36:16 +01004517
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004518 if (not g_pars.expect_channel_mode_modify) {
4519 /* Verify that the RSL-side activation actually matches our expectations */
4520 var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
Harald Weltea63b9102018-03-22 20:36:16 +01004521
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004522 var RSL_IE_Body mode_ie;
4523 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
4524 setverdict(fail, "Couldn't find CHAN_MODE IE");
Daniel Willmannafce8662018-07-06 23:11:32 +02004525 mtc.stop;
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004526 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004527 var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
4528 if (not match(mode_ie, t_mode_ie)) {
4529 log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
4530 setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004531 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004532
4533 var RSL_IE_Body mr_conf;
4534 if (g_pars.expect_mr_conf_ie != omit) {
4535 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
4536 setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
4537 mtc.stop;
4538 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004539 log("found RSL MR CONFIG IE: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004540
4541 if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
Vadim Yanitskiy8b189372022-09-14 17:31:17 +07004542 setverdict(fail, "RSL MR CONFIG IE does not match expectation. ",
4543 "Expected: ", g_pars.expect_mr_conf_ie, ", got: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004544 }
4545 } else {
4546 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
4547 log("found RSL MR CONFIG IE: ", mr_conf);
4548 setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
4549 mtc.stop;
4550 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004551 }
4552 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004553
4554 if (do_perform_clear) {
4555 f_perform_clear();
4556 }
Harald Welte60aa5762018-03-21 19:33:13 +01004557}
4558
Philipp Maierd0e64b02019-03-13 14:15:23 +01004559private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
4560
4561 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4562 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4563
4564 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004565 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maierd0e64b02019-03-13 14:15:23 +01004566 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4567 }
4568 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4569 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
4570 log("expecting ASS FAIL like this: ", exp_fail);
4571
4572 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004573 f_perform_clear();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004574}
4575
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004576const CounterNameVals counternames_bsc_bts_assignment := {
4577 { "assignment:attempted", 0 },
4578 { "assignment:completed", 0 },
4579 { "assignment:stopped", 0 },
4580 { "assignment:no_channel", 0 },
4581 { "assignment:timeout", 0 },
4582 { "assignment:failed", 0 },
4583 { "assignment:error", 0 }
4584};
4585
4586const CounterNameVals counternames_bts_assignment := {
4587 { "assignment:attempted_sign", 0 },
4588 { "assignment:attempted_speech", 0 },
4589 { "assignment:completed_sign", 0 },
4590 { "assignment:completed_speech", 0 },
4591 { "assignment:stopped_sign", 0 },
4592 { "assignment:stopped_speech", 0 },
4593 { "assignment:no_channel_sign", 0 },
4594 { "assignment:no_channel_speech", 0 },
4595 { "assignment:timeout_sign", 0 },
4596 { "assignment:timeout_speech", 0 },
4597 { "assignment:failed_sign", 0 },
4598 { "assignment:failed_speech", 0 },
4599 { "assignment:error_sign", 0 },
4600 { "assignment:error_speech", 0 }
4601};
4602
4603function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
4604 var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
4605 f_ctrs_bts_init(bts_count, bts_names);
4606 f_ctrs_bsc_init(counternames_bsc_bts_assignment);
4607}
4608
Harald Welte60aa5762018-03-21 19:33:13 +01004609testcase TC_assignment_codec_fr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004610 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004611 var MSC_ConnHdlr vc_conn;
4612
4613 f_init(1, true);
4614 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004615 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004616
4617 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004618 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004619 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004620
4621 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4622 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4623 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4624 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4625 f_ctrs_bts_verify();
4626
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004627 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004628}
4629
4630testcase TC_assignment_codec_hr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004631 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004632 var MSC_ConnHdlr vc_conn;
4633
4634 f_init(1, true);
4635 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004636 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004637
4638 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004639 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004640 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004641
4642 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4643 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4644 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4645 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4646 f_ctrs_bts_verify();
4647
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004648 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004649}
4650
4651testcase TC_assignment_codec_efr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004652 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004653 var MSC_ConnHdlr vc_conn;
4654
4655 f_init(1, true);
4656 f_sleep(1.0);
4657
4658 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004659 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004660 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004661 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004662}
4663
Philipp Maierd0e64b02019-03-13 14:15:23 +01004664/* Allow 5,90k only (current default config) */
4665private function f_allow_amr_rate_5_90k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004666 f_vty_cfg_msc(BSCVTY, 0, {
4667 "amr-config 12_2k forbidden",
4668 "amr-config 10_2k forbidden",
4669 "amr-config 7_95k forbidden",
4670 "amr-config 7_40k forbidden",
4671 "amr-config 6_70k forbidden",
4672 "amr-config 5_90k allowed",
4673 "amr-config 5_15k forbidden",
4674 "amr-config 4_75k forbidden"
4675 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004676}
4677
4678/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
4679 * ("Config-NB-Code = 1") */
4680private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004681 f_vty_cfg_msc(BSCVTY, 0, {
4682 "amr-config 12_2k allowed",
4683 "amr-config 10_2k forbidden",
4684 "amr-config 7_95k forbidden",
4685 "amr-config 7_40k allowed",
4686 "amr-config 6_70k forbidden",
4687 "amr-config 5_90k allowed",
4688 "amr-config 5_15k forbidden",
4689 "amr-config 4_75k allowed"
4690 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004691}
4692
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004693private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
4694 var charstring tch;
4695 if (fr) {
4696 tch := "tch-f";
4697 } else {
4698 tch := "tch-h";
4699 }
4700 f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
4701}
4702
4703/* Set the AMR start-mode for this TCH back to the default configuration. */
4704private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
4705 f_vty_amr_start_mode_set(fr, "auto");
4706}
4707
Harald Welte60aa5762018-03-21 19:33:13 +01004708testcase TC_assignment_codec_amr_f() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004709 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004710 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004711
4712 /* Note: This setups the codec configuration. The parameter payload in
4713 * mr_conf must be consistant with the parameter codecElements in pars
4714 * and also must match the amr-config in osmo-bsc.cfg! */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004715 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004716 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004717 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004718 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004719
Harald Welte60aa5762018-03-21 19:33:13 +01004720 f_init(1, true);
4721 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004722 f_vty_amr_start_mode_set(true, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004723 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004724
Harald Welte8863fa12018-05-10 20:15:27 +02004725 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004726 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004727
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004728 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4729 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4730 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4731 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4732 f_ctrs_bts_verify();
4733
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004734 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004735 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004736}
4737
4738testcase TC_assignment_codec_amr_h() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004739 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004740 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004741
4742 /* See note above */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004743 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004744 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004745 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004746 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004747
Harald Welte60aa5762018-03-21 19:33:13 +01004748 f_init(1, true);
4749 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004750 f_vty_amr_start_mode_set(false, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004751 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004752
Harald Welte8863fa12018-05-10 20:15:27 +02004753 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004754 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004755
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004756 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4757 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4758 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4759 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4760 f_ctrs_bts_verify();
4761
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004762 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004763 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004764}
4765
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004766/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
4767testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
4768 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4769 var MSC_ConnHdlr vc_conn;
4770
4771 f_init(1, true);
4772 f_sleep(1.0);
4773
4774 /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
4775 * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
4776 * expecting a Channel Mode Modify if the channel type is compatible. */
4777 f_disable_all_sdcch();
4778 f_disable_all_tch_h();
4779
4780 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4781 pars.expect_channel_mode_modify := true;
4782 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4783 vc_conn.done;
4784
4785 f_enable_all_sdcch();
4786 f_enable_all_tch();
4787 f_shutdown_helper();
4788}
4789
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004790/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
4791testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
4792 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4793 var MSC_ConnHdlr vc_conn;
4794
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004795 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4796 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
4797 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy36fe9582022-09-14 15:25:04 +07004798 pars.expect_mr_conf_ie := c_mr_conf_5_90;
4799 pars.expect_mr_conf_ie.multirate_cfg.icmi := false; /* expect ICMI=0, smod=00: */
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004800
4801 f_init(1, true);
4802 f_sleep(1.0);
4803
4804 /* First set nonzero start mode bits */
4805 f_vty_amr_start_mode_set(true, "4");
4806 /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
4807 * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
4808 * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
4809 f_vty_amr_start_mode_set(true, "auto");
4810
4811 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4812 vc_conn.done;
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004813
4814 /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
4815 f_vty_amr_start_mode_set(true, "1");
4816 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004817 f_shutdown_helper();
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004818}
4819
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004820function f_TC_assignment_codec_amr(boolean fr, RSL_IE_MultirateCfg mr_cfg,
4821 bitstring s8_s0, bitstring exp_s8_s0,
4822 charstring start_mode := "1")
Philipp Maierd0e64b02019-03-13 14:15:23 +01004823runs on test_CT {
4824
4825 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4826 var MSC_ConnHdlr vc_conn;
4827
Philipp Maierd0e64b02019-03-13 14:15:23 +01004828 if (fr) {
4829 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4830 } else {
4831 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4832 }
4833 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4834 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004835 pars.expect_mr_conf_ie := { multirate_cfg := mr_cfg };
Philipp Maierd0e64b02019-03-13 14:15:23 +01004836 pars.expect_mr_s0_s7 := exp_s8_s0;
4837
4838 f_init(1, true);
4839 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004840 f_vty_amr_start_mode_set(fr, start_mode);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004841 f_sleep(1.0);
4842
4843 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4844 vc_conn.done;
4845 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004846 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004847}
4848
4849function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
4850runs on test_CT {
4851
4852 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4853 var MSC_ConnHdlr vc_conn;
4854
4855 if (fr) {
4856 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4857 } else {
4858 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4859 }
4860 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4861 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4862
4863 f_init(1, true);
4864 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004865 f_vty_amr_start_mode_set(fr, "1");
Philipp Maierd0e64b02019-03-13 14:15:23 +01004866 f_sleep(1.0);
4867
4868 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
4869 vc_conn.done;
4870 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004871 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004872}
4873
Philipp Maierd0e64b02019-03-13 14:15:23 +01004874/* Set S1, we expect an AMR multirate configuration IE with all four rates
4875 * set. */
4876testcase TC_assignment_codec_amr_f_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004877 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4878 params := '20882208'O));
4879 f_TC_assignment_codec_amr(true, mr_cfg, '00000011'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004880 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004881}
4882
4883/* Set S1, we expect an AMR multirate configuration IE with the lower three
4884 * rates set. */
4885testcase TC_assignment_codec_amr_h_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004886 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4887 params := '208820'O));
4888 f_TC_assignment_codec_amr(false, mr_cfg, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004889 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004890}
4891
4892/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4893 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4894testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004895 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4896 params := '20882208'O));
4897 f_TC_assignment_codec_amr(true, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004898 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004899}
4900
4901/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4902 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4903testcase TC_assignment_codec_amr_h_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004904 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4905 params := '208820'O));
4906 f_TC_assignment_codec_amr(false, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004907 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004908}
4909
4910/* The following block of tests selects more and more rates until all four
4911 * possible rates are in the active set (full rate) */
4912testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004913 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4914 f_TC_assignment_codec_amr(true, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004915 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004916}
4917
4918testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004919 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4920 params := '2080'O));
4921 f_TC_assignment_codec_amr(true, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004922 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004923}
4924
4925testcase TC_assignment_codec_amr_f_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004926 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4927 params := '208820'O));
4928 f_TC_assignment_codec_amr(true, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004929 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004930}
4931
4932testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004933 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4934 params := '20882208'O));
4935 f_TC_assignment_codec_amr(true, mr_cfg, '10010101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004936 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004937}
4938
4939/* The following block of tests selects more and more rates until all three
4940 * possible rates are in the active set (half rate) */
4941testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004942 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4943 f_TC_assignment_codec_amr(false, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004944 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004945}
4946
4947testcase TC_assignment_codec_amr_h_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004948 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4949 params := '2080'O));
4950 f_TC_assignment_codec_amr(false, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004951 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004952}
4953
4954testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004955 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4956 params := '208820'O));
4957 f_TC_assignment_codec_amr(false, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004958 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004959}
4960
4961/* The following block tests what happens when the MSC does offer rate
4962 * configurations that are not supported by the BSC. Normally such situations
4963 * should not happen because the MSC gets informed by the BSC in advance via
4964 * the L3 COMPLETE message which rates are applicable. The MSC should not try
4965 * to offer rates that are not applicable anyway. */
4966
4967testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004968 /* Try to include 12,2k in into the active set even though the channel
4969 * is half rate only. The BSC is expected to remove the 12,0k */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004970 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4971 params := '208820'O));
4972 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004973 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004974}
4975
4976testcase TC_assignment_codec_amr_f_S01234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004977 /* See what happens when all rates are selected at once. Since then
4978 * Also S1 is selected, this setting will be prefered and we should
4979 * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004980 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4981 params := '20882208'O));
4982 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004983 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004984}
4985
4986testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004987 /* Same as above, but with S1 missing, the MSC is then expected to
4988 * select the currently supported rates, which are also 12.2k, 7,40k,
4989 * 5,90k, and 4,75k, into the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004990 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4991 params := '20882208'O));
4992 f_TC_assignment_codec_amr(true, mr_cfg, '11111101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004993 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004994}
4995
4996testcase TC_assignment_codec_amr_f_zero() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004997 /* Try to select no rates at all */
4998 f_TC_assignment_codec_amr_fail(true, '00000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004999 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01005000}
5001
5002testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02005003 /* Try to select only unsupported rates */
5004 f_TC_assignment_codec_amr_fail(true, '01101000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005005 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01005006}
5007
5008testcase TC_assignment_codec_amr_h_S7() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02005009 /* Try to select 12,2k for half rate */
5010 f_TC_assignment_codec_amr_fail(false, '10000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005011 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01005012}
5013
Neels Hofmeyr21863562020-11-26 00:34:33 +00005014testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07005015 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
5016 codec_modes := '10010101'B,
5017 params := '20882208'O));
5018 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01005019 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00005020}
5021
5022testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07005023 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
5024 codec_modes := '00010101'B,
5025 params := '208820'O));
5026 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B,
Neels Hofmeyr21863562020-11-26 00:34:33 +00005027 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01005028 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00005029}
5030
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00005031testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01005032 /* "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 +07005033 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 3,
5034 codec_modes := '10010101'B,
5035 params := '20882208'O));
5036 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01005037 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00005038}
5039
5040testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01005041 /* "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 +07005042 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 2,
5043 codec_modes := '00010101'B,
5044 params := '208820'O));
5045 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01005046 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00005047}
5048
Philipp Maierac09bfc2019-01-08 13:41:39 +01005049private function f_disable_all_tch_f() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005050 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 borken");
5051 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 borken");
5052 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 borken");
5053 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005054}
5055
5056private function f_disable_all_tch_h() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005057 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 borken");
5058 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005059}
5060
5061private function f_enable_all_tch() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005062 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 unused");
5063 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 unused");
5064 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 unused");
5065 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 unused");
5066 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 unused");
5067 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005068}
5069
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02005070private function f_disable_all_sdcch() runs on test_CT {
5071 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
5072 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
5073 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
5074 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
5075}
5076
5077private function f_enable_all_sdcch() runs on test_CT {
5078 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
5079 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
5080 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
5081 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
5082}
5083
Philipp Maierac09bfc2019-01-08 13:41:39 +01005084/* Allow HR only */
5085private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs on MSC_ConnHdlr {
5086 g_pars := f_gen_test_hdlr_pars();
5087 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5088 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5089 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5090 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5091 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5092 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5093 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005094 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005095}
5096
5097/* Allow FR only */
5098private function f_TC_assignment_codec_xr_exhausted_req_fr(charstring id) runs on MSC_ConnHdlr {
5099 g_pars := f_gen_test_hdlr_pars();
5100 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5101 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5102 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5103 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5104 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5105 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5106 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005107 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005108}
5109
5110/* Allow HR only (expect assignment failure) */
5111private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) runs on MSC_ConnHdlr {
5112 g_pars := f_gen_test_hdlr_pars();
5113 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5114 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5115 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5116 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5117 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5118 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5119 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005120 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005121}
5122
5123/* Allow FR only (expect assignment failure) */
5124private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) runs on MSC_ConnHdlr {
5125 g_pars := f_gen_test_hdlr_pars();
5126 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5127 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5128 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5129 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5130 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5131 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5132 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005133 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005134}
5135
5136/* Allow FR and HR, but prefer FR */
5137private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5138 g_pars := f_gen_test_hdlr_pars();
5139 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5140 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5141 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5142 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5143 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5144 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5145 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5146 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005147 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005148}
5149
5150/* Allow FR and HR, but prefer HR */
5151private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5152 g_pars := f_gen_test_hdlr_pars();
5153 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5154 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5155 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5156 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5157 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5158 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5159 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5160 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005161 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005162}
5163
5164/* Allow FR and HR, but prefer FR */
5165private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5166 g_pars := f_gen_test_hdlr_pars();
5167 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5168 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5169 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5170 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5171 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5172 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5173 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5174 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005175 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005176}
5177
5178/* Allow FR and HR, but prefer HR */
5179private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5180 g_pars := f_gen_test_hdlr_pars();
5181 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5182 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5183 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5184 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5185 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5186 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5187 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5188 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005189 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005190}
5191
5192/* Request a HR channel while all FR channels are exhausted, this is expected
5193 * to work without conflicts */
5194testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
5195 var MSC_ConnHdlr vc_conn;
5196 f_init(1, true);
5197 f_sleep(1.0);
5198 f_enable_all_tch();
5199 f_disable_all_tch_f();
5200 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
5201 vc_conn.done;
5202 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005203 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005204}
5205
5206/* Request a FR channel while all FR channels are exhausted, this is expected
5207 * to fail. */
5208testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
5209 var MSC_ConnHdlr vc_conn;
5210 f_init(1, true);
5211 f_sleep(1.0);
5212 f_enable_all_tch();
5213 f_disable_all_tch_f();
5214 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
5215 vc_conn.done;
5216 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005217 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005218}
5219
5220/* Request a FR (prefered) or alternatively a HR channel while all FR channels
5221 * are exhausted, this is expected to be resolved by selecting a HR channel. */
5222testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
5223 var MSC_ConnHdlr vc_conn;
5224 f_init(1, true);
5225 f_sleep(1.0);
5226 f_enable_all_tch();
5227 f_disable_all_tch_f();
5228 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
5229 vc_conn.done;
5230 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005231 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005232}
5233
5234/* Request a HR (prefered) or alternatively a FR channel while all FR channels
5235 * are exhausted, this is expected to work without conflicts. */
5236testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
5237 var MSC_ConnHdlr vc_conn;
5238 f_init(1, true);
5239 f_sleep(1.0);
5240 f_enable_all_tch();
5241 f_disable_all_tch_f();
5242 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
5243 vc_conn.done;
5244 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005245 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005246}
5247
5248/* Request a FR channel while all HR channels are exhausted, this is expected
5249 * to work without conflicts */
5250testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
5251 var MSC_ConnHdlr vc_conn;
5252 f_init(1, true);
5253 f_sleep(1.0);
5254 f_enable_all_tch();
5255 f_disable_all_tch_h();
5256 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
5257 vc_conn.done;
5258 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005259 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005260}
5261
5262/* Request a HR channel while all HR channels are exhausted, this is expected
5263 * to fail. */
5264testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
5265 var MSC_ConnHdlr vc_conn;
5266 f_init(1, true);
5267 f_sleep(1.0);
5268 f_enable_all_tch();
5269 f_disable_all_tch_h();
5270 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
5271 vc_conn.done;
5272 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005273 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005274}
5275
5276/* Request a HR (prefered) or alternatively a FR channel while all HR channels
5277 * are exhausted, this is expected to be resolved by selecting a FR channel. */
5278testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
5279 var MSC_ConnHdlr vc_conn;
5280 f_init(1, true);
5281 f_sleep(1.0);
5282 f_enable_all_tch();
5283 f_disable_all_tch_h();
5284 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
5285 vc_conn.done;
5286 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005287 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005288}
5289
5290/* Request a FR (prefered) or alternatively a HR channel while all HR channels
5291 * are exhausted, this is expected to work without conflicts. */
5292testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
5293 var MSC_ConnHdlr vc_conn;
5294 f_init(1, true);
5295 f_sleep(1.0);
5296 f_enable_all_tch();
5297 f_disable_all_tch_h();
5298 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
5299 vc_conn.done;
5300 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005301 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005302}
5303
5304/* Allow FR and HR, but prefer HR */
5305private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5306 g_pars := f_gen_test_hdlr_pars();
5307 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5308 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5309 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5310 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5311 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5312 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5313 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5314 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005315 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005316}
5317
5318/* Allow FR and HR, but prefer FR */
5319private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5320 g_pars := f_gen_test_hdlr_pars();
5321 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5322 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5323 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5324 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5325 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5326 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5327 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5328 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005329 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005330}
5331
5332/* Request a HR (prefered) or alternatively a FR channel, it is expected that
5333 * HR, which is the prefered type, is selected. */
5334testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
5335 var MSC_ConnHdlr vc_conn;
5336 f_init(1, true);
5337 f_sleep(1.0);
5338 f_enable_all_tch();
5339 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
5340 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005341 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005342}
5343
5344/* Request a FR (prefered) or alternatively a HR channel, it is expected that
5345 * FR, which is the prefered type, is selected. */
5346testcase TC_assignment_codec_req_fr_hr() runs on test_CT {
5347 var MSC_ConnHdlr vc_conn;
5348 f_init(1, true);
5349 f_sleep(1.0);
5350 f_enable_all_tch();
5351 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_fr_hr));
5352 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005353 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005354}
5355
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005356/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
5357private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
5358 g_pars := f_gen_test_hdlr_pars();
5359 g_pars.ra := '02'O; /* RA containing reason=LU */
5360
5361 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5362 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5363 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5364 var template uint3_t tsc := ?;
5365
5366 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5367 f_create_bssmap_exp(l3_enc);
5368 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5369 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5370
5371 /* we should now have a COMPL_L3 at the MSC */
5372 timer T := 10.0;
5373 T.start;
5374 alt {
5375 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5376 [] T.timeout {
5377 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5378 }
5379 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005380
5381 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005382}
5383testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
5384 var MSC_ConnHdlr vc_conn;
5385 f_init(1, true);
5386 f_sleep(1.0);
5387 f_disable_all_sdcch();
5388 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
5389 vc_conn.done;
5390 f_enable_all_sdcch();
5391 f_shutdown_helper();
5392}
5393
5394/* Request a signalling channel with all SDCCH exhausted, it is
5395 expected that no TCH will be selected for signalling and assigment will fail
5396 because it's dictated by VTY config */
5397testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
5398 var RSL_Message rsl_unused, rsl_msg;
5399 var GsmRrMessage rr;
5400 f_init(1, false);
5401 f_sleep(1.0);
5402 f_vty_allow_tch_for_signalling(false, 0);
5403 f_disable_all_sdcch();
5404
5405 /* RA containing reason=LU */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005406 f_ipa_tx(ts_RSL_CHAN_RQD('02'O, 2342));
5407 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005408 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
5409 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
5410 setverdict(fail, "Expected reject");
5411 }
5412
5413 f_vty_allow_tch_for_signalling(true, 0);
5414 f_enable_all_sdcch();
5415 f_shutdown_helper();
5416}
5417
5418/* Request a voice channel with all SDCCH exhausted, it is
5419 * expected that TCH channel will be allocated since the VTY option is only
5420 * aimed at signalling requests */
5421private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
5422 g_pars := f_gen_test_hdlr_pars();
5423 g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
5424
5425 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5426 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5427 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5428 var template uint3_t tsc := ?;
5429
5430 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5431 f_create_bssmap_exp(l3_enc);
5432 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5433 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5434
5435 /* we should now have a COMPL_L3 at the MSC */
5436 timer T := 10.0;
5437 T.start;
5438 alt {
5439 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5440 [] T.timeout {
5441 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5442 }
5443 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005444 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005445}
5446testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
5447 var MSC_ConnHdlr vc_conn;
5448 f_init(1, true);
5449 f_sleep(1.0);
5450 f_vty_allow_tch_for_signalling(false, 0);
5451 f_disable_all_sdcch();
5452
5453 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
5454 vc_conn.done;
5455
5456 f_vty_allow_tch_for_signalling(true, 0);
5457 f_enable_all_sdcch();
5458 f_shutdown_helper();
5459}
5460
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005461/* Test Osmux setup BSC<->MSC */
5462testcase TC_assignment_osmux_cn() runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005463 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5464 var MSC_ConnHdlr vc_conn;
5465
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005466 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5467 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5468 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiyb9bf00f2022-09-14 15:35:37 +07005469 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02005470 pars.use_osmux_cn := true;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005471
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02005472 g_osmux_enabled_cn := true;
5473 f_init(1, true);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005474 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005475 f_vty_amr_start_mode_set(false, "1");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005476
5477 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5478 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005479
5480 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01005481 f_shutdown_helper();
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005482}
5483
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005484/* Test Osmux setup BTS<->BSC */
5485testcase TC_assignment_osmux_bts() runs on test_CT {
5486 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5487 var MSC_ConnHdlr vc_conn;
5488
5489 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5490 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5491 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005492 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005493 pars.use_osmux_bts := true;
5494
5495 g_osmux_enabled_bts := true;
5496 f_init(1, true);
5497 f_sleep(1.0);
5498 f_vty_amr_start_mode_set(false, "1");
5499
5500 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5501 vc_conn.done;
5502
5503 f_vty_amr_start_mode_restore(false);
5504 f_shutdown_helper();
5505}
5506
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +02005507/* Test non-AMR codecs still work fine as RTP when Osmux is enabled BTS<->BSC<->MSC */
5508testcase TC_assignment_codec_hr_osmux_on() runs on test_CT {
5509 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5510 var MSC_ConnHdlr vc_conn;
5511
5512 g_osmux_enabled_cn := true;
5513 g_osmux_enabled_bts := true;
5514 f_init(1, true);
5515 f_sleep(1.0);
5516 f_ctrs_bsc_and_bts_assignment_init(1);
5517
5518 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5519 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5520 vc_conn.done;
5521
5522 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
5523 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
5524 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
5525 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
5526 f_ctrs_bts_verify();
5527
5528 f_shutdown_helper();
5529}
5530
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005531/* Test Osmux setup BTS<->BSC<->MSC */
5532testcase TC_assignment_osmux() runs on test_CT {
5533 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5534 var MSC_ConnHdlr vc_conn;
5535
5536 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5537 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5538 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005539 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005540 pars.use_osmux_cn := true;
5541 pars.use_osmux_bts := true;
5542
5543 g_osmux_enabled_cn := true;
5544 g_osmux_enabled_bts := true;
5545 f_init(1, true);
5546 f_sleep(1.0);
5547 f_vty_amr_start_mode_set(false, "1");
5548
5549 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5550 vc_conn.done;
5551
5552 f_vty_amr_start_mode_restore(false);
5553 f_shutdown_helper();
5554}
5555
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005556/* test the procedure of the MSC requesting a Classmark Update:
5557 * a) BSSMAP Classmark Request should result in RR CLASSMARK ENQUIRY,
5558 * b) L3 RR CLASSMARK CHANGE should result in BSSMAP CLASSMARK UPDATE */
Harald Welte898113b2018-01-31 18:32:21 +01005559private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005560 g_pars := f_gen_test_hdlr_pars();
5561
Harald Weltea0630032018-03-20 21:09:55 +01005562 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005563 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005564
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005565 BSSAP.send(ts_BSSMAP_ClassmarkRequest);
5566 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
5567
Harald Welte898113b2018-01-31 18:32:21 +01005568 f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
5569 BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
5570 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005571
5572 f_perform_clear();
Harald Welte898113b2018-01-31 18:32:21 +01005573}
5574testcase TC_classmark() runs on test_CT {
5575 var MSC_ConnHdlr vc_conn;
5576 f_init(1, true);
5577 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005578 vc_conn := f_start_handler(refers(f_tc_classmark));
Harald Welte898113b2018-01-31 18:32:21 +01005579 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005580 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005581}
5582
Harald Welteeddf0e92020-06-21 19:42:15 +02005583/* Send a CommonID from the simulated MSC and verify that the information is used to
5584 * fill BSC-internal data structures (specifically, bsc_subscr associated with subscr_conn) */
5585private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
5586 g_pars := f_gen_test_hdlr_pars();
5587 f_MscConnHdlr_init_vty();
5588
5589 f_create_chan_and_exp();
5590 /* we should now have a COMPL_L3 at the MSC */
Harald Welteeddf0e92020-06-21 19:42:15 +02005591
5592 /* Send CommonID */
5593 BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
5594
5595 /* Use VTY to verify that the IMSI of the subscr_conn is set */
5596 var charstring regex := "*(IMSI: " & hex2str(g_pars.imsi) & ")*";
5597 f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
5598
5599 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005600
5601 f_perform_clear();
Harald Welteeddf0e92020-06-21 19:42:15 +02005602}
5603testcase TC_common_id() runs on test_CT {
5604 var MSC_ConnHdlr vc_conn;
5605 f_init(1, true);
5606 f_sleep(1.0);
5607 vc_conn := f_start_handler(refers(f_tc_common_id));
5608 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005609 f_shutdown_helper();
Harald Welteeddf0e92020-06-21 19:42:15 +02005610}
5611
Harald Weltee3bd6582018-01-31 22:51:25 +01005612private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005613 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005614 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005615 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005616
Harald Weltee3bd6582018-01-31 22:51:25 +01005617 /* send the single message we want to send */
5618 f_rsl_send_l3(l3);
5619}
5620
5621private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr {
5622 timer T := sec;
5623 var PDU_BSSAP bssap;
Harald Welte898113b2018-01-31 18:32:21 +01005624 T.start;
5625 alt {
Harald Weltee3bd6582018-01-31 22:51:25 +01005626 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap {
5627 setverdict(fail, "Unexpected BSSMAP ", bssap);
Daniel Willmannafce8662018-07-06 23:11:32 +02005628 mtc.stop;
Harald Welte898113b2018-01-31 18:32:21 +01005629 }
5630 [] T.timeout {
5631 setverdict(pass);
5632 }
5633 }
5634}
5635
Harald Weltee3bd6582018-01-31 22:51:25 +01005636/* unsolicited ASSIGNMENT FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5637private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
5638 f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
5639 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005640 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005641}
Harald Welte898113b2018-01-31 18:32:21 +01005642testcase TC_unsol_ass_fail() runs on test_CT {
5643 var MSC_ConnHdlr vc_conn;
5644 f_init(1, true);
5645 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005646 vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
Harald Welte898113b2018-01-31 18:32:21 +01005647 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005648 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005649}
Harald Welte552620d2017-12-16 23:21:36 +01005650
Harald Welteea99a002018-01-31 20:46:43 +01005651
5652/* unsolicited ASSIGNMENT COMPLETE (without ASSIGN) from MS shouldn't bring BSC down */
5653private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005654 f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
5655 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005656 f_perform_clear();
Harald Welteea99a002018-01-31 20:46:43 +01005657}
5658testcase TC_unsol_ass_compl() runs on test_CT {
5659 var MSC_ConnHdlr vc_conn;
5660 f_init(1, true);
5661 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005662 vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
Harald Welteea99a002018-01-31 20:46:43 +01005663 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005664 f_shutdown_helper();
Harald Welteea99a002018-01-31 20:46:43 +01005665}
5666
5667
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005668/* unsolicited HANDOVER FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5669private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005670 f_est_single_l3(ts_RRM_HandoverFailure('00'O));
5671 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005672 f_perform_clear();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005673}
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005674testcase TC_unsol_ho_fail() runs on test_CT {
5675 var MSC_ConnHdlr vc_conn;
5676 f_init(1, true);
5677 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005678 vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005679 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005680 f_shutdown_helper();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005681}
5682
5683
Harald Weltee3bd6582018-01-31 22:51:25 +01005684/* short message from MS should be ignored */
5685private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005686 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005687 f_create_chan_and_exp();
Harald Weltee3bd6582018-01-31 22:51:25 +01005688 /* we should now have a COMPL_L3 at the MSC */
Harald Weltee3bd6582018-01-31 22:51:25 +01005689
5690 /* send short message */
5691 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
5692 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005693 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005694}
5695testcase TC_err_82_short_msg() runs on test_CT {
5696 var MSC_ConnHdlr vc_conn;
5697 f_init(1, true);
5698 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005699 vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
Harald Weltee3bd6582018-01-31 22:51:25 +01005700 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005701 f_shutdown_helper();
Harald Weltee3bd6582018-01-31 22:51:25 +01005702}
5703
Harald Weltee9e02e42018-01-31 23:36:25 +01005704/* 24.008 8.4 Unknown message must trigger RR STATUS */
5705private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
Andreas Eversberg9ff96e62023-07-25 12:37:42 +02005706 f_est_single_l3(ts_RRM_DTM_ASS_FAIL('00'O));
Harald Weltee9e02e42018-01-31 23:36:25 +01005707 timer T := 3.0
5708 alt {
5709 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
5710 setverdict(pass);
5711 }
5712 [] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
Harald Welte458fd372018-03-21 11:26:23 +01005713 [] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
Harald Weltee9e02e42018-01-31 23:36:25 +01005714 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005715 f_perform_clear();
Harald Weltee9e02e42018-01-31 23:36:25 +01005716}
5717testcase TC_err_84_unknown_msg() runs on test_CT {
5718 var MSC_ConnHdlr vc_conn;
5719 f_init(1, true);
5720 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005721 vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
Harald Weltee9e02e42018-01-31 23:36:25 +01005722 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005723 f_shutdown_helper();
Harald Weltee9e02e42018-01-31 23:36:25 +01005724}
5725
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005726/***********************************************************************
5727 * Handover
5728 ***********************************************************************/
5729
Harald Welte94e0c342018-04-07 11:33:23 +02005730/* execute a "bts <0-255> trx <0-255> timeslot <0-7> " command on given Dchan */
5731private function f_vty_ts_action(charstring suffix, integer bts_nr, integer trx_nr, integer ts_nr)
5732runs on test_CT {
5733 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5734 " timeslot "&int2str(ts_nr)&" ";
5735 f_vty_transceive(BSCVTY, cmd & suffix);
5736}
5737
Harald Welte261af4b2018-02-12 21:20:39 +01005738/* 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 +07005739private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
5740 uint8_t bts_nr, uint8_t trx_nr,
5741 in RslChannelNr chan_nr)
5742{
Harald Welte261af4b2018-02-12 21:20:39 +01005743 /* FIXME: resolve those from component-global state */
5744 var integer ts_nr := chan_nr.tn;
5745 var integer ss_nr;
5746 if (ischosen(chan_nr.u.ch0)) {
5747 ss_nr := 0;
5748 } else if (ischosen(chan_nr.u.lm)) {
5749 ss_nr := chan_nr.u.lm.sub_chan;
5750 } else if (ischosen(chan_nr.u.sdcch4)) {
5751 ss_nr := chan_nr.u.sdcch4.sub_chan;
5752 } else if (ischosen(chan_nr.u.sdcch8)) {
5753 ss_nr := chan_nr.u.sdcch8.sub_chan;
5754 } else {
5755 setverdict(fail, "Invalid ChanNr ", chan_nr);
Daniel Willmannafce8662018-07-06 23:11:32 +02005756 mtc.stop;
Harald Welte261af4b2018-02-12 21:20:39 +01005757 }
5758
5759 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5760 " timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005761 f_vty_transceive(pt, cmd & suffix);
Harald Welte261af4b2018-02-12 21:20:39 +01005762}
5763
Neels Hofmeyr91401012019-07-11 00:42:35 +02005764/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
5765 * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor
5766 * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
5767 * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
5768 * pair, not really to a specific BTS number. */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005769private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
5770 in RslChannelNr chan_nr, uint8_t new_bts_nr)
5771{
5772 f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
Harald Welte261af4b2018-02-12 21:20:39 +01005773}
5774
5775/* intra-BSC hand-over between BTS0 and BTS1 */
5776private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02005777 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5778 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte261af4b2018-02-12 21:20:39 +01005779
5780 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5781 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5782
Harald Weltea0630032018-03-20 21:09:55 +01005783 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005784 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Harald Welte261af4b2018-02-12 21:20:39 +01005785
5786 var HandoverState hs := {
5787 rr_ho_cmpl_seen := false,
5788 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005789 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005790 expect_target_tsc := c_BtsParams[1].tsc
Harald Welte261af4b2018-02-12 21:20:39 +01005791 };
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005792 /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005793 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
Harald Welte261af4b2018-02-12 21:20:39 +01005794 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5795 f_rslem_suspend(RSL1_PROC);
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005796
5797 /* From the MGW perspective, a handover is is characterized by
5798 * performing one MDCX operation with the MGW. So we expect to see
5799 * one more MDCX during handover. */
5800 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5801
Harald Welte261af4b2018-02-12 21:20:39 +01005802 alt {
5803 [] as_handover(hs);
Harald Welte261af4b2018-02-12 21:20:39 +01005804 }
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005805
Philipp Maier4dae0652018-11-12 12:03:26 +01005806 /* Since this is an internal handover we expect the BSC to inform the
5807 * MSC about the event */
5808 BSSAP.receive(tr_BSSMAP_HandoverPerformed);
5809
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005810 /* Check the amount of MGCP transactions is still consistant with the
5811 * test expectation */
5812 f_check_mgcp_expectations()
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005813
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005814 var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
5815
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005816 /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
5817 * 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 +02005818 f_verify_encr_info(chan_act);
5819
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005820 f_chan_act_verify_tsc(chan_act, c_BtsParams[1].tsc);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005821
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005822 f_perform_clear(RSL1, RSL1_PROC);
5823
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005824 f_sleep(0.5);
Harald Welte261af4b2018-02-12 21:20:39 +01005825}
5826
5827testcase TC_ho_int() runs on test_CT {
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005828 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte261af4b2018-02-12 21:20:39 +01005829 var MSC_ConnHdlr vc_conn;
5830 f_init(2, true);
5831 f_sleep(1.0);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005832
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005833 pars.expect_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005834
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005835 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005836
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005837 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
Harald Welte261af4b2018-02-12 21:20:39 +01005838 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005839
5840 /* from f_establish_fully() */
5841 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5842 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5843 /* from handover */
5844 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5845 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5846 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5847 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005848 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5849 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005850 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005851 f_shutdown_helper(ho := true);
Harald Welte261af4b2018-02-12 21:20:39 +01005852}
Harald Weltee9e02e42018-01-31 23:36:25 +01005853
Oliver Smith7eabd312021-07-12 14:18:56 +02005854function 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 +02005855 var MSC_ConnHdlr vc_conn;
5856 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5857 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
5858
5859 f_init(2, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02005860 f_vty_encryption_a5(enc_a5);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005861 f_sleep(1.0);
5862
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005863 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005864
5865 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
5866 vc_conn.done;
5867
5868 /* from f_establish_fully() */
5869 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5870 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5871 /* from handover */
5872 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5873 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5874 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5875 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005876 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5877 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005878 f_ctrs_bsc_and_bts_verify();
Oliver Smith7eabd312021-07-12 14:18:56 +02005879 f_vty_encryption_a5_reset();
Oliver Smith39f53072022-10-27 14:44:04 +02005880 f_shutdown_helper(ho := true);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005881}
5882
5883testcase TC_ho_int_a5_0() runs on test_CT {
5884 f_tc_ho_int_a5('01'O);
5885}
5886
5887testcase TC_ho_int_a5_1() runs on test_CT {
5888 f_tc_ho_int_a5('02'O);
5889}
5890
5891testcase TC_ho_int_a5_3() runs on test_CT {
5892 f_tc_ho_int_a5('08'O);
5893}
5894
5895testcase TC_ho_int_a5_4() runs on test_CT {
Oliver Smith7eabd312021-07-12 14:18:56 +02005896 f_tc_ho_int_a5('10'O, "0 1 3 4");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005897}
5898
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005899/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
5900private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
5901 g_pars := f_gen_test_hdlr_pars();
5902 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5903 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005904
5905 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5906 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5907
5908 f_establish_fully(ass_cmd, exp_compl);
5909 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
5910
5911 var HandoverState hs := {
5912 rr_ho_cmpl_seen := false,
5913 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005914 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005915 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005916 };
5917 /* issue hand-over command on VTY */
5918 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
5919 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5920 f_rslem_suspend(RSL1_PROC);
5921
5922 /* From the MGW perspective, a handover is is characterized by
5923 * performing one MDCX operation with the MGW. So we expect to see
5924 * one more MDCX during handover. */
5925 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5926
5927 var RSL_Message rsl;
5928 var PDU_ML3_NW_MS l3;
5929 var RslChannelNr new_chan_nr;
5930 var GsmArfcn arfcn;
5931 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
5932 l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
5933 if (not ischosen(l3.msgs.rrm.handoverCommand)) {
5934 setverdict(fail, "Expected handoverCommand");
5935 mtc.stop;
5936 }
5937 }
5938 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
5939 new_chan_nr, arfcn);
5940
5941 f_rslem_register(0, new_chan_nr, RSL1_PROC);
5942
5943 /* resume processing of RSL DChan messages, which was temporarily suspended
5944 * before performing a hand-over */
5945 f_rslem_resume(RSL1_PROC);
5946 RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
5947
5948 f_sleep(1.0);
5949
5950 /* Handover fails because no HANDO DET appears on the new lchan,
5951 * and the old lchan reports a Radio Link Failure. */
5952 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
5953
5954 var PDU_BSSAP rx_clear_request;
5955 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5956 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5957 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5958
5959 var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
5960
5961 var MgcpCommand mgcp;
5962 interleave {
5963 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
5964 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005965 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005966 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005967 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005968 }
5969 [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005970 [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005971 RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005972 f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005973 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005974 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5975 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5976 }
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005977 }
5978
5979 f_sleep(0.5);
5980 setverdict(pass);
5981}
5982testcase TC_ho_int_radio_link_failure() runs on test_CT {
5983 var MSC_ConnHdlr vc_conn;
5984 f_init(2, true);
5985 f_sleep(1.0);
5986
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005987 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005988
5989 vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
5990 vc_conn.done;
5991
5992 /* from f_establish_fully() */
5993 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5994 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5995 /* from handover */
5996 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5997 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
5998 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5999 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006000 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
6001 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
Neels Hofmeyr5f144212020-11-03 15:41:58 +00006002 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006003 f_shutdown_helper(ho := true);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00006004}
6005
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006006/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006007private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006008 var MgcpCommand mgcp;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02006009 var template MgcpResponse mgcp_resp;
6010 var MGCP_RecvFrom mrf;
6011 var template MgcpMessage msg_resp;
6012 var template MgcpMessage msg_dlcx := {
6013 command := tr_DLCX()
6014 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006015
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02006016 if (g_pars.aoip) {
6017 MGCP.receive(tr_DLCX()) -> value mgcp {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006018 log("Got first DLCX: ", mgcp);
6019 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02006020 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006021
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006022 MGCP.receive(tr_DLCX()) -> value mgcp {
6023 log("Got second DLCX: ", mgcp);
6024 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
6025 };
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02006026 } else {
6027 /* For SCCPLite, BSC doesn't handle the MSC-side */
6028 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
6029 log("Got first DLCX: ", mrf.msg.command);
6030 msg_resp := {
6031 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
6032 }
6033 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
6034 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006035 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006036}
6037
Oliver Smithc9a5f532022-10-21 11:32:23 +02006038private function f_ho_out_of_this_bsc(template (omit) BSSMAP_oldToNewBSSIEs exp_oldToNewBSSIEs := omit,
6039 boolean skip_meas_rep := false) runs on MSC_ConnHdlr {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006040
Oliver Smithc9a5f532022-10-21 11:32:23 +02006041 if (not skip_meas_rep) {
6042 var NcellReports neighbor_rep := {
6043 { rxlev := 20, bcch_freq := 0, bsic := 11 }
6044 };
6045 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
6046 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
6047 l3_mr, 0));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006048
Oliver Smithc9a5f532022-10-21 11:32:23 +02006049 BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
6050 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006051
6052 f_sleep(0.5);
6053 /* The MSC negotiates Handover Request and Handover Request Ack with
6054 * the other BSS and comes back with a BSSMAP Handover Command
6055 * containing an RR Handover Command coming from the target BSS... */
6056
6057 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6058 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6059 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6060 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6061 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6062
6063 /* expect the Handover Command to go out on RR */
6064 var RSL_Message rsl_ho_cmd
6065 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6066 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6067 var RSL_IE_Body rsl_ho_cmd_l3;
6068 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6069 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6070 setverdict(fail);
6071 } else {
6072 log("Found L3 Info: ", rsl_ho_cmd_l3);
6073 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6074 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6075 setverdict(fail);
6076 } else {
6077 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6078 setverdict(pass);
6079 }
6080 }
6081
6082 /* When the other BSS has reported a completed handover, this side is
6083 * torn down. */
6084
6085 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_HANDOVER_SUCCESSFUL;
6086 var BssmapCause cause := enum2int(cause_val);
6087 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6088
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006089 f_expect_dlcx_conns();
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006090
6091 interleave {
6092 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
6093 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
6094 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006095 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
6096 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
6097 }
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006098 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006099 setverdict(pass);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006100}
6101
6102private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
6103 g_pars := f_gen_test_hdlr_pars();
6104 var PDU_BSSAP ass_req := f_gen_ass_req();
6105 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6106 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6107 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6108 f_establish_fully(ass_req, exp_compl);
6109
6110 f_ho_out_of_this_bsc();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006111}
6112testcase TC_ho_out_of_this_bsc() runs on test_CT {
6113 var MSC_ConnHdlr vc_conn;
6114
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006115 f_init_vty();
6116 f_bts_0_cfg(BSCVTY,
6117 {"neighbor-list mode automatic",
6118 "handover 1",
6119 "handover algorithm 2",
6120 "handover2 window rxlev averaging 1",
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006121 "no neighbors",
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006122 "neighbor lac 99 arfcn 123 bsic any"});
6123 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6124
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006125 f_init(1, true);
6126 f_sleep(1.0);
6127
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006128 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006129
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006130 vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
6131 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006132
6133 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6134 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6135 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6136 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6137 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6138 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
6139 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006140 f_shutdown_helper(ho := true);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006141}
6142
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006143private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6144 template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
Vadim Yanitskiy2ef6a2f2020-10-08 23:17:32 +07006145 template (present) OCT1 dlci := ?,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006146 octetstring l3 := '0123456789'O)
6147runs on MSC_ConnHdlr {
Neels Hofmeyr43654812020-09-25 01:35:35 +02006148 /* The old lchan and conn should still be active. See that arbitrary L3
6149 * is still going through. */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006150 rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
Neels Hofmeyr43654812020-09-25 01:35:35 +02006151 var template PDU_BSSAP exp_data := {
6152 discriminator := '1'B,
6153 spare := '0000000'B,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006154 dlci := dlci,
6155 lengthIndicator := lengthof(l3),
Neels Hofmeyr43654812020-09-25 01:35:35 +02006156 pdu := {
6157 dtap := l3
6158 }
6159 };
6160 BSSAP.receive(exp_data);
6161 setverdict(pass);
6162}
6163
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006164private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6165 template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006166 template (value) OCT1 dlci := '00'O,
6167 octetstring l3 := '0123456789'O)
6168runs on MSC_ConnHdlr {
6169 BSSAP.send(PDU_BSSAP:{
6170 discriminator := '1'B,
6171 spare := '0000000'B,
6172 dlci := dlci,
6173 lengthIndicator := lengthof(l3),
6174 pdu := {
6175 dtap := l3
6176 }
6177 });
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006178 rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006179 setverdict(pass);
6180}
6181
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006182/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
6183 * simply never sends a BSSMAP Handover Command. */
6184private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006185 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006186
6187 var PDU_BSSAP ass_req := f_gen_ass_req();
6188 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6189 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6190 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6191 f_establish_fully(ass_req, exp_compl);
6192
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006193 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006194 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6195
6196 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6197
6198 /* osmo-bsc should time out 10 seconds after the handover started.
6199 * Let's give it a bit extra. */
6200 f_sleep(15.0);
6201
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006202 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006203 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006204 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006205}
6206testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
6207 var MSC_ConnHdlr vc_conn;
6208
6209 f_init(1, true);
6210 f_sleep(1.0);
6211
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006212 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006213
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006214 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
6215 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006216
6217 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6218 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6219 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6220 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6221 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6222 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6223 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006224 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006225}
6226
6227/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
6228 * RR Handover Failure. */
6229private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006230 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006231
6232 var PDU_BSSAP ass_req := f_gen_ass_req();
6233 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6234 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6235 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6236 f_establish_fully(ass_req, exp_compl);
6237
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006238 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006239 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6240
6241 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6242
6243 f_sleep(0.5);
6244 /* The MSC negotiates Handover Request and Handover Request Ack with
6245 * the other BSS and comes back with a BSSMAP Handover Command
6246 * containing an RR Handover Command coming from the target BSS... */
6247
6248 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6249 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6250 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6251 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6252 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6253
6254 /* expect the Handover Command to go out on RR */
6255 var RSL_Message rsl_ho_cmd
6256 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6257 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6258 var RSL_IE_Body rsl_ho_cmd_l3;
6259 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6260 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6261 setverdict(fail);
6262 } else {
6263 log("Found L3 Info: ", rsl_ho_cmd_l3);
6264 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6265 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6266 setverdict(fail);
6267 } else {
6268 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6269 setverdict(pass);
6270 }
6271 }
6272
6273 f_sleep(0.2);
6274 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
6275
6276 /* Should tell the MSC about the failure */
6277 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6278
6279 f_sleep(1.0);
6280
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006281 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006282 f_sleep(1.0);
6283
6284 setverdict(pass);
6285 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006286 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006287}
6288testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
6289 var MSC_ConnHdlr vc_conn;
6290
6291 f_init(1, true);
6292 f_sleep(1.0);
6293
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006294 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006295
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006296 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
6297 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006298
6299 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6300 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6301 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6302 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6303 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6304 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
6305 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006306 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006307}
6308
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006309/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
6310 * (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 +02006311 * and the lchan is released. */
6312private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006313 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006314
6315 var PDU_BSSAP ass_req := f_gen_ass_req();
6316 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6317 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6318 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6319 f_establish_fully(ass_req, exp_compl);
6320
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006321 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006322 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6323
6324 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6325
6326 f_sleep(0.5);
6327 /* The MSC negotiates Handover Request and Handover Request Ack with
6328 * the other BSS and comes back with a BSSMAP Handover Command
6329 * containing an RR Handover Command coming from the target BSS... */
6330
6331 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6332 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6333 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6334 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6335 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6336
6337 /* expect the Handover Command to go out on RR */
6338 var RSL_Message rsl_ho_cmd
6339 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6340 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6341 var RSL_IE_Body rsl_ho_cmd_l3;
6342 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6343 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6344 setverdict(fail);
6345 } else {
6346 log("Found L3 Info: ", rsl_ho_cmd_l3);
6347 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6348 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6349 setverdict(fail);
6350 } else {
6351 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6352 setverdict(pass);
6353 }
6354 }
6355
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006356 /* We get neither success nor failure report from the remote BSS. Eventually T8 times out and we run into 3GPP
6357 * TS 48.008 3.1.5.3.3 "Abnormal Conditions": Clear Request should go to the MSC, and RR should be released
6358 * after Clear Command */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006359
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006360 var PDU_BSSAP rx_clear_request;
Neels Hofmeyre1797aa2019-07-09 19:34:04 +02006361 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
6362 log("Got BSSMAP Clear Request");
6363 /* Instruct BSC to clear channel */
6364 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6365 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6366
6367 var MgcpCommand mgcp;
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006368 interleave {
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01006369 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
6370 log("Got Deact SACCH");
6371 }
Harald Welte924b6ea2019-02-04 01:05:34 +01006372 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
Neels Hofmeyr211169d2018-11-07 00:37:29 +01006373 log("Got RR Release");
6374 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02006375 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006376 log("Got RF Chan Rel");
6377 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02006378 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006379 }
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006380 }
6381
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006382 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006383 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006384 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006385
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006386 setverdict(pass);
6387 f_sleep(1.0);
6388}
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006389testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006390 var MSC_ConnHdlr vc_conn;
6391
6392 f_init(1, true);
6393 f_sleep(1.0);
6394
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006395 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006396
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006397 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006398 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006399
6400 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6401 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6402 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6403 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6404 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6405 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6406 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006407 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006408}
6409
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006410private 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 +01006411 var PDU_BSSAP rx_bssap;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006412 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6413 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6414 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6415 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6416 * before we get started. */
6417 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6418 f_rslem_register(0, new_chan_nr);
6419 g_chan_nr := new_chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06006420 var uint3_t expect_target_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006421 f_sleep(1.0);
6422
6423 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6424 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006425 var default as_media := activate(as_Media());
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006426
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01006427 var PDU_BSSAP ho_req := f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
6428 cell_id_source := g_pars.cell_id_source,
6429 oldToNewBSSIEs := oldToNewBSSIEs,
6430 enc := g_pars.encr);
6431 if (g_pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr) {
6432 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, ho_req));
6433 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6434 } else {
6435 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, omit));
6436 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6437 BSSAP.send(ho_req);
6438 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006439
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006440 alt {
6441 [] BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap {
6442 if (g_pars.expect_ho_fail) {
6443 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6444 "Expected Handover Request to fail, but got Handover Request Ack")
6445 }
6446 }
6447 [] BSSAP.receive(tr_BSSMAP_HandoverFailure) -> value rx_bssap {
6448 if (not g_pars.expect_ho_fail) {
6449 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6450 "Expected Handover Request to succeed, but got Handover Failure")
6451 }
6452 // TODO: evaluate correct cause value. But osmo-bsc doesn't seem to send meaningful causes yet!
6453 // For now just accept any cause.
6454 BSSAP.receive(tr_BSSMAP_ClearRequest);
6455 setverdict(pass);
6456 return;
6457 }
6458 }
6459
Oliver Smith7a8594a2023-02-13 14:30:49 +01006460 if (g_pars.expect_ho_fail_lchan_est) {
6461 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6462 setverdict(pass);
Oliver Smitha1cbec52023-02-21 12:44:12 +01006463
6464 /* When we let MGCP MDCX run into a timeout, it's still in the
6465 * queue and additionally after BSSAP HandoverFailure, two DLCX
Oliver Smith30eb8822023-03-06 12:31:53 +01006466 * get sent (for AoIP, for SCCPlite one DLCX). */
Oliver Smitha1cbec52023-02-21 12:44:12 +01006467 if (g_pars.ignore_mgw_mdcx) {
Oliver Smith30eb8822023-03-06 12:31:53 +01006468 if (g_pars.aoip) {
6469 MGCP.receive(tr_MDCX);
6470 MGCP.receive(tr_DLCX);
6471 MGCP.receive(tr_DLCX);
6472 } else {
6473 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_MDCX}));
6474 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_DLCX}));
6475 }
Oliver Smitha1cbec52023-02-21 12:44:12 +01006476 }
Oliver Smith7a8594a2023-02-13 14:30:49 +01006477 return;
6478 }
6479
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006480 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6481
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006482 /* we're sure that the channel activation is done now, verify the parameters in it */
6483 var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
6484 f_verify_encr_info(chan_act);
6485 f_chan_act_verify_tsc(chan_act, expect_target_tsc);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006486
Neels Hofmeyr46e16e52022-02-23 17:04:00 +01006487 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.codecList)) {
6488 if (not g_pars.aoip) {
6489 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6490 "handoverRequestAck: Expected no Speech Codec List (BSS Supported), because this is not AoIP");
6491 }
6492 /* TODO: check actual codecs? */
6493 } else {
6494 if (g_pars.aoip) {
6495 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6496 "handoverRequestAck: Expected Speech Codec List (BSS Supported), but none found");
6497 }
6498 }
6499
6500 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.speechCodec)) {
6501 if (not g_pars.aoip) {
6502 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6503 "handoverRequestAck: Expected no Speech Codec (Chosen), because this is not AoIP");
6504 }
6505 /* TODO: check actual codec? */
6506 } else {
6507 if (g_pars.aoip) {
6508 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6509 "handoverRequestAck: Expected Speech Codec (Chosen), but none found");
6510 }
6511 }
6512
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006513 var octetstring ho_command_str;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006514 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6515 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6516 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6517 log("L3 Info in HO Request Ack is ", ho_command);
6518
6519 var GsmArfcn arfcn;
6520 var RslChannelNr actual_new_chan_nr;
6521 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6522 actual_new_chan_nr, arfcn);
6523
6524 if (actual_new_chan_nr != new_chan_nr) {
6525 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6526 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6527 setverdict(fail);
6528 return;
6529 }
6530 log("Handover Command chan_nr is", actual_new_chan_nr);
6531
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006532 var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
6533 if (not match(got_tsc, expect_target_tsc)) {
6534 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6535 expect_target_tsc, " got ", got_tsc);
6536 mtc.stop;
6537 } else {
6538 log("handoverCommand: verified TSC = ", got_tsc);
6539 }
6540
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006541 /* Check the Cipher Mode Setting IE (shall be present during inter-RAT handover) */
6542 if (ispresent(ho_command.msgs.rrm.handoverCommand.cipherModeSetting)) {
6543 var CipherModeSetting_TV cms := ho_command.msgs.rrm.handoverCommand.cipherModeSetting;
6544 var template (present) CipherModeSetting_TV tr_cms := {
6545 sC := '0'B, /* no ciphering by default */
6546 algorithmIdentifier := '000'B,
6547 elementIdentifier := ?
6548 };
6549 if (ispresent(g_pars.encr) and g_pars.encr.enc_alg_expect != '01'O) { /* A5/N */
6550 tr_cms.algorithmIdentifier := f_cipher_mode_bssmap_to_rr(g_pars.encr.enc_alg_expect);
6551 tr_cms.sC := '1'B;
6552 }
6553 if (not match(cms, tr_cms)) {
6554 setverdict(fail, "RR Handover Command: unexpected Cipher Mode Setting IE: ",
6555 cms, ", expected: ", tr_cms);
6556 }
6557 } else {
6558 setverdict(fail, "RR Handover Command: Cipher Mode Setting IE is not present");
6559 }
6560
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006561 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6562 * tells the MS to handover to the new lchan. Here comes the new MS on
6563 * the new lchan with a Handover RACH: */
6564
6565 /* send handover detect */
6566
6567 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6568
6569 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6570
6571 /* send handover complete over the new channel */
6572
6573 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_HandoverComplete('00'O));
6574 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
6575 enc_PDU_ML3_MS_NW(l3_tx)));
6576
6577 BSSAP.receive(tr_BSSMAP_HandoverComplete);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006578 deactivate(as_media);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006579 setverdict(pass);
6580}
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006581
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006582private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006583 var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006584 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
6585 if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
6586 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006587 }
6588 if (g_pars.exp_fast_return) {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006589 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006590 } else {
6591 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006592 }
6593 f_ho_into_this_bsc(id, oldToNewBSSIEs);
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006594 if (g_pars.expect_ho_fail) {
6595 f_perform_clear_no_lchan();
Oliver Smith7a8594a2023-02-13 14:30:49 +01006596 } else if (g_pars.expect_ho_fail_lchan_est) {
6597 BSSAP.receive(tr_BSSMAP_ClearRequest);
6598 f_perform_clear_no_lchan();
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006599 } else {
6600 f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
6601 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006602 setverdict(pass);
6603}
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006604function 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 +01006605 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006606
6607 f_init(1, true);
6608 f_sleep(1.0);
6609
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006610 f_vty_encryption_a5(vty_a5_cfg);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006611 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006612
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006613 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6614 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006615
6616 vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
6617 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006618
6619 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006620 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006621 if (pars.expect_ho_fail) {
6622 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6623 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:failed");
Oliver Smith7a8594a2023-02-13 14:30:49 +01006624 } else if (pars.expect_ho_fail_lchan_est) {
6625 f_ctrs_bsc_and_bts_add(0, "handover:error");
6626 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006627 } else {
6628 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6629 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
6630 }
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006631 f_ctrs_bsc_and_bts_verify();
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006632
6633 f_vty_encryption_a5_reset();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006634}
6635
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006636testcase TC_ho_into_this_bsc() runs on test_CT {
6637 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6638 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006639 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006640}
6641
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006642function f_tc_ho_into_this_bsc_a5(TestHdlrEncrParams encr, charstring vty_a5_cfg := VTY_A5_DEFAULT,
6643 boolean expect_fail := false) runs on test_CT {
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006644 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006645 pars.encr := encr;
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006646 pars.expect_ho_fail := expect_fail;
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006647 f_tc_ho_into_this_bsc_main(pars, vty_a5_cfg);
Oliver Smith39f53072022-10-27 14:44:04 +02006648 f_shutdown_helper(ho := true);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006649}
6650
6651testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006652 f_tc_ho_into_this_bsc_a5(f_encr_params('01'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006653}
6654
6655testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006656 f_tc_ho_into_this_bsc_a5(f_encr_params('02'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006657}
6658
6659testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006660 f_tc_ho_into_this_bsc_a5(f_encr_params('08'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006661}
6662
6663testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006664 f_tc_ho_into_this_bsc_a5(f_encr_params('10'O, kc128 := true), "3 4");
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006665}
6666
Neels Hofmeyr1951be22022-02-16 16:21:07 +01006667/* Report: in inter-BSC incoming handover, when the MSC omits the Chosen Encryption Algorithm IE in the Handover Request
6668 * message, then osmo-bsc starts an unencrypted lchan even if A5/0 is not permitted.
6669 *
6670 * This test verifies that the Encryption Information is present in the Channel Activation when the Chosen Enc Alg is
6671 * omitted.
6672 *
6673 * Related: SYS#5839
6674 */
6675testcase TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() runs on test_CT {
6676 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O, alg_chosen := omit));
6677}
6678
6679testcase TC_ho_into_this_bsc_a5_1_3() runs on test_CT {
6680 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O));
6681}
6682
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006683/* Send a permitted algo mask that does not intersect with osmo-bsc.cfg */
6684testcase TC_ho_into_this_bsc_a5_mismatch() runs on test_CT {
6685 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '18'O, alg_expect := '10'O), "0 1",
6686 expect_fail := true); // 0x18 = A5/3 and A5/4
6687}
6688
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006689testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
6690 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6691 pars.host_aoip_tla := "::6";
6692 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006693 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006694}
6695
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006696/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006697 to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006698 channel is later released (RR CHannel Release), should trigger inclusion of
6699 IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
6700 neighbors. */
6701testcase TC_srvcc_eutran_to_geran() runs on test_CT {
6702 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6703 pars.last_used_eutran_plmn := '323454'O;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006704 pars.exp_fast_return := true;
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006705 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006706
6707 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6708 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6709 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006710 f_shutdown_helper(ho := true);
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006711}
6712
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006713/* Same as TC_srvcc_eutran_to_geran, but enables ciphering on the target channel. */
6714testcase TC_srvcc_eutran_to_geran_a5_3() runs on test_CT {
6715 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6716 pars.encr := f_encr_params('08'O); /* only A5/3 */
6717 pars.last_used_eutran_plmn := '323454'O;
6718 pars.exp_fast_return := true;
6719 f_tc_ho_into_this_bsc_main(pars);
6720
6721 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6722 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6723 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006724 f_shutdown_helper(ho := true);
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006725}
6726
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006727/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
6728 on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
6729 list when the channel is released. */
6730testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
6731 f_init_vty();
6732 f_vty_allow_srvcc_fast_return(true, 0)
6733
6734 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6735 pars.last_used_eutran_plmn := '323454'O;
6736 pars.exp_fast_return := false;
6737 f_tc_ho_into_this_bsc_main(pars);
6738 f_vty_allow_srvcc_fast_return(false, 0);
6739 f_shutdown_helper();
6740}
6741
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01006742/* Same as TC_srvcc_eutran_to_geran, but using SAI as serving Cell Identifier. SYS#5838 */
6743testcase TC_srvcc_eutran_to_geran_src_sai() runs on test_CT {
6744 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6745 pars.last_used_eutran_plmn := '323454'O;
6746 pars.cell_id_source := valueof(ts_CellID_SAI('123456'O, 300, 444));
6747 f_tc_ho_into_this_bsc_main(pars);
6748
6749 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6750 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6751 f_ctrs_bsc_and_bts_verify();
6752 f_shutdown_helper();
6753}
6754
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006755private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
6756 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
6757 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
6758 f_ho_into_this_bsc(id, oldToNewBSSIEs);
6759 f_ho_out_of_this_bsc(oldToNewBSSIEs);
6760 setverdict(pass);
6761}
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006762
6763private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
6764 runs on test_CT {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006765 var MSC_ConnHdlr vc_conn;
6766 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6767
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006768 f_init_vty();
6769 f_bts_0_cfg(BSCVTY,
6770 {"neighbor-list mode automatic",
6771 "handover 1",
6772 "handover algorithm 2",
6773 "handover2 window rxlev averaging 1",
6774 "no neighbors",
6775 "neighbor lac 99 arfcn 123 bsic any"});
6776 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6777
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006778 f_init(1, true);
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006779 if (disable_fast_return) {
6780 f_vty_allow_srvcc_fast_return(true, 0);
6781 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006782 f_sleep(1.0);
6783
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006784 f_ctrs_bsc_and_bts_handover_init();
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006785
6786 pars.last_used_eutran_plmn := '323454'O;
6787 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6788 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
6789
6790 vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
6791 vc_conn.done;
6792
6793 f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
6794 f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
6795 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
6796 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
6797 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
6798 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006799
6800 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
6801 f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006802 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006803
6804 if (disable_fast_return) {
6805 f_vty_allow_srvcc_fast_return(false, 0);
6806 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006807 f_shutdown_helper();
6808}
6809
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006810/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
6811 BSS Information" IE with "Last Used E-UTRAN PLMN Id".
6812 Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
6813 IE with "Last Used E-UTRAN PLMN Id" from first step. */
6814testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
6815 f_tc_srvcc_eutran_to_geran_ho_out_main(false);
6816}
6817/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
6818 * independently of fast-reture allowed/forbidden in local BTS */
6819testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
6820 f_tc_srvcc_eutran_to_geran_ho_out_main(true);
6821}
6822
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006823private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
6824 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6825 f_rslem_register(0, new_chan_nr);
6826 g_chan_nr := new_chan_nr;
6827 f_sleep(1.0);
6828
6829 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6830 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6831 activate(as_Media());
6832
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006833 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006834 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006835 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006836
6837 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6838
6839 var PDU_BSSAP rx_bssap;
6840 var octetstring ho_command_str;
6841
6842 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6843
6844 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6845 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6846 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6847 log("L3 Info in HO Request Ack is ", ho_command);
6848
6849 var GsmArfcn arfcn;
6850 var RslChannelNr actual_new_chan_nr;
6851 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6852 actual_new_chan_nr, arfcn);
6853
6854 if (actual_new_chan_nr != new_chan_nr) {
6855 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6856 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6857 setverdict(fail);
6858 return;
6859 }
6860 log("Handover Command chan_nr is", actual_new_chan_nr);
6861
Neels Hofmeyr61ca08d2019-05-06 23:52:22 +02006862 /* For deterministic test results, give some time for the MGW endpoint to be configured */
6863 f_sleep(1.0);
6864
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006865 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6866 * tells the MS to handover to the new lchan. In this case, the MS
6867 * reports a Handover Failure to the old BSS, which forwards a BSSMAP
6868 * Handover Failure to the MSC. The procedure according to 3GPP TS
6869 * 48.008 3.1.5.3.2 "Handover Failure" is then that the MSC sends a
6870 * BSSMAP Clear Command: */
6871
6872 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6873 var BssmapCause cause := enum2int(cause_val);
6874 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6875
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006876 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006877 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006878 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006879
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006880 setverdict(pass);
6881 f_sleep(1.0);
6882
6883 setverdict(pass);
6884}
6885testcase TC_ho_in_fail_msc_clears() runs on test_CT {
6886 var MSC_ConnHdlr vc_conn;
6887 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6888
6889 f_init(1, true);
6890 f_sleep(1.0);
6891
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006892 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006893
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006894 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6895 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006896
6897 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
6898 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006899
6900 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6901 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6902 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6903 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6904 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006905 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006906}
6907
6908private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
6909 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6910 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6911 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6912 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6913 * before we get started. */
6914 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6915 f_rslem_register(0, new_chan_nr);
6916 g_chan_nr := new_chan_nr;
6917 f_sleep(1.0);
6918
6919 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6920 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6921 activate(as_Media());
6922
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006923 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006924 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006925 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006926
6927 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6928
6929 var PDU_BSSAP rx_bssap;
6930 var octetstring ho_command_str;
6931
6932 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6933
6934 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6935 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6936 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6937 log("L3 Info in HO Request Ack is ", ho_command);
6938
6939 var GsmArfcn arfcn;
6940 var RslChannelNr actual_new_chan_nr;
6941 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6942 actual_new_chan_nr, arfcn);
6943
6944 if (actual_new_chan_nr != new_chan_nr) {
6945 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6946 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6947 setverdict(fail);
6948 return;
6949 }
6950 log("Handover Command chan_nr is", actual_new_chan_nr);
6951
6952 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6953 * tells the MS to handover to the new lchan. Here comes the new MS on
6954 * the new lchan with a Handover RACH: */
6955
6956 /* send handover detect */
6957
6958 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6959
6960 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6961
6962 /* The MSC chooses to clear the connection now, maybe we got the
6963 * Handover RACH on the new cell but the MS still signaled Handover
6964 * Failure to the old BSS? */
6965
6966 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6967 var BssmapCause cause := enum2int(cause_val);
6968 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6969
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006970 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006971 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006972 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006973
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006974 f_sleep(1.0);
6975}
6976testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
6977 var MSC_ConnHdlr vc_conn;
6978 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6979
6980 f_init(1, true);
6981 f_sleep(1.0);
6982
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006983 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006984
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006985 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6986 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006987
6988 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
6989 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006990
6991 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6992 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6993 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6994 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6995 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006996 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006997}
6998
6999/* The new BSS's lchan times out before the MSC decides that handover failed. */
7000private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
7001 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
7002 f_rslem_register(0, new_chan_nr);
7003 g_chan_nr := new_chan_nr;
7004 f_sleep(1.0);
7005
7006 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
7007 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01007008 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007009
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007010 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007011 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02007012 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007013
7014 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
7015
7016 var PDU_BSSAP rx_bssap;
7017 var octetstring ho_command_str;
7018
7019 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
7020
7021 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
7022 log("Received L3 Info in HO Request Ack: ", ho_command_str);
7023 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
7024 log("L3 Info in HO Request Ack is ", ho_command);
7025
7026 var GsmArfcn arfcn;
7027 var RslChannelNr actual_new_chan_nr;
7028 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
7029 actual_new_chan_nr, arfcn);
7030
7031 if (actual_new_chan_nr != new_chan_nr) {
7032 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
7033 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
7034 setverdict(fail);
7035 return;
7036 }
7037 log("Handover Command chan_nr is", actual_new_chan_nr);
7038
7039 /* Now the MSC forwards the RR Handover Command to the other BSC, which
7040 * tells the MS to handover to the new lchan. But the MS never shows up
7041 * on the new lchan. */
7042
7043 BSSAP.receive(tr_BSSMAP_HandoverFailure);
7044
7045 /* Did osmo-bsc also send a Clear Request? */
7046 timer T := 0.5;
7047 T.start;
7048 alt {
7049 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
7050 [] T.timeout { }
7051 }
7052
7053 /* MSC plays along with a Clear Command (no matter whether osmo-bsc
7054 * asked for it, this is a Handover Failure after all). */
7055
7056 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
7057 var BssmapCause cause := enum2int(cause_val);
7058 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7059
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007060 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007061 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007062 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007063
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007064 f_sleep(1.0);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007065}
7066testcase TC_ho_in_fail_no_detect() runs on test_CT {
7067 var MSC_ConnHdlr vc_conn;
7068 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7069
Oliver Smithd49f46d2023-03-08 12:23:13 +01007070 pars.fail_on_dlcx := false;
7071
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007072 f_init(1, true);
7073 f_sleep(1.0);
7074
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007075 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007076
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007077 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7078 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007079
7080 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect), pars);
7081 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007082
7083 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7084 f_ctrs_bsc_and_bts_add(0, "handover:error");
7085 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7086 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7087 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007088 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007089}
7090
7091/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
7092private function f_tc_ho_in_fail_no_detect2(charstring id) runs on MSC_ConnHdlr {
7093 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
7094 f_rslem_register(0, new_chan_nr);
7095 g_chan_nr := new_chan_nr;
7096 f_sleep(1.0);
7097
7098 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
7099 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01007100 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007101
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007102 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007103 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02007104 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007105
7106 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
7107
7108 var PDU_BSSAP rx_bssap;
7109 var octetstring ho_command_str;
7110
7111 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
7112
7113 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
7114 log("Received L3 Info in HO Request Ack: ", ho_command_str);
7115 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
7116 log("L3 Info in HO Request Ack is ", ho_command);
7117
7118 var GsmArfcn arfcn;
7119 var RslChannelNr actual_new_chan_nr;
7120 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
7121 actual_new_chan_nr, arfcn);
7122
7123 if (actual_new_chan_nr != new_chan_nr) {
7124 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
7125 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
7126 setverdict(fail);
7127 return;
7128 }
7129 log("Handover Command chan_nr is", actual_new_chan_nr);
7130
7131 /* Now the MSC forwards the RR Handover Command to the other BSC, which
7132 * tells the MS to handover to the new lchan. But the MS never shows up
7133 * on the new lchan. */
7134
7135 BSSAP.receive(tr_BSSMAP_HandoverFailure);
7136
7137 /* MSC plays dumb and sends no Clear Command */
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007138 var PDU_BSSAP rx_clear_request;
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02007139
7140 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request {
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007141 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
7142 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7143 };
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007144 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007145 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007146 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007147
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007148 f_sleep(1.0);
7149}
7150testcase TC_ho_in_fail_no_detect2() runs on test_CT {
7151 var MSC_ConnHdlr vc_conn;
7152 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7153
Oliver Smith735b47c2023-02-15 16:03:54 +01007154 pars.fail_on_dlcx := false;
7155
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007156 f_init(1, true);
7157 f_sleep(1.0);
7158
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007159 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007160
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007161 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7162 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007163
7164 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
7165 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007166
7167 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7168 f_ctrs_bsc_and_bts_add(0, "handover:error");
7169 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7170 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7171 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007172 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007173}
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01007174
Oliver Smith7a8594a2023-02-13 14:30:49 +01007175testcase TC_ho_in_fail_mgw_mdcx_timeout() runs on test_CT {
7176 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7177
7178 pars.ignore_mgw_mdcx := true;
7179 pars.expect_ho_fail_lchan_est := true;
7180
7181 f_tc_ho_into_this_bsc_main(pars);
7182 f_shutdown_helper(ho := true);
7183}
7184
Oliver Smith4eed06f2023-02-15 15:43:19 +01007185testcase TC_ho_in_fail_ipa_crcx_timeout() runs on test_CT {
7186 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7187
7188 pars.ignore_ipa_media := true;
7189 pars.expect_ho_fail_lchan_est := true;
7190 pars.fail_on_dlcx := false;
7191
7192 f_tc_ho_into_this_bsc_main(pars);
7193 f_shutdown_helper(ho := true);
7194}
7195
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007196/* An incoming inter-BSC HO can either issue the Handover Request message attached to the initial SCCP N-Connect (as in
7197 * the other tests we have so far), or the first CR can be "empty" with the BSSAP request following later. Test the
7198 * empty N-Connect case. */
7199testcase TC_ho_into_this_bsc_sccp_cr_without_bssap() runs on test_CT {
7200 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7201 pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr := false;
7202 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02007203 f_shutdown_helper(ho := true);
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007204}
7205
Neels Hofmeyr91401012019-07-11 00:42:35 +02007206type record of charstring Commands;
7207
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007208private function f_bts_0_cfg(TELNETasp_PT pt, Commands cmds := {})
Neels Hofmeyr91401012019-07-11 00:42:35 +02007209{
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007210 f_vty_enter_cfg_bts(pt, 0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007211 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007212 f_vty_transceive(pt, cmds[i]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007213 }
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007214 f_vty_transceive(pt, "end");
Neels Hofmeyr91401012019-07-11 00:42:35 +02007215}
7216
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01007217private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
7218{
7219 f_vty_enter_cfg_cs7_inst(pt, 0);
7220 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
7221 f_vty_transceive(pt, cmds[i]);
7222 }
7223 f_vty_transceive(pt, "end");
7224}
7225
Neels Hofmeyr91401012019-07-11 00:42:35 +02007226private function f_probe_for_handover(charstring log_label,
7227 charstring log_descr,
7228 charstring handover_vty_cmd,
7229 boolean expect_handover,
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007230 boolean is_inter_bsc_handover := false,
7231 template uint3_t expect_target_tsc := ?)
Neels Hofmeyr91401012019-07-11 00:42:35 +02007232runs on MSC_ConnHdlr
7233{
Neels Hofmeyrb3fc8982020-05-11 00:16:42 +02007234 /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
7235 * lchans to be established on bts 1 or bts 2. */
7236 f_rslem_suspend(RSL1_PROC);
7237 f_rslem_suspend(RSL2_PROC);
7238
Neels Hofmeyr91401012019-07-11 00:42:35 +02007239 var RSL_Message rsl;
7240
7241 var charstring log_msg := " (expecting handover)"
7242 if (not expect_handover) {
7243 log_msg := " (expecting NO handover)";
7244 }
7245 log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg);
7246 f_vty_transceive(BSCVTY, handover_vty_cmd);
7247
Neels Hofmeyr91401012019-07-11 00:42:35 +02007248 timer T := 2.0;
7249 T.start;
7250
7251 alt {
7252 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
7253 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
7254 log("Rx L3 from net: ", l3);
7255 if (ischosen(l3.msgs.rrm.handoverCommand)) {
7256 var RslChannelNr new_chan_nr;
7257 var GsmArfcn arfcn;
7258 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
7259 new_chan_nr, arfcn);
7260 log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
7261 log(l3.msgs.rrm.handoverCommand);
7262
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007263 /* Verify correct TSC in handoverCommand */
7264 var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
7265 if (not match(got_tsc, expect_target_tsc)) {
7266 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
7267 expect_target_tsc, " got ", got_tsc);
7268 mtc.stop;
7269 } else {
7270 log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
7271 expect_target_tsc, ")");
7272 }
7273
Neels Hofmeyr91401012019-07-11 00:42:35 +02007274 /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
7275 * matter on which BTS it really is, we're not going to follow through an entire handover
7276 * anyway. */
7277 f_rslem_register(0, new_chan_nr, RSL1_PROC);
7278 f_rslem_resume(RSL1_PROC);
7279 f_rslem_register(0, new_chan_nr, RSL2_PROC);
7280 f_rslem_resume(RSL2_PROC);
7281
7282 if (expect_handover and not is_inter_bsc_handover) {
7283 setverdict(pass);
7284 log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected.");
7285 } else {
7286 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. "
7287 & log_label & ": " & log_descr);
7288 }
7289
7290 log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
7291 /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with
7292 * Handover Failure. */
7293 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
7294
7295 /* target BTS is told to release lchan again; don't care which BTS nor what messages. */
7296 f_sleep(0.5);
7297 RSL1.clear;
7298 RSL2.clear;
7299 log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)");
7300 break;
7301 } else {
7302 repeat;
7303 }
7304 }
7305 [] BSSAP.receive(tr_BSSMAP_HandoverRequired) {
7306 if (expect_handover and is_inter_bsc_handover) {
7307 setverdict(pass);
7308 log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected.");
7309 } else {
7310 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. "
7311 & log_label & ": " & log_descr);
7312 }
7313
7314 log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)");
7315
7316 /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to
7317 * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required,
7318 * setting a short timeout and waiting is the only way. */
7319 log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out...");
7320 f_sleep(1.5);
7321 log("f_probe_for_handover(" & log_label & "): ...done");
7322
7323 break;
7324 }
7325 [] T.timeout {
7326 if (expect_handover) {
7327 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. "
7328 & log_label & ": " & log_descr);
7329 } else {
7330 setverdict(pass);
7331 log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected.");
7332 }
7333 log("f_probe_for_handover(" & log_label & "): done (got no Handover)");
7334 break;
7335 }
7336 }
7337
7338 f_rslem_resume(RSL1_PROC);
7339 f_rslem_resume(RSL2_PROC);
7340 f_sleep(3.0);
7341 RSL.clear;
7342
7343 log("f_probe_for_handover(" & log_label & "): done clearing");
7344}
7345
7346/* Test the effect of various neighbor configuration scenarios:
7347 *
7348 * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0.
7349 * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO.
7350 */
7351private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
7352 g_pars := f_gen_test_hdlr_pars();
7353 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
7354 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007355
7356 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
7357 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
7358
7359 /* Establish lchan at bts 0 */
7360 f_establish_fully(ass_cmd, exp_compl);
7361
7362 /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */
7363 f_vty_enter_cfg_network(BSCVTY);
7364 f_vty_transceive(BSCVTY, "timer T7 1");
7365 f_vty_transceive(BSCVTY, "end");
7366}
7367
7368private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
7369 f_tc_ho_neighbor_config_start();
7370
7371 /*
7372 * bts 0 ARFCN 871 BSIC 10
7373 * bts 1 ARFCN 871 BSIC 11
7374 * bts 2 ARFCN 871 BSIC 12
7375 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7376 */
7377
7378 log("f_tc_ho_neighbor_config: 1. No 'neighbor' config");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007379 f_bts_0_cfg(BSCVTY, {"no neighbors"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007380 f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
7381 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007382 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007383
7384 f_probe_for_handover("1.b", "HO to unknown cell does not start",
7385 "handover any to arfcn 13 bsic 39",
7386 false);
7387
7388 f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error",
7389 "handover any to arfcn 871 bsic 12",
7390 false);
7391
7392 f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
7393 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007394 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007395
7396 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007397}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007398testcase TC_ho_neighbor_config_1() runs on test_CT {
7399 var MSC_ConnHdlr vc_conn;
7400 f_init(3, true, guard_timeout := 60.0);
7401 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007402 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007403 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
7404 vc_conn.done;
7405
7406 /* f_tc_ho_neighbor_config_start() */
7407 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7408 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7409
7410 /* 1.a */
7411 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7412 * handover quickly by sending a Handover Failure message. */
7413 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7414 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7415 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7416 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007417 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7418 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007419
7420 /* 1.b */
7421 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7422 f_ctrs_bsc_and_bts_add(0, "handover:error");
7423
7424 /* 1.c */
7425 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7426 f_ctrs_bsc_and_bts_add(0, "handover:error");
7427
7428 /* 1.d */
7429 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7430 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7431 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7432 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007433 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7434 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007435
7436 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007437 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007438}
7439
Neels Hofmeyr91401012019-07-11 00:42:35 +02007440private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
7441 f_tc_ho_neighbor_config_start();
7442
7443 /*
7444 * bts 0 ARFCN 871 BSIC 10
7445 * bts 1 ARFCN 871 BSIC 11
7446 * bts 2 ARFCN 871 BSIC 12
7447 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7448 */
7449
7450 log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007451 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007452 f_sleep(0.5);
7453
7454 f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
7455 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007456 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007457
7458 f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
7459 "handover any to arfcn 871 bsic 12",
7460 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007461 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007462}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007463testcase TC_ho_neighbor_config_2() runs on test_CT {
7464 var MSC_ConnHdlr vc_conn;
7465 f_init(3, true, guard_timeout := 50.0);
7466 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007467 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007468 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
7469 vc_conn.done;
7470
7471 /* f_tc_ho_neighbor_config_start() */
7472 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7473 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7474
7475 /* 2.a */
7476 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7477 * handover quickly by sending a Handover Failure message. */
7478 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7479 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7480 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7481 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007482 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7483 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007484
7485 /* 2.b */
7486 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7487 f_ctrs_bsc_and_bts_add(0, "handover:error");
7488
7489 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007490 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007491}
7492
Neels Hofmeyr91401012019-07-11 00:42:35 +02007493private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
7494 f_tc_ho_neighbor_config_start();
7495
7496 /*
7497 * bts 0 ARFCN 871 BSIC 10
7498 * bts 1 ARFCN 871 BSIC 11
7499 * bts 2 ARFCN 871 BSIC 12
7500 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7501 */
7502
7503 log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007504 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007505 f_sleep(0.5);
7506
7507 f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor",
7508 "handover any to arfcn 871 bsic 11",
7509 false);
7510 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",
7511 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007512 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007513 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007514}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007515testcase TC_ho_neighbor_config_3() runs on test_CT {
7516 var MSC_ConnHdlr vc_conn;
7517 f_init(3, true, guard_timeout := 50.0);
7518 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007519 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007520 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
7521 vc_conn.done;
7522
7523 /* f_tc_ho_neighbor_config_start() */
7524 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7525 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7526
7527 /* 3.a */
7528 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7529 f_ctrs_bsc_and_bts_add(0, "handover:error");
7530
7531 /* 3.b */
7532 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7533 * handover quickly by sending a Handover Failure message. */
7534 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7535 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7536 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7537 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007538 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7539 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007540
7541 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007542 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007543}
7544
Neels Hofmeyr91401012019-07-11 00:42:35 +02007545private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
7546 f_tc_ho_neighbor_config_start();
7547
7548 /*
7549 * bts 0 ARFCN 871 BSIC 10
7550 * bts 1 ARFCN 871 BSIC 11
7551 * bts 2 ARFCN 871 BSIC 12
7552 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7553 */
7554
7555 log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007556 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007557 f_sleep(0.5);
7558
7559 f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor",
7560 "handover any to arfcn 871 bsic 11",
7561 false);
7562 f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor",
7563 "handover any to arfcn 871 bsic 12",
7564 false);
7565 f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
7566 "handover any to arfcn 123 bsic 45",
7567 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007568 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007569}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007570testcase TC_ho_neighbor_config_4() runs on test_CT {
7571 var MSC_ConnHdlr vc_conn;
7572 f_init(3, true, guard_timeout := 50.0);
7573 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007574 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007575 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
7576 vc_conn.done;
7577
7578 /* f_tc_ho_neighbor_config_start() */
7579 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7580 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7581
7582 /* 4.a */
7583 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7584 f_ctrs_bsc_and_bts_add(0, "handover:error");
7585
7586 /* 4.b */
7587 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7588 f_ctrs_bsc_and_bts_add(0, "handover:error");
7589
7590 /* 4.c */
7591 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7592 * handover quickly by timing out after the Handover Required message */
7593 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7594 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7595 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7596 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7597
7598 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007599 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007600}
7601
Neels Hofmeyr91401012019-07-11 00:42:35 +02007602private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
7603 f_tc_ho_neighbor_config_start();
7604
7605 /*
7606 * bts 0 ARFCN 871 BSIC 10
7607 * bts 1 ARFCN 871 BSIC 11
7608 * bts 2 ARFCN 871 BSIC 12
7609 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7610 */
7611
7612 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 +02007613 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007614 f_sleep(0.5);
7615
7616 f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
7617 "handover any to arfcn 871 bsic 12",
7618 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007619 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007620}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007621testcase TC_ho_neighbor_config_5() runs on test_CT {
7622 var MSC_ConnHdlr vc_conn;
7623 f_init(3, true);
7624 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007625 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007626 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
7627 vc_conn.done;
7628
7629 /* f_tc_ho_neighbor_config_start() */
7630 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7631 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7632
7633 /* 5 */
7634 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7635 * handover quickly by timing out after the Handover Required message */
7636 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7637 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7638 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7639 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7640
7641 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007642 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007643}
7644
Neels Hofmeyr91401012019-07-11 00:42:35 +02007645private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
7646 f_tc_ho_neighbor_config_start();
7647
7648 /*
7649 * bts 0 ARFCN 871 BSIC 10
7650 * bts 1 ARFCN 871 BSIC 11
7651 * bts 2 ARFCN 871 BSIC 12
7652 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7653 */
7654
7655 log("f_tc_ho_neighbor_config: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:"
7656 & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007657 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007658 f_sleep(0.5);
7659
7660 f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
7661 "handover any to arfcn 871 bsic 12",
7662 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007663 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007664}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007665testcase TC_ho_neighbor_config_6() runs on test_CT {
7666 var MSC_ConnHdlr vc_conn;
7667 f_init(3, true);
7668 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007669 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007670 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
7671 vc_conn.done;
7672
7673 /* f_tc_ho_neighbor_config_start() */
7674 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7675 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7676
7677 /* 6.a */
7678 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7679 * handover quickly by timing out after the Handover Required message */
7680 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7681 f_ctrs_bsc_and_bts_add(0, "handover:error");
7682
7683 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007684 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007685}
7686
Neels Hofmeyr91401012019-07-11 00:42:35 +02007687private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
7688 f_tc_ho_neighbor_config_start();
7689
7690 /*
7691 * bts 0 ARFCN 871 BSIC 10
7692 * bts 1 ARFCN 871 BSIC 11
7693 * bts 2 ARFCN 871 BSIC 12
7694 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7695 */
7696
7697 log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:"
7698 & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007699 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007700 f_sleep(0.5);
7701
7702 f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
7703 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007704 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007705 f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
7706 "handover any to arfcn 123 bsic 45",
7707 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007708 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007709}
Neels Hofmeyr91401012019-07-11 00:42:35 +02007710testcase TC_ho_neighbor_config_7() runs on test_CT {
7711 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf2b88032020-06-16 00:35:04 +02007712 f_init(3, true, guard_timeout := 50.0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007713 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007714 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007715 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
7716 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007717
7718 /* f_tc_ho_neighbor_config_start() */
7719 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7720 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7721
7722 /* 7.a */
7723 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7724 * handover quickly by sending a Handover Failure message. */
7725 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7726 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7727 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7728 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007729 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7730 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007731
7732 /* 7.b */
7733 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7734 * handover quickly by timing out after the Handover Required message */
7735 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7736 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7737 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7738 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7739
7740 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007741 f_shutdown_helper(ho := true);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007742}
7743
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007744/* OS#3041: Open and close N connections in a normal fashion, and expect no
7745 * BSSMAP Reset just because of that. */
7746testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
7747 var default d;
7748 var integer i;
7749 var DchanTuple dt;
7750
7751 f_init();
7752
7753 /* Wait for initial BSSMAP Reset to pass */
7754 f_sleep(4.0);
7755
7756 d := activate(no_bssmap_reset());
7757
7758 /* Setup up a number of connections and RLSD them again from the MSC
7759 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7760 * Let's do it some more times for good measure. */
Harald Weltec3260d92018-06-11 17:48:16 +02007761 for (i := 0; i < 4; i := i+1) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007762 /* Since we're doing a lot of runs, give each one a fresh
7763 * T_guard from the top. */
7764 T_guard.start;
7765
7766 /* Setup a BSSAP connection and clear it right away. This is
7767 * the MSC telling the BSC about a planned release, it's not an
7768 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007769 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007770
7771 /* MSC disconnects (RLSD). */
7772 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
7773 }
7774
7775 /* In the buggy behavior, a timeout of 2 seconds happens between above
7776 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7777 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7778 f_sleep(4.0);
7779
7780 deactivate(d);
7781 f_shutdown_helper();
7782}
Harald Welte552620d2017-12-16 23:21:36 +01007783
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007784/* OS#3041: Open and close N connections in a normal fashion, and expect no
7785 * BSSMAP Reset just because of that. Invoke the release by a BSSMAP Clear from
7786 * the MSC. */
7787testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
7788 var default d;
7789 var integer i;
7790 var DchanTuple dt;
7791 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007792 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
7793 var BssmapCause cause := enum2int(cause_val);
7794
7795 f_init();
7796
7797 /* Wait for initial BSSMAP Reset to pass */
7798 f_sleep(4.0);
7799
7800 d := activate(no_bssmap_reset());
7801
7802 /* Setup up a number of connections and RLSD them again from the MSC
7803 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7804 * Let's do it some more times for good measure. */
7805 for (i := 0; i < 8; i := i+1) {
7806 /* Since we're doing a lot of runs, give each one a fresh
7807 * T_guard from the top. */
7808 T_guard.start;
7809
7810 /* Setup a BSSAP connection and clear it right away. This is
7811 * the MSC telling the BSC about a planned release, it's not an
7812 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007813 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007814
7815 /* Instruct BSC to clear channel */
7816 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7817
7818 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007819 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007820 }
7821
7822 /* In the buggy behavior, a timeout of 2 seconds happens between above
7823 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7824 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7825 f_sleep(4.0);
7826
7827 deactivate(d);
7828 f_shutdown_helper();
7829}
7830
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007831/* OS#3041: Open and close N connections in a normal fashion, and expect no
7832 * BSSMAP Reset just because of that. Close connections from the MS side with a
7833 * Release Ind on RSL. */
7834testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
7835 var default d;
7836 var integer i;
7837 var DchanTuple dt;
7838 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007839 var integer j;
7840
7841 f_init();
7842
7843 /* Wait for initial BSSMAP Reset to pass */
7844 f_sleep(4.0);
7845
7846 d := activate(no_bssmap_reset());
7847
7848 /* Setup up a number of connections and RLSD them again from the MSC
7849 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7850 * Let's do it some more times for good measure. */
7851 for (i := 0; i < 8; i := i+1) {
7852 /* Since we're doing a lot of runs, give each one a fresh
7853 * T_guard from the top. */
7854 T_guard.start;
7855
7856 /* Setup a BSSAP connection and clear it right away. This is
7857 * the MSC telling the BSC about a planned release, it's not an
7858 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007859 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007860
7861 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007862 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007863
7864 /* expect Clear Request on MSC side */
7865 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
7866
7867 /* Instruct BSC to clear channel */
7868 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
7869 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7870
7871 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007872 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007873 }
7874
7875 /* In the buggy behavior, a timeout of 2 seconds happens between above
7876 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7877 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7878 f_sleep(4.0);
7879
7880 deactivate(d);
7881 f_shutdown_helper();
7882}
7883
Harald Welte94e0c342018-04-07 11:33:23 +02007884/***********************************************************************
7885 * IPA style dynamic PDCH
7886 ***********************************************************************/
7887
7888private function f_dyn_ipa_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7889 template (omit) RSL_Cause nack := omit)
7890runs on test_CT {
7891 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7892 var RSL_Message rsl_unused;
7893 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7894 f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
7895 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007896 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007897 if (istemplatekind(nack, "omit")) {
7898 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007899 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007900 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007901 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007902 }
7903}
7904
7905private function f_dyn_ipa_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7906 template (omit) RSL_Cause nack := omit)
7907runs on test_CT {
7908 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7909 var RSL_Message rsl_unused;
7910 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7911 f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
7912 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007913 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_DEACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007914 if (istemplatekind(nack, "omit")) {
7915 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007916 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007917 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007918 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007919 }
7920}
7921
7922private function f_ts_dyn_mode_get(integer bts_nr, integer trx_nr, integer ts_nr)
7923runs on test_CT return charstring {
7924 var charstring cmd, resp;
7925 cmd := "show timeslot "&int2str(bts_nr)&" "&int2str(trx_nr)&" "&int2str(ts_nr);
Stefan Sperlingcff13562018-11-13 15:24:06 +01007926 return f_vty_transceive_match_regexp_retry(BSCVTY, cmd, "*\((*)\)*", 0, 4, 1.0);
Harald Welte94e0c342018-04-07 11:33:23 +02007927}
7928
7929private function f_ts_dyn_mode_assert(integer bts_nr, integer trx_nr, integer ts_nr,
7930 template charstring exp)
7931runs on test_CT {
7932 var charstring mode := f_ts_dyn_mode_get(bts_nr, trx_nr, ts_nr);
7933 if (not match(mode, exp)) {
7934 setverdict(fail, "Unexpected TS Mode: ", mode);
Daniel Willmannafce8662018-07-06 23:11:32 +02007935 mtc.stop;
Harald Welte94e0c342018-04-07 11:33:23 +02007936 }
7937}
7938
7939private function f_ts_set_chcomb(integer bts_nr, integer trx_nr, integer ts_nr, charstring chcomb)
7940runs on test_CT {
7941 f_vty_enter_cfg_ts(BSCVTY, bts_nr, trx_nr, ts_nr);
7942 f_vty_transceive(BSCVTY, "phys_chan_config " & chcomb);
7943 f_vty_transceive(BSCVTY, "end");
7944}
7945
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007946
7947private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
7948 var integer i;
7949 for (i := 0; i < 8; i := i + 1) {
7950 f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
7951 }
7952}
7953
Harald Welte94e0c342018-04-07 11:33:23 +02007954private const charstring TCHF_MODE := "TCH/F mode";
7955private const charstring TCHH_MODE := "TCH/H mode";
7956private const charstring PDCH_MODE := "PDCH mode";
7957private const charstring NONE_MODE := "NONE mode";
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007958private const charstring SDCCH8_MODE := "SDCCH8 mode";
Harald Welte94e0c342018-04-07 11:33:23 +02007959
7960/* Test IPA PDCH activation / deactivation triggered by VTY */
7961testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
7962 var RSL_Message rsl_unused;
7963
7964 /* change Timeslot 6 before f_init() starts RSL */
7965 f_init_vty();
7966 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7967 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7968
7969 f_init(1, false);
7970 f_sleep(1.0);
7971
7972 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7973
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007974 log("TCH/F_PDCH pchan starts out in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007975 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7976 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007977 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7978 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007979 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007980 log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007981 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7982
7983 /* De-activate it via VTY */
7984 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7985 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007986 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007987 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7988
7989 /* re-activate it via VTY */
7990 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn);
7991 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007992 log("TCH/F_PDCH pchan, PDCH ACT via VTY, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007993 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7994
7995 /* and finally de-activate it again */
7996 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7997 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007998 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007999 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
8000
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008001 /* clean up config */
8002 f_ts_set_chcomb(0, 0, 6, "PDCH");
8003
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008004 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008005}
8006
8007/* Test IPA PDCH activation NACK */
8008testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
8009 var RSL_Message rsl_unused;
8010
8011 /* change Timeslot 6 before f_init() starts RSL */
8012 f_init_vty();
8013 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
8014 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8015
8016 f_init(1, false);
8017 f_sleep(1.0);
8018
8019 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
8020
8021 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
8022 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008023 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
8024 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02008025 f_sleep(1.0);
8026 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
8027
8028 /* De-activate it via VTY */
8029 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
8030 f_sleep(1.0);
8031 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
8032
8033 /* re-activate it via VTY, but fail that; check BSC still assumes TCH/F mode */
8034 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn, RSL_ERR_EQUIPMENT_FAIL);
8035 f_sleep(1.0);
8036 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
8037
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008038 /* clean up config */
8039 f_ts_set_chcomb(0, 0, 6, "PDCH");
8040
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008041 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008042}
8043
8044
8045/***********************************************************************
8046 * Osmocom style dynamic PDCH
8047 ***********************************************************************/
8048
8049private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
8050 template (omit) RSL_Cause nack := omit)
8051runs on test_CT {
8052 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
8053 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02008054 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02008055 /* FIXME: no VTY command to activate Osmocom PDCH !! */
8056 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008057 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT(chan_nr, ?));
Harald Welte94e0c342018-04-07 11:33:23 +02008058 if (istemplatekind(nack, "omit")) {
8059 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008060 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02008061 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008062 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02008063 }
8064}
8065
8066private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
8067 template (omit) RSL_Cause nack := omit)
8068runs on test_CT {
8069 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
8070 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02008071 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02008072 /* FIXME: no VTY command to activate Osmocom PDCH !! */
8073 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008074 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008075 if (istemplatekind(nack, "omit")) {
8076 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008077 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008078 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008079 //f_ipa_tx(ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02008080 }
8081}
8082
8083/* Test Osmocom dyn PDCH activation / deactivation triggered by VTY */
8084testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
8085 var RSL_Message rsl_unused;
8086
8087 /* change Timeslot 6 before f_init() starts RSL */
8088 f_init_vty();
8089 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8090 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8091
8092 f_init(1, false);
8093 f_sleep(1.0);
8094
8095 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8096
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008097 log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02008098 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8099 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008100 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008101
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008102 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02008103 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008104 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 +02008105 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
8106
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008107 /* clean up config */
8108 f_ts_set_chcomb(0, 0, 6, "PDCH");
8109
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008110 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008111}
8112
8113/* Test Osmocom dyn PDCH activation NACK behavior */
8114testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
8115 var RSL_Message rsl_unused;
8116
8117 /* change Timeslot 6 before f_init() starts RSL */
8118 f_init_vty();
8119 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8120 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8121
8122 f_init(1, false);
8123 f_sleep(1.0);
8124
8125 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8126
8127 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8128 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008129 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008130
8131 /* NACK this activation and expect the "show timeslot" mode still to be NONE */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008132 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte94e0c342018-04-07 11:33:23 +02008133 f_sleep(1.0);
8134 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8135
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008136 /* clean up config */
8137 f_ts_set_chcomb(0, 0, 6, "PDCH");
8138
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008139 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008140}
8141
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008142/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
8143testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
8144 var RSL_Message rsl_unused, rsl_msg;
8145 var DchanTuple dt;
8146 var BSSAP_N_CONNECT_ind rx_c_ind;
8147
8148 /* change Timeslot 6 before f_init() starts RSL */
8149 f_init_vty();
8150 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8151 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8152
8153 f_init(1, false);
8154 f_sleep(1.0);
8155
8156 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8157
8158 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8159 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8160 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008161 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008162
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008163 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008164 f_sleep(1.0);
8165 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8166 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8167
8168 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8169 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008170 var DchanTuples sdcch_cleanup := {};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008171 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008172 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008173 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008174 sdcch_cleanup := sdcch_cleanup & { dt };
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008175 }
8176
8177 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008178 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8179 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8180 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008181
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008182 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008183 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008184 dt.idx := {0, 0};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008185
8186 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008187 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8188 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008189 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
8190
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008191 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 +02008192 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8193 dt.sccp_conn_id := rx_c_ind.connectionId;
8194 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8195
8196 /* Instruct BSC to clear channel */
8197 var BssmapCause cause := 0;
8198 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008199 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008200
8201 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008202 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8203 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008204 f_sleep(1.0);
8205 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8206
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008207 /* Clean up SDCCH lchans */
8208 for (i := 0; i < lengthof(sdcch_cleanup); i := i + 1) {
8209 f_perform_clear_test_ct(sdcch_cleanup[i]);
8210 }
8211
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008212 /* clean up config */
8213 f_ts_set_chcomb(0, 0, 6, "PDCH");
8214
8215 f_shutdown_helper();
8216}
8217
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008218/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
8219testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
8220 var ASP_RSL_Unitdata rsl_ud;
8221 var integer i;
8222 var integer chreq_total, chreq_nochan;
8223
8224 f_init_vty();
8225 for (i := 1; i < 8; i := i + 1) {
8226 if (i == 2) {
8227 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8228 } else {
8229 f_ts_set_chcomb(0, 0, i, "PDCH");
8230 }
8231 }
8232 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8233
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008234 f_init(1, guard_timeout := 60.0);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008235
8236 /* The dyn TS want to activate PDCH mode, ACK that. */
8237 var RslChannelNr chan_nr;
8238 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008239 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
8240 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008241
8242 f_sleep(1.0);
8243
8244 /* Exhaust all dedicated SDCCH lchans.
8245 /* GSM 44.018 Table 9.1.8.2:
8246 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
8247 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008248 var DchanTuples chan_cleanup := {};
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008249 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008250 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 +02008251 }
8252
8253 /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008254 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 +02008255 /* Also occupy the seven other SDCCH of the dyn TS */
8256 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008257 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 +01008258 }
8259
8260 /* Clean up SDCCH lchans */
8261 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8262 f_perform_clear_test_ct(chan_cleanup[i]);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008263 }
8264
8265 /* clean up config */
8266 f_ts_reset_chcomb(0);
8267
8268 f_shutdown_helper();
8269}
8270
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008271/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
8272 SDCCH8 would end up in having no free TCH, then BSC should decide to activate
8273 it as TCH directly instead. SYS#5309. */
8274testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
8275 var RSL_Message rsl_unused, rsl_msg;
8276 var DchanTuple dt;
8277 var BSSAP_N_CONNECT_ind rx_c_ind;
8278 var integer i;
8279
8280 /* change Timeslot 6 before f_init() starts RSL */
8281 f_init_vty();
8282 for (i := 1; i < 8; i := i + 1) {
8283 if (i == 6) {
8284 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8285 } else {
8286 f_ts_set_chcomb(0, 0, i, "PDCH");
8287 }
8288 }
8289 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8290
8291 f_init(1, false);
8292 f_sleep(1.0);
8293
8294 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8295
8296 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8297 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8298 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008299 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008300
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008301 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008302 f_sleep(1.0);
8303 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8304 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8305
8306 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8307 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008308 var DchanTuples chan_cleanup := {};
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02008309 var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008310 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008311 dt := f_est_dchan(ra, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008312 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008313 }
8314
8315 /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008316 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
8317 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8318 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008319
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008320 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008321 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008322 dt.idx := {0, 0};
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008323
8324 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008325 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8326 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008327 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
8328
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008329 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 +02008330 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8331 dt.sccp_conn_id := rx_c_ind.connectionId;
8332 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8333
8334 /* Instruct BSC to clear channel */
8335 var BssmapCause cause := 0;
8336 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008337 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008338
8339 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008340 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8341 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008342 f_sleep(1.0);
8343 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8344
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008345 /* Clean up SDCCH lchans */
8346 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8347 f_perform_clear_test_ct(chan_cleanup[i]);
8348 }
8349
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008350 /* clean up config */
8351 f_ts_reset_chcomb(0);
8352 /* TODO: clean up other channels? */
8353
8354 f_shutdown_helper();
8355}
8356
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008357/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
8358testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
8359 var RSL_Message rsl_unused, rsl_msg;
8360 var DchanTuple dt;
8361 var BSSAP_N_CONNECT_ind rx_c_ind;
8362 var GsmRrMessage rr;
8363
8364 /* change Timeslot 6 before f_init() starts RSL */
8365 f_init_vty();
8366 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8367 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8368
8369 f_init(1, false);
8370 f_sleep(1.0);
8371
8372 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8373
8374 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8375 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8376 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008377 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008378
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008379 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008380 f_sleep(1.0);
8381 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8382 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8383
8384 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8385 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008386 var DchanTuples chan_cleanup := {};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008387 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008388 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008389 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008390 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008391 }
8392
8393 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008394 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8395 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8396 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008397
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008398 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008399 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008400 dt.idx := {0, 0};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008401
8402 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008403 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
8404 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008405 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
8406 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
8407 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
8408 }
8409
8410 /* FIXME? Currently the TS stays in state BORKEN: */
8411
8412 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008413 /* rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8414 * f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008415 * f_sleep(1.0);
8416 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
8417 */
8418
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008419 /* Clean up SDCCH lchans */
8420 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8421 f_perform_clear_test_ct(chan_cleanup[i]);
8422 }
8423
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008424 /* clean up config */
8425 f_ts_set_chcomb(0, 0, 6, "PDCH");
8426
8427 f_shutdown_helper();
8428}
8429
Stefan Sperling0796a822018-10-05 13:01:39 +02008430testcase TC_chopped_ipa_ping() runs on test_CT {
Stefan Sperling554123f2018-10-09 14:12:30 +02008431 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port, mp_bsc_ctrl_port};
Stefan Sperling0796a822018-10-05 13:01:39 +02008432 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8433 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8434 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008435 f_shutdown_helper();
Stefan Sperling0796a822018-10-05 13:01:39 +02008436}
8437
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008438testcase TC_chopped_ipa_payload() runs on test_CT {
8439 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port
8440 /* TODO: mp_bsc_ctrl_port does not work yet */};
8441 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8442 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8443 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008444 f_shutdown_helper();
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008445}
8446
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008447/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
8448 the BTS does autonomous MS power control loop */
8449testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
8450 var MSC_ConnHdlr vc_conn;
8451 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8452 //pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
8453 pars.exp_ms_power_params := true;
8454
8455 f_init(1, true);
8456 f_sleep(1.0);
8457 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
8458 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008459 f_shutdown_helper();
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008460}
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008461
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008462/* Verify activation and deactivation of the BCCH carrier power reduction mode */
8463testcase TC_c0_power_red_mode() runs on test_CT {
8464 f_init(1);
8465
8466 for (var integer red := 6; red >= 0; red := red - 2) {
8467 /* Configure BCCH carrier power reduction mode via the VTY */
8468 f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
8469
8470 /* Expect Osmocom specific BS Power Control message on the RSL */
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03008471 var template (present) RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008472 chan_nr := t_RslChanNr_BCCH(0),
8473 bs_power := tr_RSL_IE_BS_Power(red / 2));
8474 tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008475 var RSL_Message unused := f_exp_ipa_rx(tr_rsl_pdu);
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008476
8477 /* Additionally verify the applied value over the CTRL interface */
8478 var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
8479 if (cred != int2str(red)) {
8480 setverdict(fail, "Unexpected BCCH carrier power reduction value ",
8481 cred, " (expected ", red, ")");
8482 }
8483 }
8484
8485 f_shutdown_helper();
8486}
8487
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008488/***********************************************************************
8489 * MSC Pooling
8490 ***********************************************************************/
8491
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008492template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
Harald Weltebf397612021-01-14 20:39:46 +01008493 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 +02008494
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008495private 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 +02008496runs on MSC_ConnHdlr {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008497 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008498 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008499 f_logp(BSCVTY, "Got RSL RR Release");
8500 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008501 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008502 f_logp(BSCVTY, "Got RSL Deact SACCH");
8503 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008504 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008505 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008506 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8507 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008508 break;
8509 }
8510 }
8511}
8512
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008513private altstep as_mgcp_ack_all_dlcx() runs on MSC_ConnHdlr {
8514 var MgcpCommand mgcp_cmd;
Oliver Smithab7354b2023-05-08 11:34:30 +02008515 var template MgcpMessage msg_dlcx := {
8516 command := tr_DLCX
8517 }
8518 var MGCP_RecvFrom mrf;
8519
8520 [g_pars.aoip] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008521 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
8522 repeat;
8523 }
Oliver Smithab7354b2023-05-08 11:34:30 +02008524
8525 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
8526 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
8527 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
8528 }));
8529 repeat;
8530 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008531}
8532
8533private altstep as_rsl_ack_all_rel_req() runs on MSC_ConnHdlr {
8534 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
8535 [] RSL.receive(tr_RSL_REL_REQ(g_chan_nr, ?)) {
8536 RSL.send(ts_RSL_REL_CONF(g_chan_nr, main_dcch));
8537 repeat;
8538 }
8539}
8540
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008541friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
8542 template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02008543runs on MSC_ConnHdlr {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008544 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8545 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008546 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008547 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8548 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008549 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008550 f_logp(BSCVTY, "Got RSL RR Release");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008551 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008552 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008553 f_logp(BSCVTY, "Got RSL Deact SACCH");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008554 }
8555 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008556 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008557 /* Also drop the SCCP connection */
8558 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8559 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008560 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008561 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008562 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8563 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008564 }
8565 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008566 deactivate(ack_dlcx);
8567 deactivate(ack_rel_req);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008568}
8569
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01008570friend function f_perform_clear_no_rr_rel(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC)
8571runs on MSC_ConnHdlr {
8572 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8573 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
8574 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8575 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8576 interleave {
8577 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
8578 f_logp(BSCVTY, "Got RSL Deact SACCH");
8579 }
8580 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
8581 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8582 /* Also drop the SCCP connection */
8583 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8584 }
8585 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
8586 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
8587 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8588 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
8589 }
8590 }
8591 deactivate(ack_dlcx);
8592 deactivate(ack_rel_req);
8593}
8594
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01008595friend function f_perform_clear_no_lchan()
8596runs on MSC_ConnHdlr {
8597 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8598 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8599 BSSAP.receive(tr_BSSMAP_ClearComplete);
8600 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8601 /* Also drop the SCCP connection */
8602 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8603}
8604
Vadim Yanitskiy65d879d2022-06-23 18:15:39 +07008605friend function f_perform_clear_test_ct(DchanTuple dt)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008606 runs on test_CT
8607{
8608 /* Instruct BSC to clear channel */
8609 var BssmapCause cause := 0;
8610 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008611 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008612}
8613
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008614private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
8615 template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008616runs on MSC_ConnHdlr {
8617 timer T := 10.0;
8618 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
8619
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008620 f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008621 f_create_bssmap_exp(l3_enc);
8622
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008623 /* RSL_Emulation.f_chan_est() on rsl_pt:
8624 * This is basically code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008625 * RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
8626 */
8627 var RSL_Message rx_rsl;
8628 var GsmRrMessage rr;
8629
8630 /* request a channel to be established */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008631 rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008632 /* expect immediate assignment.
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008633 * Code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008634 * rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
8635 */
8636 timer Tt := 10.0;
8637
8638 /* request a channel to be established */
8639 Tt.start;
8640 alt {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008641 [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008642 Tt.stop;
8643 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008644 [] rsl_pt.receive {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008645 setverdict(fail, "Unexpected RSL message on DCHAN");
8646 mtc.stop;
8647 }
8648 [] Tt.timeout {
8649 setverdict(fail, "Timeout waiting for RSL on DCHAN");
8650 mtc.stop;
8651 }
8652 }
8653 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
8654 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008655 rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008656
8657
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008658 if (expect_bssmap_l3) {
8659 f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
8660 var template PDU_BSSAP exp_l3_compl;
8661 exp_l3_compl := tr_BSSMAP_ComplL3()
8662 if (g_pars.aoip == false) {
8663 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
8664 } else {
8665 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
8666 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008667
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008668 var PDU_BSSAP bssap;
8669 T.start;
8670 alt {
8671 [] BSSAP.receive(exp_l3_compl) -> value bssap {
8672 f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
8673 log("rx exp_l3_compl = ", bssap);
8674 }
8675 [] BSSAP.receive(tr_BSSMAP_ComplL3) {
8676 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
8677 }
8678 [] T.timeout {
8679 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
8680 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008681 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008682
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008683 /* start ciphering, if requested */
8684 if (ispresent(g_pars.encr)) {
8685 f_logp(BSCVTY, "start ciphering");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008686 f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008687 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008688 }
8689
8690 if (do_clear) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008691 f_perform_clear(rsl_pt, rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008692 }
8693 setverdict(pass);
8694 f_sleep(1.0);
8695}
8696
8697private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
8698 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8699 if (g_pars.mscpool.rsl_idx == 0) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008700 f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008701 } else if (g_pars.mscpool.rsl_idx == 1) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008702 f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008703 } else if (g_pars.mscpool.rsl_idx == 2) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008704 f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008705 }
8706}
8707
8708/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
8709private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
8710 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008711 f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
8712 f_perform_compl_l3(RSL, RSL_PROC, ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_IMSI_LV('001010000000002'H))) );
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008713 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)) );
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008714 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 +02008715}
8716testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
8717
8718 f_init(1, true);
8719 f_sleep(1.0);
8720 var MSC_ConnHdlr vc_conn;
8721 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008722
8723 f_ctrs_msc_init();
8724
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008725 vc_conn := f_start_handler(refers(f_tc_mscpool_L3Compl_on_1_msc), pars);
8726 vc_conn.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008727
8728 f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008729 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008730}
8731
8732/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
8733/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8734 * just as well using only RSL. */
8735testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
8736
8737 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8738 f_sleep(1.0);
8739
8740 /* Control which MSC gets chosen next by the round-robin, otherwise
8741 * would be randomly affected by which other tests ran before this. */
8742 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8743
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008744 f_ctrs_msc_init();
8745
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008746 var MSC_ConnHdlr vc_conn1;
8747 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8748 pars1.mscpool.rsl_idx := 0;
8749 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8750 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8751 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008752 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008753
8754 var MSC_ConnHdlr vc_conn2;
8755 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8756 pars2.mscpool.rsl_idx := 1;
8757 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8758 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8759 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008760 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008761
8762 /* Test round-robin wrap to the first MSC */
8763 var MSC_ConnHdlr vc_conn3;
8764 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8765 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008766 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008767 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8768 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008769 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008770 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008771}
8772
8773/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 0
8774 * (configured in osmo-bsc.cfg). */
8775/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8776 * just as well using only RSL. */
8777testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
8778
8779 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8780 f_sleep(1.0);
8781
8782 /* Control which MSC gets chosen next by the round-robin, otherwise
8783 * would be randomly affected by which other tests ran before this. */
8784 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8785
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008786 f_ctrs_msc_init();
8787
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008788 var MSC_ConnHdlr vc_conn1;
8789 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8790 pars1.mscpool.rsl_idx := 0;
8791 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8792 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8793 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008794 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008795
8796 var MSC_ConnHdlr vc_conn2;
8797 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8798 pars2.mscpool.rsl_idx := 1;
8799 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8800 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8801 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008802 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008803
8804 /* Test round-robin wrap to the first MSC */
8805 var MSC_ConnHdlr vc_conn3;
8806 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8807 pars3.mscpool.rsl_idx := 2;
8808 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8809 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8810 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008811 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008812 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008813}
8814
8815/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
8816 * (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
8817 * NULL-NRI setting is stronger than that. */
8818/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8819 * just as well using only RSL. */
8820testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
8821
8822 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8823 f_sleep(1.0);
8824
8825 /* Control which MSC gets chosen next by the round-robin, otherwise
8826 * would be randomly affected by which other tests ran before this. */
8827 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8828
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008829 f_ctrs_msc_init();
8830
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008831 var MSC_ConnHdlr vc_conn1;
8832 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8833 pars1.mscpool.rsl_idx := 0;
8834 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8835 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8836 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008837 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008838
8839 var MSC_ConnHdlr vc_conn2;
8840 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8841 pars2.mscpool.rsl_idx := 1;
8842 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8843 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8844 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008845 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008846
8847 /* Test round-robin wrap to the first MSC */
8848 var MSC_ConnHdlr vc_conn3;
8849 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8850 pars3.mscpool.rsl_idx := 2;
8851 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8852 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8853 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008854 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008855 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008856}
8857
8858/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
8859 * assigned to any MSC (configured in osmo-bsc.cfg). */
8860/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8861 * just as well using only RSL. */
8862testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test_CT {
8863
8864 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8865 f_sleep(1.0);
8866
8867 /* Control which MSC gets chosen next by the round-robin, otherwise
8868 * would be randomly affected by which other tests ran before this. */
8869 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8870
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008871 f_ctrs_msc_init();
8872
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008873 var MSC_ConnHdlr vc_conn1;
8874 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8875 pars1.mscpool.rsl_idx := 0;
8876 /* An NRI that is not assigned to any MSC */
8877 pars1.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(1023))));
8878 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8879 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008880 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008881
8882 var MSC_ConnHdlr vc_conn2;
8883 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8884 pars2.mscpool.rsl_idx := 1;
8885 /* An NRI that is not assigned to any MSC */
8886 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(768)), '00F110'O));
8887 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8888 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008889 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008890
8891 /* Test round-robin wrap to the first MSC */
8892 var MSC_ConnHdlr vc_conn3;
8893 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8894 pars3.mscpool.rsl_idx := 2;
8895 /* An NRI that is not assigned to any MSC */
8896 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, valueof(ts_MI_TMSI_NRI_LV(819))));
8897 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8898 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008899 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008900 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008901}
8902
8903/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
8904 * assigned to an MSC that is currently not connected (configured in osmo-bsc.cfg). */
8905/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8906 * just as well using only RSL. */
8907testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
8908
8909 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8910 f_sleep(1.0);
8911
8912 /* Control which MSC gets chosen next by the round-robin, otherwise
8913 * would be randomly affected by which other tests ran before this. */
8914 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8915
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008916 f_ctrs_msc_init();
8917
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008918 var MSC_ConnHdlr vc_conn1;
8919 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8920 pars1.mscpool.rsl_idx := 0;
8921 /* An NRI that is assigned to an unconnected MSC */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008922 pars1.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(512)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008923 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8924 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008925 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8926 f_ctrs_msc_add(0, "mscpool:subscr:new");
8927 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008928
8929 var MSC_ConnHdlr vc_conn2;
8930 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8931 pars2.mscpool.rsl_idx := 1;
8932 /* An NRI that is assigned to an unconnected MSC */
8933 pars2.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(767))));
8934 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8935 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008936 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8937 f_ctrs_msc_add(1, "mscpool:subscr:new");
8938 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008939
8940 /* Test round-robin wrap to the first MSC */
8941 var MSC_ConnHdlr vc_conn3;
8942 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8943 pars3.mscpool.rsl_idx := 2;
8944 /* An NRI that is assigned to an unconnected MSC */
8945 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(750)), '00F110'O));
8946 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8947 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008948 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8949 f_ctrs_msc_add(0, "mscpool:subscr:new");
8950 f_ctrs_msc_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008951 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008952}
8953
8954/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
8955 * osmo-bsc.cfg). */
8956/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8957 * just as well using only RSL. */
8958testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
8959
8960 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8961 f_sleep(1.0);
8962
8963 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
8964 * this is not using round-robin. */
8965 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8966
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008967 f_ctrs_msc_init();
8968
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008969 var MSC_ConnHdlr vc_conn1;
8970 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8971 pars1.mscpool.rsl_idx := 0;
8972 /* An NRI of the second MSC's range (256-511) */
8973 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(256))));
8974 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8975 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008976 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008977
8978 var MSC_ConnHdlr vc_conn2;
8979 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8980 pars2.mscpool.rsl_idx := 1;
8981 /* An NRI of the second MSC's range (256-511) */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008982 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(260)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008983 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8984 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008985 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008986
8987 var MSC_ConnHdlr vc_conn3;
8988 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8989 pars3.mscpool.rsl_idx := 2;
8990 /* An NRI of the second MSC's range (256-511) */
8991 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(511)), '00F110'O));
8992 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8993 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008994 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008995 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008996}
8997
8998/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
8999 * while a round-robin remains unaffected by that. */
9000/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
9001 * just as well using only RSL. */
9002testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
9003
9004 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9005 f_sleep(1.0);
9006
9007 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
9008 * this is not using round-robin. */
9009 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
9010
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009011 f_ctrs_msc_init();
9012
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009013 var MSC_ConnHdlr vc_conn1;
9014 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 2);
9015 pars1.mscpool.rsl_idx := 0;
9016 /* An NRI of the third MSC's range (512-767) */
9017 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(512))));
9018 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9019 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009020 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009021
9022 var MSC_ConnHdlr vc_conn2;
9023 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9024 pars2.mscpool.rsl_idx := 1;
9025 /* An NRI of the third MSC's range (512-767) */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009026 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(678)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009027 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9028 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009029 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009030
9031 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
9032 var MSC_ConnHdlr vc_conn3;
9033 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
9034 pars3.mscpool.rsl_idx := 2;
9035 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000013'H)), '00F110'O));
9036 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9037 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009038 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009039 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009040}
9041
9042/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
9043/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
9044 * just as well using only RSL. */
9045testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
9046
9047 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9048 f_sleep(1.0);
9049
9050 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
9051 * instead, and hits msc 0. */
9052 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9053
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009054 f_ctrs_msc_init();
9055
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009056 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-bsc.cfg */
9057 var MSC_ConnHdlr vc_conn1;
9058 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9059 pars1.mscpool.rsl_idx := 0;
9060 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(260)), '99F999'O));
9061 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9062 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009063 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009064
9065 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
9066 var MSC_ConnHdlr vc_conn2;
9067 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9068 pars2.mscpool.rsl_idx := 1;
9069 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(555)), '00F110'O));
9070 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9071 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009072 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009073 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009074}
9075
9076/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
9077 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9078private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
9079 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9080 //cid_list := { cIl_allInBSS := ''O };
9081 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9082 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9083 var BSSAP_N_UNITDATA_req paging;
9084 var hexstring imsi := '001010000000123'H;
9085
9086 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9087
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009088 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009089 valueof(ts_BSSMAP_Paging(imsi, cid_list, omit, bssmap_chneed))));
9090 BSSAP.send(paging);
9091
9092 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9093 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9094 * channel number is picked here. */
9095 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9096 f_rslem_register(0, new_chan_nr);
9097 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(imsi)));
9098 f_rslem_unregister(0, new_chan_nr);
9099
9100 /* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
9101 * causes this Paging Response to go to the first MSC (bssap_idx := 0). */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009102 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV(imsi)) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009103 f_sleep(1.0);
9104}
9105testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
9106 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9107 f_sleep(1.0);
9108
9109 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9110 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9111 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
9112
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009113 f_ctrs_msc_init();
9114
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009115 var MSC_ConnHdlr vc_conn1;
9116 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9117 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009118 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9119 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009120 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
9121 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009122 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009123 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009124}
9125
9126/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
9127 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9128private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
9129 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9130 //cid_list := { cIl_allInBSS := ''O };
9131 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9132 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9133 var integer nri_v := 300; /* <-- second MSC's NRI */
Harald Weltebf397612021-01-14 20:39:46 +01009134 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009135 var BSSAP_N_UNITDATA_req paging;
9136
9137 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9138
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009139 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009140 valueof(ts_BSSMAP_Paging('001010000000011'H, cid_list, tmsi, bssmap_chneed))));
9141 BSSAP.send(paging);
9142
9143 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9144 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9145 * channel number is picked here. */
9146 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9147 f_rslem_register(0, new_chan_nr);
9148 RSL.receive(tr_RSL_PAGING_CMD(t_MI_TMSI(tmsi)));
9149 f_rslem_unregister(0, new_chan_nr);
9150
9151 /* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
9152 * third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
9153 * the first MSC (bssap_idx := 0). */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009154 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_TMSI_NRI_LV(nri_v)) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009155 f_sleep(1.0);
9156}
9157testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
9158 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9159 f_sleep(1.0);
9160
9161 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9162 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9163 f_vty_transceive(BSCVTY, "mscpool roundrobin next 2");
9164
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009165 f_ctrs_msc_init();
9166
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009167 var MSC_ConnHdlr vc_conn1;
9168 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9169 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009170 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9171 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009172 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
9173 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009174 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009175 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009176}
9177
9178/* For round-robin, skip an MSC that has 'no allow-attach' set. */
9179/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
9180 * just as well using only RSL. */
9181testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
9182
9183 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9184 f_sleep(1.0);
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009185 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9186 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009187
9188 /* Control which MSC gets chosen next by the round-robin, otherwise
9189 * would be randomly affected by which other tests ran before this. */
9190 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9191
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009192 f_ctrs_msc_init();
9193
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009194 var MSC_ConnHdlr vc_conn1;
9195 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9196 pars1.mscpool.rsl_idx := 0;
9197 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9198 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9199 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009200 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009201
9202 var MSC_ConnHdlr vc_conn2;
9203 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9204 pars2.mscpool.rsl_idx := 1;
9205 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9206 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9207 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009208 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009209
9210 var MSC_ConnHdlr vc_conn3;
9211 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
9212 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009213 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009214 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9215 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009216 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009217 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009218}
9219
9220/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
9221 * TMSI NRI. */
9222testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
9223
9224 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9225 f_sleep(1.0);
9226
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009227 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9228 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
9229
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009230 /* Control which MSC gets chosen next by the round-robin, otherwise
9231 * would be randomly affected by which other tests ran before this. */
9232 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9233
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009234 f_ctrs_msc_init();
9235
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009236 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
9237 var MSC_ConnHdlr vc_conn1;
9238 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
9239 pars1.mscpool.rsl_idx := 0;
9240 /* An NRI of the second MSC's range (256-511) */
9241 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_TMSI_NRI_LV(260))));
9242 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9243 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009244 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009245
9246 var MSC_ConnHdlr vc_conn2;
9247 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9248 pars2.mscpool.rsl_idx := 1;
9249 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9250 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9251 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009252 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009253
9254 var MSC_ConnHdlr vc_conn3;
9255 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 2);
9256 pars3.mscpool.rsl_idx := 2;
9257 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000003'H))));
9258 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9259 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009260 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009261 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009262}
9263
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009264/* When an MSC point-code gets an SCCP N-PCSTATE saying it is unreachable, immediately mark the MSC as unusable. */
9265testcase TC_mscpool_sccp_n_pcstate_detaches_msc() runs on test_CT {
9266
9267 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
9268 f_sleep(1.0);
9269
9270 /* Control which MSC gets chosen next by the round-robin, otherwise
9271 * would be randomly affected by which other tests ran before this. */
9272 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9273
9274 f_ctrs_msc_init();
9275
9276 var MSC_ConnHdlr vc_conn1;
9277 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9278 pars1.mscpool.rsl_idx := 0;
9279 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9280 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9281 vc_conn1.done;
9282 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9283
9284 var MSC_ConnHdlr vc_conn2;
9285 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
9286 pars2.mscpool.rsl_idx := 1;
9287 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9288 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9289 vc_conn2.done;
9290 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9291
9292 f_logp(BSCVTY, "disconnecting msc0");
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009293 f_bssap_idx_disconnect(0);
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009294
9295 /* Now round-robin would wrap to the first MSC, but since the first MSC is disconnected, it wraps around to msc
9296 * 2 again. */
9297 var MSC_ConnHdlr vc_conn3;
9298 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
9299 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009300 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009301 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9302 vc_conn3.done;
9303 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9304 f_shutdown_helper();
9305}
9306
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009307/* When an MSC point-code gets an SCCP N-PCSTATE saying it is now reachable, immediately trigger RESET and bring up the
9308 * MSC. */
9309testcase TC_mscpool_sccp_n_pcstate_attaches_msc() runs on test_CT {
9310
9311 f_init(nr_bts := 3, handler_mode := true, nr_msc := 1);
9312 f_sleep(1.0);
9313
9314 /* Control which MSC gets chosen next by the round-robin, otherwise
9315 * would be randomly affected by which other tests ran before this. */
9316 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9317
9318 f_ctrs_msc_init();
9319
9320 /* There is only one MSC, round robin stays on msc0 */
9321 var MSC_ConnHdlr vc_conn1;
9322 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9323 pars1.mscpool.rsl_idx := 0;
9324 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('0010100230000001'H)), '00F110'O));
9325 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9326 vc_conn1.done;
9327 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9328
9329 var MSC_ConnHdlr vc_conn2;
9330 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9331 pars2.mscpool.rsl_idx := 1;
9332 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010023000002'H))));
9333 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9334 vc_conn2.done;
9335 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9336
9337 f_logp(BSCVTY, "connecting msc1");
9338 f_vty_msc_allow_attach(BSCVTY, { true, true });
9339 f_bssap_idx_init(1);
9340 f_sleep(1.0);
9341
9342 /* This time round-robin wraps to the second MSC, because it is now online. */
9343 var MSC_ConnHdlr vc_conn4;
9344 var TestHdlrParams pars4 := f_gen_test_hdlr_pars(bssap_idx := 1);
9345 pars4.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009346 pars4.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010023000003'H)));
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009347 vc_conn4 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars4);
9348 vc_conn4.done;
9349 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9350
9351 f_shutdown_helper();
9352}
9353
Philipp Maier783681c2020-07-16 16:47:06 +02009354/* Allow/Deny emergency calls globally via VTY */
9355private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
9356 f_vty_enter_cfg_msc(BSCVTY, 0);
9357 if (allow) {
9358 f_vty_transceive(BSCVTY, "allow-emergency allow");
9359 } else {
9360 f_vty_transceive(BSCVTY, "allow-emergency deny");
9361 }
9362 f_vty_transceive(BSCVTY, "exit");
9363 f_vty_transceive(BSCVTY, "exit");
9364}
9365
9366/* Allow/Deny emergency calls per BTS via VTY */
9367private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
9368 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9369 if (allow) {
9370 f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
9371 } else {
9372 f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
9373 }
9374 f_vty_transceive(BSCVTY, "exit");
9375 f_vty_transceive(BSCVTY, "exit");
Neels Hofmeyrb6ed80c2020-10-12 22:52:39 +00009376 f_vty_transceive(BSCVTY, "exit");
Philipp Maier783681c2020-07-16 16:47:06 +02009377}
9378
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02009379/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
9380private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
9381 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9382 if (allow) {
9383 f_vty_transceive(BSCVTY, "srvcc fast-return allow");
9384 } else {
9385 f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
9386 }
9387 f_vty_transceive(BSCVTY, "exit");
9388 f_vty_transceive(BSCVTY, "exit");
9389 f_vty_transceive(BSCVTY, "exit");
9390}
9391
Pau Espin Pedrol14475352021-07-22 15:48:16 +02009392/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
9393private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
9394 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9395 if (allow) {
9396 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
9397 } else {
9398 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
9399 }
9400 f_vty_transceive(BSCVTY, "exit");
9401 f_vty_transceive(BSCVTY, "exit");
9402 f_vty_transceive(BSCVTY, "exit");
9403}
9404
Pau Espin Pedrol35609792023-01-03 16:56:59 +01009405/* Begin assignment procedure and send an EMERGENCY SETUP (RR) */
Philipp Maier783681c2020-07-16 16:47:06 +02009406private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
9407 var PDU_ML3_MS_NW emerg_setup;
9408 var octetstring emerg_setup_enc;
9409 var RSL_Message emerg_setup_data_ind;
9410
9411 f_establish_fully(omit, omit);
9412
9413 emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
9414 emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
9415 emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
9416
9417 RSL.send(emerg_setup_data_ind);
9418}
9419
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009420/* expect EmergencySetup on BSSAP after calling f_assignment_emerg_setup() */
9421private function f_assignment_emerg_setup_exp_bssap()
9422runs on MSC_ConnHdlr {
Philipp Maier783681c2020-07-16 16:47:06 +02009423 var PDU_BSSAP emerg_setup_data_ind_bssap;
9424 var PDU_ML3_MS_NW emerg_setup;
9425 timer T := 3.0;
9426
Philipp Maier783681c2020-07-16 16:47:06 +02009427 T.start;
9428 alt {
9429 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
9430 emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
9431 if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
9432 setverdict(fail, "no emergency setup");
9433 }
9434 }
9435 [] BSSAP.receive {
9436 setverdict(fail, "unexpected BSSAP message!");
9437 }
9438 [] T.timeout {
9439 setverdict(fail, "timout waiting for EMERGENCY SETUP!");
9440 }
9441 }
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009442}
9443
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009444private function f_assignment_emerg_setup_voice()
9445runs on MSC_ConnHdlr {
9446 /* Go on with voice call assignment */
9447 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
9448 var PDU_BSSAP ass_cmd := f_gen_ass_req();
9449
9450 /* Below speechOrDataIndicator and codecList are copied from an emergency call captured during tests.
9451 * They seem a bit weird (AMR-WB, and the order differ between speechId_DataIndicator and the codecList), but
9452 * seems a good idea to see how osmo-bsc reacts to this. */
9453 ass_cmd.pdu.bssmap.assignmentRequest.channelType := {
9454 elementIdentifier := '0B'O, /* overwritten */
9455 lengthIndicator := 0, /* overwritten */
9456 speechOrDataIndicator := '0001'B, /* speech */
9457 spare1_4 := '0000'B,
9458 channelRateAndType := ChRate_TCHForH_Fpref,
9459 speechId_DataIndicator := 'c2918105'O
9460 };
9461 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({
9462 ts_CodecHR, ts_CodecAMR_WB, ts_CodecEFR, ts_CodecFR}));
9463
9464 f_rslem_dchan_queue_enable();
9465
9466 var ExpectCriteria mgcpcrit := {
9467 connid := omit,
9468 endpoint := omit,
9469 transid := omit
9470 };
9471 f_create_mgcp_expect(mgcpcrit);
9472
9473 BSSAP.send(ass_cmd);
9474
9475 var AssignmentState st := valueof(ts_AssignmentStateInit);
Oliver Smithce2dd692023-04-17 10:25:50 +02009476 st.rtp_stream := true;
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009477 st.is_assignment := false;
9478 alt {
9479 [] as_modify(st);
9480 [] as_Media();
9481 [st.modify_done] BSSAP.receive(exp_compl) {
9482 setverdict(pass);
9483 }
9484 }
9485
9486 /* Voice call carries on ... */
9487 f_sleep(2.0);
9488}
9489
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009490/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
9491 * CALLS are permitted by the BSC config. */
9492private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
9493
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009494 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
9495 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
9496 * another lchan. */
9497 g_pars.ra := f_rnd_ra_emerg();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009498 f_assignment_emerg_setup();
9499 f_assignment_emerg_setup_exp_bssap();
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009500 f_assignment_emerg_setup_voice();
Philipp Maier783681c2020-07-16 16:47:06 +02009501
9502 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009503 f_perform_clear();
Philipp Maier783681c2020-07-16 16:47:06 +02009504}
9505
9506/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
9507 * forbidden by the BSC config. */
9508private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
9509 var PDU_BSSAP emerg_setup_data_ind_bssap;
9510 timer T := 3.0;
9511
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009512 f_assignment_emerg_setup();
Philipp Maier783681c2020-07-16 16:47:06 +02009513
9514 T.start;
9515 alt {
9516 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
9517 setverdict(pass);
9518 }
9519 [] RSL.receive {
9520 setverdict(fail, "unexpected RSL message!");
9521 }
9522 [] T.timeout {
9523 setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
9524 }
9525 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009526 BSSAP.receive(tr_BSSMAP_ClearRequest);
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01009527 f_perform_clear_no_rr_rel();
Philipp Maier783681c2020-07-16 16:47:06 +02009528}
9529
9530/* EMERGENCY CALL situation #1, allowed globally and by BTS */
9531testcase TC_assignment_emerg_setup_allow() runs on test_CT {
9532 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9533 var MSC_ConnHdlr vc_conn;
9534
9535 f_init(1, true);
9536 f_sleep(1.0);
9537
9538 f_vty_allow_emerg_msc(true);
9539 f_vty_allow_emerg_bts(true, 0);
9540 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9541 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009542 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009543}
9544
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +01009545/* Test MO emergency call using MobileIdentity=IMEI (possible for emergency
9546 * calls from phones without SIM card).
9547 * 3GPP TS 24.008 section 10.5.1.4, OS#5849 */
9548testcase TC_assignment_emerg_setup_allow_imei() runs on test_CT {
9549 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9550 var MSC_ConnHdlr vc_conn;
9551
9552 /* Remove IMSI set by f_gen_test_hdlr_pars(), then IMEI will be used to place the call */
9553 pars.imsi := omit;
9554
9555 f_init(1, true);
9556 f_sleep(1.0);
9557
9558 f_vty_allow_emerg_msc(true);
9559 f_vty_allow_emerg_bts(true, 0);
9560 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9561 vc_conn.done;
9562 f_shutdown_helper();
9563}
9564
Philipp Maier783681c2020-07-16 16:47:06 +02009565/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
9566testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
9567 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9568 var MSC_ConnHdlr vc_conn;
9569
9570 f_init(1, true);
9571 f_sleep(1.0);
9572
9573 f_vty_allow_emerg_msc(false);
9574 f_vty_allow_emerg_bts(true, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009575 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx): */
9576 pars.ra := f_rnd_ra_emerg();
Philipp Maier783681c2020-07-16 16:47:06 +02009577 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9578 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009579 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009580}
9581
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009582/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS.
9583 * The RACH req (and hence CHAN RQD) indicate other than emergency call.
9584 * Hence BSC only learns about it being an emergency call later during call setup.
9585 * If interested in the ra="emergency call" + deny bts policy case,
9586 * see TC_chan_rqd_emerg_deny.
9587 */
Philipp Maier783681c2020-07-16 16:47:06 +02009588testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
9589 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9590 var MSC_ConnHdlr vc_conn;
9591
9592 /* Note: This simulates a spec violation by the MS, correct MS
9593 * implementations would not try to establish an emergency call because
9594 * the system information tells in advance that emergency calls are
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009595 * not allowed */
Philipp Maier783681c2020-07-16 16:47:06 +02009596
9597 f_init(1, true);
9598 f_sleep(1.0);
9599
9600 f_vty_allow_emerg_msc(true);
9601 f_vty_allow_emerg_bts(false, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009602 /* Note: Here we implicitly leave default g_pars.ra which is different than "emergency call" */
Philipp Maier783681c2020-07-16 16:47:06 +02009603 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9604 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009605 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009606}
9607
Philipp Maier82812002020-08-13 18:48:27 +02009608/* Test what happens when an emergency call arrives while all TCH channels are
9609 * busy, the BSC is expected to terminate one call in favor of the incoming
9610 * emergency call */
9611testcase TC_emerg_premption() runs on test_CT {
9612 var ASP_RSL_Unitdata rsl_ud;
9613 var integer i;
9614 var integer chreq_total, chreq_nochan;
9615 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009616 var octetstring l3_payload := gen_l3_valid_payload();
Philipp Maier82812002020-08-13 18:48:27 +02009617
9618 f_init(1);
9619 f_sleep(1.0);
9620
9621 f_vty_allow_emerg_msc(true);
9622 f_vty_allow_emerg_bts(true, 0);
9623
9624 /* Fill up all channels on the BTS */
9625 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
9626 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
9627 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 +02009628 f_chreq_act_ack('33'O, i);
Philipp Maier82812002020-08-13 18:48:27 +02009629 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009630 IPA_RSL[0][0].clear;
Philipp Maier82812002020-08-13 18:48:27 +02009631 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
9632 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
9633
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009634 /* Send EST IND for the first TCH, so we get to test the RR release cause */
9635 var RslChannelNr first_tch := valueof(t_RslChanNr_Bm(1));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009636 f_ipa_tx(ts_RSL_EST_IND(first_tch, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009637
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009638 /* Accept BSSAP conn, so we get to test the Clear Request cause */
9639 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009640 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009641 var integer sccp_conn_id := rx_c_ind.connectionId;
9642 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
9643
Philipp Maier82812002020-08-13 18:48:27 +02009644 /* Send Channel request for emegergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009645 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier82812002020-08-13 18:48:27 +02009646
9647 /* Expect the BSC to release one (the first) TCH/F on the BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009648 f_expect_chan_rel(first_tch, expect_rr_chan_rel := true, expect_rll_rel_req := false,
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009649 expect_rr_cause := GSM48_RR_CAUSE_PREMPTIVE_REL);
Philipp Maier82812002020-08-13 18:48:27 +02009650
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009651 /* Also expect a BSSMAP Clear Request with PREEMPTION */
9652 var BSSAP_N_DATA_ind rx_clear_req;
9653 const myBSSMAP_Cause preemption := GSM0808_CAUSE_PREEMPTION;
9654 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_clear_req;
9655 log("XXX ", rx_clear_req);
9656 if (rx_clear_req.userData.pdu.bssmap.clearRequest.cause.causeValue != int2bit(enum2int(preemption), 7)) {
9657 setverdict(fail, "BSSMAP Clear Request: expected cause PREEMPTION");
9658 }
9659
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009660 /* Expect the BSC to send activate/assign the channel for the emergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009661 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009662 if (first_tch != rx_rsl.ies[0].body.chan_nr) {
9663 setverdict(fail, "different TCH lchan activated than expected");
9664 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009665 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(first_tch, 33));
9666 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Philipp Maier104f4c02020-09-11 18:12:18 +02009667
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009668 /* complete the BSSMAP Clear to satisfy the conn leak check */
9669 BSSAP.send(ts_BSSAP_DATA_req(sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(preemption))));
9670 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearComplete)) {
9671 BSSAP.send(ts_BSSAP_DISC_req(sccp_conn_id, 0));
9672 }
9673
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009674 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009675}
9676
9677/* Hopping parameters per a timeslot */
Vadim Yanitskiybc6654a2020-09-13 01:27:40 +07009678private type record length(0..64) of GsmArfcn ArfcnList;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009679private type record FHParamsTs {
9680 boolean enabled,
9681 uint6_t hsn,
9682 uint6_t maio,
9683 ArfcnList ma
9684};
9685
9686/* Hopping parameters per a transceiver */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009687private type record FHParamsTrx {
Philipp Maier798d8952021-10-19 14:43:19 +02009688 GsmBandArfcn arfcn,
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009689 FHParamsTs ts[8]
9690};
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009691
9692/* Randomly generate the hopping parameters for the given timeslot numbers */
9693private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
9694runs on test_CT return FHParamsTrx {
9695 var FHParamsTrx fhp;
9696
Philipp Maier798d8952021-10-19 14:43:19 +02009697 /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
9698 * fall in the GSM900 band. */
9699 fhp.arfcn.arfcn := f_rnd_int(3);
9700 fhp.arfcn.pcs := false;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009701
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009702 for (var integer tn := 0; tn < 8; tn := tn + 1) {
9703 if (not match(tn, tr_tn)) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009704 fhp.ts[tn].enabled := false;
9705 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009706 continue;
9707 }
9708
9709 /* Random HSN / MAIO values: 0..63 */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009710 fhp.ts[tn].hsn := f_rnd_int(64);
9711 fhp.ts[tn].maio := f_rnd_int(64);
9712 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009713
9714 /* Random Mobile Allocation (hopping channels) */
9715 var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
9716 var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
9717 for (var integer i := 1; i <= ma_len; i := i + 1) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009718 fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009719 }
9720
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009721 fhp.ts[tn].enabled := true;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009722 }
9723
9724 log("f_TC_fh_params_gen(): ", fhp);
9725 return fhp;
9726}
9727
9728/* Make sure that the given Channel Description IE matches the hopping configuration */
9729private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
9730{
9731 var template (present) ChannelDescription tr_cd;
9732 var template (present) MaioHsn tr_maio_hsn;
9733 var uint3_t tn := cd.chan_nr.tn;
9734
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009735 if (fhp.ts[tn].enabled) {
9736 tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009737 tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
9738 } else {
Philipp Maier798d8952021-10-19 14:43:19 +02009739 tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009740 }
9741
9742 if (not match(cd, tr_cd)) {
9743 setverdict(fail, "Channel Description IE does not match: ",
9744 cd, " vs expected ", tr_cd);
9745 }
9746}
9747
9748/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
9749private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
9750 in MobileAllocationLV ma)
9751{
9752 var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
9753
9754 if (not match(ma, tr_ma)) {
9755 setverdict(fail, "Mobile Allocation IE does not match (tn := ",
9756 tn, "): ", ma, " vs expected: ", tr_ma);
9757 } else {
9758 setverdict(pass);
9759 }
9760}
9761
9762private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
9763 in MobileAllocationLV ma)
9764return template MobileAllocationLV {
9765 /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009766 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009767 return { len := 0, ma := ''B };
9768 }
9769
9770 var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
9771 var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
9772 var bitstring ma_mask := ''B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009773
9774 /* Compose the full bit-mask (all channels, up to 1024 entries) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009775 for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
9776 for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
9777 if (full_mask[fhp.ts[i].ma[j]] == '1'B)
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009778 { continue; }
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009779 full_mask[fhp.ts[i].ma[j]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009780 }
9781 }
9782
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009783 /* Take ARFCN of the TRX itself into account */
Philipp Maier798d8952021-10-19 14:43:19 +02009784 full_mask[fhp.arfcn.arfcn] := '1'B;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009785
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009786 /* Compose a bit-mask for the given timeslot number */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009787 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9788 slot_mask[fhp.ts[tn].ma[i]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009789 }
9790
9791 /* Finally, compose the Mobile Allocation bit-mask */
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009792 for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009793 if (full_mask[i] != '1'B)
9794 { continue; }
9795
9796 /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
9797 if (slot_mask[i] == '1'B) {
9798 ma_mask := ma_mask & '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009799 } else {
9800 ma_mask := ma_mask & '0'B;
9801 }
9802 }
9803
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009804 /* ARFCN 0 (if present) goes to the last position of the bit-mask */
9805 if (full_mask[0] == '1'B) {
9806 /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
9807 if (slot_mask[0] == '1'B) {
9808 ma_mask := ma_mask & '1'B;
9809 } else {
9810 ma_mask := ma_mask & '0'B;
9811 }
9812 }
9813
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009814 /* Ensure that ma_mask is octet-aligned */
Vadim Yanitskiy2aa02522020-09-06 14:05:23 +07009815 var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009816 ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
9817
9818 return { len := ma_mask_len, ma := ma_mask };
9819}
9820
Philipp Maier798d8952021-10-19 14:43:19 +02009821/* Configure the appropriate band for a given arfcn, exc */
9822private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
9823{
9824 var charstring band;
9825 var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
9826
9827 select (arfcn_) {
9828 case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
9829 case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
9830 case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
9831 case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
9832 case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
9833 case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
9834 case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
9835 case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
9836 case else { return; }
9837 }
9838
9839 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9840 f_vty_transceive(BSCVTY, "band " & band);
9841 f_vty_transceive(BSCVTY, "end");
9842}
9843
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009844/* Configure the hopping parameters in accordance with the given record */
9845private function f_TC_fh_params_set(in FHParamsTrx fhp,
9846 uint8_t bts_nr := 0,
9847 uint8_t trx_nr := 0)
9848runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009849
9850 f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
9851
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009852 /* Enter the configuration node for the given BTS/TRX numbers */
9853 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9854
Philipp Maier798d8952021-10-19 14:43:19 +02009855 f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009856
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009857 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009858 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9859
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009860 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009861 f_vty_transceive(BSCVTY, "hopping enabled 0");
9862 f_vty_transceive(BSCVTY, "exit"); /* go back */
9863 continue;
9864 }
9865
9866 /* Configure HSN / MAIO values */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009867 f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
9868 f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009869
9870 /* Configure the Mobile Allocation (hopping channels) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009871 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9872 f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009873 }
9874
9875 f_vty_transceive(BSCVTY, "hopping enabled 1");
9876 f_vty_transceive(BSCVTY, "exit"); /* go back */
9877 }
9878
9879 f_vty_transceive(BSCVTY, "end");
9880}
9881
9882/* Disable frequency hopping on all timeslots */
9883private function f_TC_fh_params_unset(in FHParamsTrx fhp,
9884 uint8_t bts_nr := 0,
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009885 uint8_t trx_nr := 0,
Philipp Maier798d8952021-10-19 14:43:19 +02009886 GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009887runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009888
9889 f_TC_set_band_by_arfcn(bts_nr, arfcn);
9890
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009891 /* Enter the configuration node for the given BTS/TRX numbers */
9892 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9893
Philipp Maier798d8952021-10-19 14:43:19 +02009894 f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009895
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009896 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009897 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9898
9899 /* Delete all ARFCNs from the Mobile Allocation (if any) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009900 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9901 f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009902 }
9903
9904 f_vty_transceive(BSCVTY, "hopping enabled 0");
9905 f_vty_transceive(BSCVTY, "exit"); /* go back */
9906 }
9907
9908 f_vty_transceive(BSCVTY, "end");
9909 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9910}
9911
9912/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
9913 * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
9914testcase TC_fh_params_chan_activ() runs on test_CT {
9915 var FHParamsTrx fhp := f_TC_fh_params_gen();
9916 var RSL_Message rsl_msg;
9917 var RSL_IE_Body ie;
9918
9919 f_init_vty();
9920
9921 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9922 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9923
9924 f_init(1);
9925
9926 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9927 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009928 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9929 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009930
9931 /* Make sure that Channel Identification IE is present */
9932 if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
9933 setverdict(fail, "RSL Channel Identification IE is absent");
9934 continue;
9935 }
9936
9937 /* Make sure that hopping parameters (HSN/MAIO) match */
9938 f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
9939
9940 /* "Mobile Allocation shall be included but empty" - let's check this */
9941 if (ie.chan_ident.ma.v.len != 0) {
9942 setverdict(fail, "Mobile Allocation IE is not empty: ",
9943 ie.chan_ident.ma, ", despite it shall be");
9944 continue;
9945 }
9946 }
9947
9948 /* Disable frequency hopping */
9949 f_TC_fh_params_unset(fhp);
9950
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009951 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009952}
9953
9954/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
9955testcase TC_fh_params_imm_ass() runs on test_CT {
9956 var FHParamsTrx fhp := f_TC_fh_params_gen();
9957 var RSL_Message rsl_msg;
9958 var RSL_IE_Body ie;
9959
9960 f_init_vty();
9961
9962 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9963 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9964
9965 f_init(1);
9966
9967 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9968 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009969 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9970 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009971
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009972 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9973 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009974
9975 /* Make sure that Full Immediate Assign Info IE is present */
9976 if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
9977 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
9978 continue;
9979 }
9980
9981 /* Decode the actual Immediate Assignment message */
9982 var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
9983 if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
9984 setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
9985 continue;
9986 }
9987
9988 /* Make sure that hopping parameters (HSN/MAIO) match */
9989 f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
9990
9991 /* Make sure that the Mobile Allocation IE matches */
9992 f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
9993 rr_msg.payload.imm_ass.mobile_allocation);
9994 }
9995
9996 /* Disable frequency hopping */
9997 f_TC_fh_params_unset(fhp);
Philipp Maier82812002020-08-13 18:48:27 +02009998
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009999 f_shutdown_helper();
Philipp Maier82812002020-08-13 18:48:27 +020010000}
10001
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010002/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
10003testcase TC_fh_params_assignment_cmd() runs on test_CT {
10004 var FHParamsTrx fhp := f_TC_fh_params_gen();
10005 var RSL_Message rsl_msg;
10006 var RSL_IE_Body ie;
10007
10008 f_init_vty();
10009
10010 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
10011 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10012
10013 f_init(1);
10014
10015 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020010016 vc_MGCP[0].stop;
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010017
10018 var template PDU_BSSAP ass_cmd := f_gen_ass_req();
10019 ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
10020
10021 /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
10022 * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
10023 for (var integer i := 0; i < 3; i := i + 1) {
10024 /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010010025 var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010026
10027 /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
10028 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010029 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010030
10031 /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010032 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
10033 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010034
10035 /* Make sure that L3 Information IE is present */
10036 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
10037 setverdict(fail, "RSL L3 Information IE is absent");
10038 continue;
10039 }
10040
10041 /* Decode the L3 message and make sure it is (RR) Assignment Command */
10042 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
10043 if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
10044 setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
10045 continue;
10046 }
10047
10048 /* Make sure that hopping parameters (HSN/MAIO) match */
10049 var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
10050 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10051
10052 /* Make sure that Cell Channel Description IE is present if FH is enabled */
10053 if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
Vadim Yanitskiy38d069d2020-09-02 17:18:57 +070010054 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010055 continue;
10056 }
10057
10058 /* Make sure that the Mobile Allocation IE matches (if present) */
10059 var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
10060 if (chan_desc.h and ma_present) {
10061 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10062 l3_msg.payload.ass_cmd.mobile_allocation.v);
10063 } else if (chan_desc.h and not ma_present) {
10064 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10065 continue;
10066 } else if (not chan_desc.h and ma_present) {
10067 setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
10068 continue;
10069 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010070
10071 f_perform_clear_test_ct(dt);
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010072 }
10073
10074 /* Give the IUT some time to release all channels */
10075 f_sleep(3.0);
10076
10077 /* Disable frequency hopping */
10078 f_TC_fh_params_unset(fhp);
10079
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010080 f_shutdown_helper();
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010081}
10082
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010083/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
10084private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
10085runs on test_CT {
10086 var RSL_Message rsl_msg;
10087 var RSL_IE_Body ie;
10088 var DchanTuple dt;
10089
10090 /* Establish a dedicated channel, so we can trigger handover */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010010091 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyc18ff472021-11-18 20:15:37 +030010092 f_sleep(0.5);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010093
10094 /* Trigger handover from BTS0 to BTS1 */
10095 f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
10096 f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
10097
10098 /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010099 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx := {1, 0});
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010100
10101 /* ACKnowledge channel activation and expect (RR) Handover Command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010102 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33), idx := {1, 0});
10103 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010104
10105 /* Make sure that L3 Information IE is present */
10106 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
10107 setverdict(fail, "RSL L3 Information IE is absent");
10108 return;
10109 }
10110
10111 /* Decode the L3 message and make sure it is (RR) Handover Command */
10112 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
10113 if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
10114 setverdict(fail, "Failed to match Handover Command: ", l3_msg);
10115 return;
10116 }
10117
10118 /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
10119 var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
10120 if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
10121 setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
10122 return;
10123 }
10124
10125 /* Make sure that hopping parameters (HSN/MAIO) match */
10126 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10127
10128 /* Make sure that Cell Channel Description IE is present */
10129 if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
10130 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
10131 return;
10132 }
10133
10134 /* Make sure that the Mobile Allocation (after time) IE is present and matches */
10135 var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
10136 if (ma_present) {
10137 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10138 l3_msg.payload.ho_cmd.mobile_allocation.v);
10139 } else {
10140 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10141 return;
10142 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010143
10144 f_perform_clear_test_ct(dt);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010145}
10146testcase TC_fh_params_handover_cmd() runs on test_CT {
10147 var FHParamsTrx fhp := f_TC_fh_params_gen();
10148
10149 f_init_vty();
10150
10151 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
10152 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
10153
10154 f_vty_transceive(BSCVTY, "timeslot 0");
10155 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10156 f_vty_transceive(BSCVTY, "exit"); /* go back */
10157
10158 f_vty_transceive(BSCVTY, "timeslot 1");
10159 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
10160 f_vty_transceive(BSCVTY, "end"); /* we're done */
10161
10162 f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
10163 f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
10164
10165 f_init(2);
10166
10167 f_TC_fh_params_handover_cmd(fhp);
10168
10169 /* Disable frequency hopping on BTS1 */
10170 f_TC_fh_params_unset(fhp, 1);
10171
10172 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
10173 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
10174
10175 f_vty_transceive(BSCVTY, "timeslot 0");
10176 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
10177 f_vty_transceive(BSCVTY, "exit"); /* go back */
10178
10179 f_vty_transceive(BSCVTY, "timeslot 1");
10180 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10181 f_vty_transceive(BSCVTY, "end"); /* we're done */
10182
10183 f_shutdown_helper();
10184}
10185
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010186/* Verify the hopping parameters in System Information Type 4 */
10187testcase TC_fh_params_si4_cbch() runs on test_CT {
10188 var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
10189 var ASP_RSL_Unitdata rx_rsl_ud;
10190 timer T := 5.0;
10191
10192 f_init_vty();
10193
10194 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
10195 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10196
10197 f_vty_transceive(BSCVTY, "timeslot 0");
10198 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10199 f_vty_transceive(BSCVTY, "exit"); /* go back */
10200
10201 f_vty_transceive(BSCVTY, "timeslot 1");
10202 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
10203 f_vty_transceive(BSCVTY, "end"); /* we're done */
10204
10205 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
10206 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10207
10208 f_init(1);
10209
10210 T.start;
10211 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010212 [] 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 +070010213 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
10214 var SystemInformation si := dec_SystemInformation(ie.other.payload);
10215
10216 /* Make sure that what we decoded is System Information Type 4 */
10217 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
10218 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
10219 repeat;
10220 }
10221
10222 /* Make sure that CBCH Channel Description IE is present */
10223 if (not ispresent(si.payload.si4.cbch_chan_desc)) {
10224 setverdict(fail, "CBCH Channel Description IE is absent");
10225 break;
10226 }
10227
10228 /* Finally, check the hopping parameters (HSN, MAIO) */
10229 var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
10230 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10231
10232 /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
10233 * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
10234 if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
10235 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10236 break;
10237 } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
10238 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10239 si.payload.si4.cbch_mobile_alloc.v);
10240 }
10241 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010242 [] IPA_RSL[0][0].receive { repeat; }
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010243 [] T.timeout {
10244 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
10245 }
10246 }
10247
10248 /* Disable frequency hopping */
10249 f_TC_fh_params_unset(fhp);
10250
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010251 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010252 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10253
10254 f_vty_transceive(BSCVTY, "timeslot 0");
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010255 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010256 f_vty_transceive(BSCVTY, "exit"); /* go back */
10257
10258 f_vty_transceive(BSCVTY, "timeslot 1");
10259 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10260 f_vty_transceive(BSCVTY, "end"); /* we're done */
10261
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010262 f_shutdown_helper();
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010263}
10264
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010265template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
10266 := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
10267
10268private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
10269 template (present) BSSLAP_PDU expect_bsslap)
10270{
10271 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
10272 if (not match(bsslap, expect_bsslap)) {
10273 log("EXPECTING BSSLAP: ", expect_bsslap);
10274 log("GOT BSSLAP: ", bsslap);
10275 setverdict(fail, "BSSLAP is not as expected");
10276 mtc.stop;
10277 }
10278 setverdict(pass);
10279}
10280
10281/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
10282const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
10283
10284private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
10285 var PDU_BSSAP_LE rx_bsslap;
10286 BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
10287 f_match_bsslap(rx_bsslap, expect_rx_bsslap);
10288}
10289
10290/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10291 * Request on Lb interface. Either with or without the SMLC doing a BSSLAP TA Request. */
10292private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
10293 f_sleep(1.0);
10294
10295 f_establish_fully(omit, omit);
10296 f_bssap_le_register_imsi(g_pars.imsi, omit);
10297
10298 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10299 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10300
10301 var PDU_BSSAP_LE plr;
10302 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10303
10304 if (not do_ta_request) {
10305 /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
10306 var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
10307 if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
10308 log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
10309 log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
10310 setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
10311 mtc.stop;
10312 }
10313 var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
10314 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
10315 if (not match(bsslap, expect_ta_layer3)) {
10316 log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
10317 log("GOT BSSLAP: ", bsslap);
10318 setverdict(fail, "BSSLAP is not as expected");
10319 mtc.stop;
10320 }
10321 /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
10322 * has no need to request the TA from the BSC and directly responds. */
10323 } else {
10324 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10325 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10326 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10327 }
10328
10329 /* SMLC got the TA from the BSC, now responds with geo information data. */
10330 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10331 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10332 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10333
10334 /* The LCS was using an active A-interface conn. It should still remain active after this. */
10335 f_mo_l3_transceive();
10336
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010337 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010338
10339 f_sleep(2.0);
10340 setverdict(pass);
10341}
10342
10343/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10344 * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
10345private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
10346 f_lcs_loc_req_for_active_ms(false);
10347}
10348testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
10349 var MSC_ConnHdlr vc_conn;
10350 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10351
10352 f_init(1, true);
10353 f_sleep(1.0);
10354 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
10355 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010356 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010357}
10358
10359/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10360 * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
10361private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
10362 f_lcs_loc_req_for_active_ms(true);
10363}
10364testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
10365 var MSC_ConnHdlr vc_conn;
10366 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10367
10368 f_init(1, true);
10369 f_sleep(1.0);
10370 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
10371 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010372 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010373}
10374
10375/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
10376 * conn without an active lchan. */
10377private function f_clear_A_conn() runs on MSC_ConnHdlr
10378{
10379 var BssmapCause cause := 0;
10380 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10381 BSSAP.receive(tr_BSSMAP_ClearComplete);
10382 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10383
10384 timer no_more_bssap := 5.0;
10385 no_more_bssap.start;
10386 alt {
10387 [] no_more_bssap.timeout { break; }
10388 [] BSSAP.receive(tr_BSSAP_BSSMAP) {
10389 setverdict(fail, "Expected no more BSSAP after Clear Complete");
10390 mtc.stop;
10391 }
10392 }
10393 setverdict(pass);
10394}
10395
10396/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
10397 * for LCS, for cases where there is only an A conn without an active lchan. */
10398private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
10399{
10400 f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
10401
10402 /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
10403 * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
10404 * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
10405 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10406 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10407 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10408
10409 /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
10410 f_clear_A_conn();
10411 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10412 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10413}
10414
10415/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10416 * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
10417 */
10418private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
10419 f_sleep(1.0);
10420
10421 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10422 f_bssap_le_register_imsi(g_pars.imsi, omit);
10423
10424 /* Register to receive the Paging Command */
10425 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10426 g_chan_nr := new_chan_nr;
10427 f_rslem_register(0, g_chan_nr);
10428
10429 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10430 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10431 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10432 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10433
10434 var PDU_BSSAP_LE plr;
10435 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10436
10437 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10438 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10439
10440 /* OsmoBSC needs to Page */
10441 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
10442 f_logp(BSCVTY, "got Paging Command");
10443
10444 /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
10445 * the MSC, and releases the lchan directly. */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +020010446 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV(g_pars.imsi)), do_clear := false, expect_bssmap_l3 := false);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010447 f_expect_lchan_rel(RSL, RSL_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010448
10449 /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
10450
10451 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10452
10453 /* SMLC got the TA from the BSC, now responds with geo information data. */
10454 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10455 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10456
10457 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10458
10459 /* The lchan is gone, the A-interface conn was created for the LCS only.
10460 * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
10461 f_verify_active_A_conn_and_clear();
10462
10463 f_sleep(2.0);
10464 setverdict(pass);
10465}
10466testcase TC_lcs_loc_req_for_idle_ms() runs on test_CT {
10467 var MSC_ConnHdlr vc_conn;
10468 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10469
10470 f_init(1, true);
10471 f_sleep(1.0);
10472
10473 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10474 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10475
10476 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
10477 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010478 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010479}
10480
10481/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
10482 */
10483private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
10484 f_sleep(1.0);
10485
10486 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10487 f_bssap_le_register_imsi(g_pars.imsi, omit);
10488
10489 /* provoke an abort by omitting both IMSI and IMEI */
10490 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10491 valueof(ts_BSSMAP_Perform_Location_Request(omit,
10492 ts_CellId_CGI('262'H, '42'H, 23, 42)))));
10493 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10494
10495 /* BSC tells MSC about failure */
10496 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10497 locationEstimate := omit, positioningData := omit,
10498 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
10499
10500 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10501 f_verify_active_A_conn_and_clear();
10502
10503 f_sleep(2.0);
10504 setverdict(pass);
10505}
10506testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
10507 var MSC_ConnHdlr vc_conn;
10508 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10509
10510 f_init(1, true);
10511 f_sleep(1.0);
10512
10513 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10514 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10515
10516 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
10517 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010518 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010519}
10520
10521/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10522 * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
10523private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
10524 f_sleep(1.0);
10525
10526 f_establish_fully(omit, omit);
10527 f_bssap_le_register_imsi(g_pars.imsi, omit);
10528
10529 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10530 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10531
10532 var PDU_BSSAP_LE plr;
10533 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10534
10535 if (do_ta) {
10536 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10537 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10538 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10539 }
10540
10541 /* SMLC fails to respond, BSC runs into timeout */
10542 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
10543 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10544
10545 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10546 locationEstimate := omit, positioningData := omit,
10547 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
10548
10549 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10550 f_verify_active_A_conn_and_clear();
10551
10552 f_sleep(2.0);
10553 setverdict(pass);
10554}
10555
10556/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10557 * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
10558private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
10559 f_lcs_loc_req_for_active_ms_le_timeout(false);
10560}
10561
10562testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
10563 var MSC_ConnHdlr vc_conn;
10564 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10565
10566 f_init(1, true);
10567 f_sleep(1.0);
10568 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
10569 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010570 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010571}
10572
10573/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10574 * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
10575private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
10576 f_lcs_loc_req_for_active_ms_le_timeout(true);
10577}
10578
10579testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
10580 var MSC_ConnHdlr vc_conn;
10581 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10582
10583 f_init(1, true);
10584 f_sleep(1.0);
10585 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
10586 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010587 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010588}
10589
10590/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
10591private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
10592 f_sleep(1.0);
10593
10594 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10595 f_bssap_le_register_imsi(g_pars.imsi, omit);
10596
10597 /* Register to receive the Paging Command */
10598 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10599 g_chan_nr := new_chan_nr;
10600 f_rslem_register(0, g_chan_nr);
10601
10602 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10603 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10604 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10605 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10606
10607 var PDU_BSSAP_LE plr;
10608 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10609
10610 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10611 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10612
10613 /* OsmoBSC needs to Page */
10614 var PDU_BSSAP_LE rx_bsslap;
10615 alt {
10616 [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
10617 f_logp(BSCVTY, "got Paging Command");
10618 repeat;
10619 }
10620 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10621 /* MS does not respond to Paging, TA Req runs into timeout. */
10622 f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
10623 }
10624 }
10625
10626 /* SMLC responds with failure */
10627 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10628 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10629
10630 /* BSC tells MSC about failure */
10631 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10632 locationEstimate := omit, positioningData := omit,
10633 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
10634
10635 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10636 f_verify_active_A_conn_and_clear();
10637
10638 f_sleep(2.0);
10639 setverdict(pass);
10640}
10641testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
10642 var MSC_ConnHdlr vc_conn;
10643 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10644
10645 f_init(1, true);
10646 f_sleep(1.0);
10647
10648 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10649 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10650
10651 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
10652 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010653 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010654}
10655
10656/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
10657 * over. */
10658private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10659 f_sleep(1.0);
10660
10661 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10662 f_bssap_le_register_imsi(g_pars.imsi, omit);
10663
10664 /* Register to receive the Paging Command */
10665 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10666 g_chan_nr := new_chan_nr;
10667 f_rslem_register(0, g_chan_nr);
10668
10669 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10670 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10671 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10672 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10673
10674 var PDU_BSSAP_LE plr;
10675 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10676
10677 /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
10678 * and establish Layer 3. It should use the existing A-interface conn. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010679 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 +020010680 do_clear := false, expect_bssmap_l3 := true);
10681
10682 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10683 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10684
10685 /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
10686 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10687
10688 /* SMLC got the TA from the BSC, now responds with geo information data. */
10689 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10690 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10691 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10692
10693 /* The lchan should still exist, it was from a CM Service Request. */
10694 f_mo_l3_transceive();
10695
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010696 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010697
10698 f_sleep(2.0);
10699 setverdict(pass);
10700}
10701testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
10702 var MSC_ConnHdlr vc_conn;
10703 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10704
10705 f_init(1, true);
10706 f_sleep(1.0);
10707
10708 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10709 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10710
10711 vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
10712 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010713 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010714}
10715
10716/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
10717 * the new lchan after handover. */
10718private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10719 f_sleep(1.0);
10720
10721 f_establish_fully(omit, omit);
10722 f_bssap_le_register_imsi(g_pars.imsi, omit);
10723
10724 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10725 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10726
10727 var PDU_BSSAP_LE plr;
10728 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10729
10730 /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
10731 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
10732
10733 var HandoverState hs := {
10734 rr_ho_cmpl_seen := false,
10735 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +020010736 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010737 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010738 };
10739 /* issue hand-over command on VTY */
10740 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
10741 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
10742 f_rslem_suspend(RSL1_PROC);
10743
10744 /* From the MGW perspective, a handover is is characterized by
10745 * performing one MDCX operation with the MGW. So we expect to see
10746 * one more MDCX during handover. */
10747 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
10748
10749 alt {
10750 [] as_handover(hs);
10751 }
10752
10753 var PDU_BSSAP_LE rx_bsslap;
10754
10755 interleave {
10756 /* Expect the BSC to inform the MSC about the handover */
10757 [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
10758
10759 /* Expect the BSC to inform the SMLC about the handover */
10760 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10761 f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
10762 }
10763 }
10764
10765 /* SMLC now responds with geo information data. */
10766 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10767 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10768 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10769
10770 /* lchan still active */
10771 f_mo_l3_transceive(RSL1);
10772
10773 /* MSC decides it is done now. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010774 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010775
10776 f_sleep(2.0);
10777 setverdict(pass);
10778}
10779testcase TC_ho_during_lcs_loc_req() runs on test_CT {
10780 var MSC_ConnHdlr vc_conn;
10781 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10782
10783 f_init(2, true);
10784 f_sleep(1.0);
10785 vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
10786 vc_conn.done;
Oliver Smith39f53072022-10-27 14:44:04 +020010787 f_shutdown_helper(ho := true);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010788}
10789
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010790private function f_tc_emerg_call_and_lcs_loc_req(charstring id) runs on MSC_ConnHdlr
10791{
10792 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
10793 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
10794 * another lchan. */
Pau Espin Pedrol1809bce2023-01-03 16:54:41 +010010795 g_pars.ra := f_rnd_ra_emerg();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010796 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010797 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010798
10799 /* Here would usually be a CC Call Proceeding from the MSC, but what does the BSC care about DTAP. */
10800
10801 /* Do a Location Request in-between the CC call setup */
10802 f_bssap_le_register_imsi(g_pars.imsi, omit);
10803 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10804 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10805 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10806 /* SMLC got the TA from the BSC, now responds with geo information data. */
10807 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10808 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10809 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10810
Pau Espin Pedrol14076d32023-01-03 17:07:59 +010010811 f_assignment_emerg_setup_voice();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010812
10813 setverdict(pass);
10814 f_perform_clear();
10815}
10816
10817testcase TC_emerg_call_and_lcs_loc_req() runs on test_CT {
10818 var MSC_ConnHdlr vc_conn;
10819 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10820
10821 f_init(1, true);
10822 f_sleep(1.0);
10823 f_vty_allow_emerg_msc(true);
10824 f_vty_allow_emerg_bts(true, 0);
10825 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req), pars);
10826 vc_conn.done;
10827 f_shutdown_helper();
10828}
10829
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010830private altstep no_bssmap_clear_req() runs on MSC_ConnHdlr {
10831 [] BSSAP.receive(tr_BSSMAP_ClearRequest) {
10832 setverdict(fail, "unexpected BSSMAP Clear Request");
10833 mtc.stop;
10834 }
10835}
10836
10837private type enumerated RslRel {
10838 RSLREL_REL_IND,
10839 RSLREL_CONN_FAIL
10840};
10841
10842private function f_emerg_call_and_lcs_loc_req_early_lchan_release(RslRel rsl_rel) runs on MSC_ConnHdlr
10843{
10844 g_pars.ra := f_rnd_ra_emerg();
10845 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010846 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010847
10848 /* Start a Location Request to locate the emergency */
10849 f_bssap_le_register_imsi(g_pars.imsi, omit);
10850 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10851 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10852 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10853
10854 /* 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
10855 * do a Clear Command when the Location Response arrives. */
10856 activate(no_bssmap_clear_req());
10857
10858 /* the lchan gets interrupted while the Location Request has no response */
10859 select (rsl_rel) {
10860 case (RSLREL_REL_IND) {
10861 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
10862 f_expect_lchan_rel(RSL, RSL_PROC);
10863 }
10864 case (RSLREL_CONN_FAIL) {
10865 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
10866 }
10867 case else {
10868 setverdict(fail, "Unknown RslRel type");
10869 mtc.stop;
10870 }
10871 }
10872
10873 /* Still expect the Location Response to find its way to the MSC. */
10874 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10875 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10876 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10877
10878 setverdict(pass);
10879
10880 select (rsl_rel) {
10881 case (RSLREL_REL_IND) {
10882 f_perform_clear_no_lchan();
10883 }
10884 case (RSLREL_CONN_FAIL) {
10885 f_perform_clear();
10886 }
10887 }
10888}
10889
10890private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind(charstring id) runs on MSC_ConnHdlr
10891{
10892 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_REL_IND);
10893}
10894
10895testcase TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() runs on test_CT {
10896 var MSC_ConnHdlr vc_conn;
10897 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10898
10899 f_init(1, true);
10900 f_sleep(1.0);
10901 f_vty_allow_emerg_msc(true);
10902 f_vty_allow_emerg_bts(true, 0);
10903 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind), pars);
10904 vc_conn.done;
10905 f_shutdown_helper();
10906}
10907
10908private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail(charstring id) runs on MSC_ConnHdlr
10909{
10910 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_CONN_FAIL);
10911}
10912
10913testcase TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() runs on test_CT {
10914 var MSC_ConnHdlr vc_conn;
10915 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10916
10917 f_init(1, true);
10918 f_sleep(1.0);
10919 f_vty_allow_emerg_msc(true);
10920 f_vty_allow_emerg_bts(true, 0);
10921 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail), pars);
10922 vc_conn.done;
10923 f_shutdown_helper();
10924}
10925
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010926/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
10927private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
10928 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10929
10930 /* Also disable attach for the single connected MSC */
10931 f_vty_msc_allow_attach(BSCVTY, { false });
10932
10933 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) ));
10934 f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
10935
10936 /* No MSC is found, expecting a proper release on RSL */
10937 interleave {
10938 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
10939 f_logp(BSCVTY, "Got RSL RR Release");
10940 }
10941 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10942 f_logp(BSCVTY, "Got RSL Deact SACCH");
10943 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010944 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010945 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
10946 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010947 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010948 }
10949 }
10950 setverdict(pass);
10951}
10952testcase TC_no_msc() runs on test_CT {
10953
10954 f_init(1, true);
10955 f_sleep(1.0);
10956 var MSC_ConnHdlr vc_conn;
10957 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10958
10959 f_ctrs_bsc_init(counternames_bsc_mscpool);
10960
10961 vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
10962 vc_conn.done;
10963
10964 f_ctrs_bsc_add("mscpool:subscr:no_msc");
10965 f_ctrs_bsc_verify();
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010966 f_shutdown_helper();
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010967}
10968
Harald Welte0ea2d5e2018-04-07 21:40:29 +020010969/* Dyn PDCH todo:
10970 * activate OSMO as TCH/F
10971 * activate OSMO as TCH/H
10972 * does the BSC-located PCU socket get the updated INFO?
10973 * what if no PCU is connected at the time?
10974 * is the info correct on delayed PCU (re)connect?
10975 */
Harald Welte94e0c342018-04-07 11:33:23 +020010976
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010977private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +020010978 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020010979 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010980
10981 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
10982 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10983 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
10984 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
10985 g_pars.ass_codec_list.codecElements[0];
10986 if (isvalue(g_pars.expect_mr_s0_s7)) {
10987 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
10988 g_pars.expect_mr_s0_s7;
10989 }
10990 }
10991 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
10992 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
10993 log("expecting ASS COMPL like this: ", exp_compl);
10994
10995 f_establish_fully(ass_cmd, exp_compl);
10996
Neels Hofmeyr8746b0d2021-06-01 17:25:39 +020010997 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 +000010998
10999 var RSL_Message rsl;
11000
11001 timer T := 5.0;
11002 T.start;
11003 alt {
11004 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
11005 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
11006 log("Rx L3 from net: ", l3);
11007 if (ischosen(l3.msgs.rrm.channelModeModify)) {
11008 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
11009 mtc.stop;
11010 }
11011 }
11012 [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
11013 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
11014 mtc.stop;
11015 }
11016 [] T.timeout {
11017 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
11018 setverdict(pass);
11019 }
11020 }
11021 T.stop;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011022
11023 f_perform_clear();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011024}
11025
11026/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
11027 * osmo-bsc. */
11028testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
11029 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11030 var MSC_ConnHdlr vc_conn;
11031
11032 f_init(1, true);
11033 f_sleep(1.0);
11034
11035 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11036 vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
11037 vc_conn.done;
11038 f_shutdown_helper();
11039}
11040
11041/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
11042 */
11043testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
11044 f_init_vty();
11045
11046 f_init(1, false);
11047 f_sleep(1.0);
11048
11049 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
11050
11051 var ASP_RSL_Unitdata rx_rsl_ud;
11052 timer T := 5.0;
11053
11054 T.start;
11055 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011056 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011057 if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
11058 T.stop;
11059 setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
11060 mtc.stop;
11061 }
11062 repeat;
11063 }
11064 [] T.timeout {
11065 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
11066 setverdict(pass);
11067 }
11068 }
11069}
11070
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011071private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
11072 /* First fully set up a speech lchan */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011073 f_assignment_codec(id, do_perform_clear := false);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011074
11075 /* Trigger re-assignment to another lchan */
11076 var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
11077
11078 /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
11079 * one MDCX on MGCP. */
11080 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
11081
11082 /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
11083 * as the old lchan used. */
11084 g_media.bts.ipa_crcx_seen := false;
11085 g_media.bts.ipa_mdcx_seen := false;
11086
11087 /* Send different BTS side RTP port number for the new lchan */
11088 g_media.bts.bts.port_nr := 4223;
11089
11090 f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
11091
11092 /* Trigger re-assignment. */
11093 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
11094
11095 timer T := 5.0;
11096 T.start;
11097 alt {
11098 [] as_assignment(assignment_st);
11099 [] as_Media();
11100 [] T.timeout {
11101 break;
11102 }
11103 }
11104
11105 if (not assignment_st.assignment_done) {
11106 setverdict(fail, "Assignment did not complete");
11107 mtc.stop;
11108 }
11109
11110 f_check_mgcp_expectations()
11111 setverdict(pass);
11112
11113 f_sleep(2.0);
11114 log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
11115
11116 /* Instruct BSC to clear channel */
11117 var BssmapCause cause := 0;
11118 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
11119 interleave {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011120 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
11121 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020011122 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011123 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020011124 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011125 }
11126 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
11127 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11128 }
11129 }
Neels Hofmeyr40a45d12021-09-23 22:57:12 +020011130 f_expect_dlcx_conns();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011131
11132 f_sleep(0.5);
11133}
11134
11135testcase TC_reassignment_fr() runs on test_CT {
11136 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11137 var MSC_ConnHdlr vc_conn;
11138
11139 f_init(1, true);
11140 f_sleep(1.0);
11141
Neels Hofmeyrac432fa2021-11-02 16:45:56 +010011142 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011143
11144 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11145 vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
11146 vc_conn.done;
11147
11148 /* from f_establish_fully() */
11149 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
11150 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
11151 /* from re-assignment */
11152 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
11153 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
11154 f_ctrs_bsc_and_bts_verify();
11155 f_shutdown_helper();
11156}
11157
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011158const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
11159const charstring REEST_CLEAR := "REEST_CLEAR";
11160const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
11161
11162/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
11163 * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
11164 * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
11165 * the MSC as the CM Re-Establishment is handled.
11166 *
11167 * MS bts0 bts1 bsc msc test-component
11168 * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
11169 * | | _1 wait a bit, to settle down
11170 * |<-x x--| | _1 "lose connection"
11171 * | | REEST_LOST_CONNECTION
11172 * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
11173 * | | REEST_CLEAR
11174 * | |<-0---| _1 Clear Command on first A-conn
11175 * | |--0-->| _1 Clear Complete
11176 * | |<----------------->| | _1 Release first channel
11177 * | | REEST_CLEAR_DONE
11178 * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
11179 * |<-----------------|<-------|<-1---| _2 Clear Command, Release
11180 *
11181 */
11182private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
11183 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
11184 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11185
11186 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11187 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11188
11189 f_establish_fully(ass_cmd, exp_compl);
11190
11191 /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
11192 * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
11193 * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
11194 f_sleep(2.0);
11195 COORD.send(REEST_LOST_CONNECTION);
11196
11197 alt {
11198 [] COORD.receive(REEST_CLEAR);
11199 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
11200 setverdict(fail, "Unexpected channel release");
11201 mtc.stop;
11202 }
11203 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
11204 setverdict(fail, "Unexpected channel release");
11205 mtc.stop;
11206 }
11207 }
11208 f_perform_clear()
Neels Hofmeyr969abd02021-09-23 22:24:08 +020011209 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011210 COORD.send(REEST_CLEAR_DONE);
11211}
11212
11213private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
11214 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
11215
11216 /* The MS lost the connection on the first channel, now establishes another one */
11217 COORD.receive(REEST_LOST_CONNECTION);
11218
11219 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
11220 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
11221 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
11222
11223 f_create_bssmap_exp(l3_enc);
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011224 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 +020011225 BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
11226
11227 /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
11228 COORD.send(REEST_CLEAR);
11229 COORD.receive(REEST_CLEAR_DONE);
11230
11231 f_sleep(2.0);
11232
11233 /* Answer the CM Re-Establishment with an Assignment Command. */
11234 var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
11235 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11236 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11237 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11238
11239 var AssignmentState st := valueof(ts_AssignmentStateInit);
Oliver Smithce2dd692023-04-17 10:25:50 +020011240 st.rtp_stream := true;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011241 st.is_assignment := true;
11242
11243 var ExpectCriteria mgcpcrit := {
11244 connid := omit,
11245 endpoint := omit,
11246 transid := omit
11247 };
11248 f_create_mgcp_expect(mgcpcrit);
11249
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011250 f_rslem_dchan_queue_enable(RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011251
11252 BSSAP.send(ass_cmd);
11253
11254 var PDU_BSSAP bssap;
11255
11256 alt {
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011257 [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
11258 [] as_Media_ipacc(RSL1, RSL2);
11259 [] as_Media_mgw();
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011260 [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
11261 break;
11262 }
11263 }
11264
11265 f_sleep(3.0);
11266
11267 f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011268 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011269}
11270
11271testcase TC_cm_reestablishment() runs on test_CT {
11272 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
11273 var MSC_ConnHdlr vc_conn1;
11274
11275 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
11276 var MSC_ConnHdlr vc_conn2;
11277 pars2.imsi := pars1.imsi;
11278 pars2.media_nr := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011279 pars2.expect_tsc := c_BtsParams[1].tsc;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011280
11281 f_init(2, true, guard_timeout := 40.0);
11282 f_sleep(1.0);
11283
11284 vc_conn1 := f_start_handler_create(pars1);
11285 vc_conn2 := f_start_handler_create(pars2);
11286 connect(vc_conn1:COORD, vc_conn2:COORD);
11287 f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
11288 f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
11289 vc_conn1.done;
11290 vc_conn2.done;
11291
11292 f_shutdown_helper();
11293}
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011294
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011295function f_exp_ipa_rx_nonfatal(template (present) RSL_Message t_rx,
11296 boolean ignore_other_rx := true,
11297 BtsTrxIdx idx := {0, 0},
11298 float Tval := 2.0)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011299runs on test_CT return template (omit) RSL_Message {
11300 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011301 timer T := Tval;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011302
11303 T.start;
11304 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011305 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011306 T.stop;
11307 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011308 [ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
11309 [not ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011310 log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
11311 T.stop;
11312 return omit;
11313 }
11314 [] T.timeout {
11315 return omit;
11316 }
11317 }
11318 return rx_rsl_ud.rsl;
11319}
11320
11321private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
11322 f_vty_enter_cfg_bts(pt, bts_nr);
11323 f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
11324 f_vty_transceive(pt, "exit");
11325 f_vty_transceive(pt, "exit");
11326 f_vty_transceive(pt, "exit");
11327}
11328
11329private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +030011330 template (present) RslChannelNr chan_nr := ?,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011331 template (present) uint12_t arfcn := ?,
11332 template (present) uint3_t tsc := ?)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011333{
11334 var RSL_IE_Body full_imm_ass_info;
11335 if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
11336 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
11337 mtc.stop;
11338 }
11339
11340 var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
11341 var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
11342 fn := fn,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011343 ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011344 page_mode := ?);
11345 if (not match(rr_imm_ass, expect_imm_ass)) {
11346 log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
11347 setverdict(fail, "Failed to match Immediate Assignment");
11348 mtc.stop;
11349 }
11350}
11351
11352testcase TC_imm_ass_post_chan_ack() runs on test_CT {
11353 var RSL_Message chan_act;
11354 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011355 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011356
11357 f_init(1, false);
11358 f_sleep(1.0);
11359
11360 /* (should be the default anyway, just to make things clear) */
11361 f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
11362
11363 /* RA containing reason=LU */
11364 var GsmFrameNumber fn := 2342;
11365 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011366 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011367
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011368 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011369
11370 /* First send the Chan Act ACK */
11371 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011372 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011373 var RSL_IE_Body chan_ident_ie;
11374 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11375 setverdict(fail, "RSL Channel Identification IE is absent");
11376 mtc.stop;
11377 }
11378
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011379 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011380
11381 /* Then expect the Immediate Assignment, after we ACKed the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011382 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011383
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011384 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11385 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011386
11387 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011388 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011389
11390 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011391 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011392 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011393 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11394
11395 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011396 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011397 f_shutdown_helper();
11398}
11399
11400testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
11401 var RSL_Message chan_act;
11402 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011403 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011404
11405 f_init(1, false);
11406 f_sleep(1.0);
11407
11408 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11409
11410 /* RA containing reason=LU */
11411 var GsmFrameNumber fn := 2342;
11412 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011413 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011414
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011415 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011416 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011417 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011418 var RSL_IE_Body chan_ident_ie;
11419 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11420 setverdict(fail, "RSL Channel Identification IE is absent");
11421 mtc.stop;
11422 }
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011423
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011424 /* (set bts 0 cfg back to default) */
11425 f_vty_set_imm_ass(BSCVTY);
11426
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011427 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011428 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011429 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11430 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011431
11432 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011433 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +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 Hofmeyrb07b2952021-08-07 04:23:14 +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 Hofmeyrb07b2952021-08-07 04:23:14 +020011441 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11442
11443 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011444 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011445 f_shutdown_helper();
11446}
11447
Neels Hofmeyr23158742021-09-07 19:08:07 +020011448testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
11449 var RSL_Message chan_act;
11450 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011451 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr23158742021-09-07 19:08:07 +020011452
11453 f_init(1, false);
11454 f_sleep(1.0);
11455
11456 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11457
11458 /* RA containing reason=LU */
11459 var GsmFrameNumber fn := 2342;
11460 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011461 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011462
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011463 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011464 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011465 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr23158742021-09-07 19:08:07 +020011466 var RSL_IE_Body chan_ident_ie;
11467 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11468 setverdict(fail, "RSL Channel Identification IE is absent");
11469 mtc.stop;
11470 }
11471
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011472 /* (set bts 0 cfg back to default) */
11473 f_vty_set_imm_ass(BSCVTY);
11474
Neels Hofmeyr23158742021-09-07 19:08:07 +020011475 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011476 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011477 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11478 chan_ident_ie.chan_ident.ch_desc.v.tsc);
11479
11480 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011481 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011482
11483 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011484 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011485
11486 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011487 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011488 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr23158742021-09-07 19:08:07 +020011489 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11490
11491 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011492 f_perform_clear_test_ct(dt);
Neels Hofmeyr23158742021-09-07 19:08:07 +020011493 f_shutdown_helper();
11494}
11495
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011496testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
11497 /* change Timeslot 6 before f_init() starts RSL */
11498 f_init_vty();
11499 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11500 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11501
11502 f_init(1, false);
11503 f_sleep(1.0);
11504
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011505 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011506 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11507 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011508 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11509 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011510
11511 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11512 f_ts_set_chcomb(0, 0, 6, "PDCH");
11513
11514 /* block all static timeslots so that the dyn TS will be used */
11515 f_disable_all_tch_f();
11516 f_disable_all_tch_h();
11517 f_disable_all_sdcch();
11518
11519 var RSL_Message chan_act;
11520 var RSL_Message imm_ass;
11521
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011522 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11523
11524 /* RA containing reason=LU */
11525 var GsmFrameNumber fn := 2342;
11526 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011527 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011528
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011529 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011530 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
11531 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011532
11533 /* Now activation as SDCCH8 */
11534 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011535 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011536
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011537 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011538 var RSL_IE_Body chan_ident_ie;
11539 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11540 setverdict(fail, "RSL Channel Identification IE is absent");
11541 mtc.stop;
11542 }
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011543
11544 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011545 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011546 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11547 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011548
11549 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011550 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011551
11552 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011553 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011554
11555 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011556 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011557 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011558 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11559
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011560 /* (set bts 0 cfg back to default) */
11561 f_vty_set_imm_ass(BSCVTY);
11562
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011563 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011564 f_perform_clear_test_ct(dt);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011565 f_shutdown_helper();
11566}
11567
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011568testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
11569 /* change Timeslot 6 before f_init() starts RSL */
11570 f_init_vty();
11571 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11572 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11573
11574 f_init(1, false);
11575 f_sleep(1.0);
11576
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011577 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011578 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11579 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011580 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11581 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011582
11583 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11584 f_ts_set_chcomb(0, 0, 6, "PDCH");
11585
11586 /* block all static timeslots so that the dyn TS will be used */
11587 f_disable_all_tch_f();
11588 f_disable_all_tch_h();
11589 f_disable_all_sdcch();
11590
11591 var RSL_Message chan_act;
11592 var RSL_Message imm_ass;
11593
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011594 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11595
11596 /* RA containing reason=LU */
11597 var GsmFrameNumber fn := 2342;
11598 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011599 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011600
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011601 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011602 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011603
11604 /* And already the Immediate Assignment even before the PDCH Deact ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011605 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011606
11607 /* continue the Osmo style PDCH Deact (usual chan rel) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011608 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011609
11610 /* Now activation as SDCCH8 */
11611 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011612 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011613
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011614 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011615 var RSL_IE_Body chan_ident_ie;
11616 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11617 setverdict(fail, "RSL Channel Identification IE is absent");
11618 mtc.stop;
11619 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011620 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011621
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011622 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11623 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011624
11625 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011626 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011627
11628 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011629 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011630 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011631 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11632
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011633 /* (set bts 0 cfg back to default) */
11634 f_vty_set_imm_ass(BSCVTY);
11635
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011636 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011637 f_perform_clear_test_ct(dt);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011638 f_shutdown_helper();
11639}
11640
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011641/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
11642testcase TC_ctrl_trx_rf_locked() runs on test_CT {
11643 var MSC_ConnHdlr vc_conn;
11644
11645 f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
11646 f_sleep(1.0);
11647
11648 /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
11649 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11650 "0,0,operational,unlocked,on,rsl-up;" &
11651 "1,0,operational,unlocked,on,rsl-up;" &
11652 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011653 "2,1,operational,unlocked,on,rsl-down;" &
11654 "2,2,operational,unlocked,on,rsl-down;" &
11655 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011656 "3,0,inoperational,locked,on,rsl-down;");
11657
11658 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock BTS 1 TRX 0");
11659 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11660 /* give it a moment to settle the FSM status */
11661 f_sleep(1.0);
11662
11663 /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
11664 * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
11665 * of "off"? But that's for a future patch if at all. */
11666 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11667 "0,0,operational,unlocked,on,rsl-up;" &
11668 "1,0,operational,locked,on,rsl-up;" &
11669 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011670 "2,1,operational,unlocked,on,rsl-down;" &
11671 "2,2,operational,unlocked,on,rsl-down;" &
11672 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011673 "3,0,inoperational,locked,on,rsl-down;");
11674
11675 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
11676 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11677 f_sleep(1.0);
11678 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11679 "0,0,operational,unlocked,on,rsl-up;" &
11680 "1,0,operational,locked,on,rsl-up;" &
11681 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011682 "2,1,operational,unlocked,on,rsl-down;" &
11683 "2,2,operational,unlocked,on,rsl-down;" &
11684 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011685 "3,0,inoperational,locked,on,rsl-down;");
11686
11687 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
11688 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
11689 f_sleep(1.0);
11690 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11691 "0,0,operational,unlocked,on,rsl-up;" &
11692 "1,0,operational,unlocked,on,rsl-up;" &
11693 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011694 "2,1,operational,unlocked,on,rsl-down;" &
11695 "2,2,operational,unlocked,on,rsl-down;" &
11696 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011697 "3,0,inoperational,locked,on,rsl-down;");
11698
11699 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
11700 f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
11701 f_sleep(1.0);
11702 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11703 "0,0,operational,unlocked,on,rsl-up;" &
11704 "1,0,operational,unlocked,on,rsl-up;" &
11705 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011706 "2,1,operational,unlocked,on,rsl-down;" &
11707 "2,2,operational,unlocked,on,rsl-down;" &
11708 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011709 "3,0,inoperational,locked,on,rsl-down;");
11710
11711 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
11712 f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
11713 f_sleep(1.0);
11714 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11715 "0,0,operational,unlocked,on,rsl-up;" &
11716 "1,0,operational,unlocked,on,rsl-up;" &
11717 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011718 "2,1,operational,unlocked,on,rsl-down;" &
11719 "2,2,operational,unlocked,on,rsl-down;" &
11720 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011721 "3,0,inoperational,locked,on,rsl-down;");
11722
11723 f_shutdown_helper();
11724}
11725
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011726const CounterNameVals counternames_cm_serv_rej := {
11727 { "cm_serv_rej", 0 },
11728 { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
11729 { "cm_serv_rej:illegal_ms", 0 },
11730 { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
11731 { "cm_serv_rej:imei_not_accepted", 0 },
11732 { "cm_serv_rej:illegal_me", 0 },
11733 { "cm_serv_rej:plmn_not_allowed", 0 },
11734 { "cm_serv_rej:loc_not_allowed", 0 },
11735 { "cm_serv_rej:roaming_not_allowed", 0 },
11736 { "cm_serv_rej:network_failure", 0 },
11737 { "cm_serv_rej:synch_failure", 0 },
11738 { "cm_serv_rej:congestion", 0 },
11739 { "cm_serv_rej:srv_opt_not_supported", 0 },
11740 { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
11741 { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
11742 { "cm_serv_rej:call_can_not_be_identified", 0 },
11743 { "cm_serv_rej:incorrect_message", 0 },
11744 { "cm_serv_rej:invalid_mandantory_inf", 0 },
11745 { "cm_serv_rej:msg_type_not_implemented", 0 },
11746 { "cm_serv_rej:msg_type_not_compatible", 0 },
11747 { "cm_serv_rej:inf_eleme_not_implemented", 0 },
11748 { "cm_serv_rej:condtional_ie_error", 0 },
11749 { "cm_serv_rej:msg_not_compatible", 0 },
11750 { "cm_serv_rej:protocol_error", 0 },
11751 { "cm_serv_rej:retry_in_new_cell", 0 }
11752};
11753
11754private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
11755{
11756 f_create_chan_and_exp();
Vadim Yanitskiya7fc5a62021-12-04 20:10:08 +030011757 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011758 BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011759 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_CM_SERV_REJ));
11760 f_perform_clear();
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011761 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011762}
11763testcase TC_cm_serv_rej() runs on test_CT {
11764 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11765 var MSC_ConnHdlr vc_conn;
11766
11767 f_init(1, true);
11768 f_sleep(1.0);
11769
11770 f_ctrs_bts_init(1, counternames_cm_serv_rej);
11771
11772 vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
11773 vc_conn.done;
11774
11775 f_ctrs_bts_add(0, "cm_serv_rej", 1);
11776 f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
11777 f_ctrs_bts_verify();
11778
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011779 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011780 f_shutdown_helper();
11781}
11782
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011783/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
11784 * Activ Ack (SYS#5627). */
11785private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
11786 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Vadim Yanitskiyf0310e32021-10-26 00:30:59 +030011787
11788 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11789 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011790
11791 var BSSMAP_FIELD_CodecType codecType;
11792 codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
11793
11794 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
11795
11796 /* First establish a signalling lchan */
11797 f_create_chan_and_exp();
11798 f_rslem_dchan_queue_enable();
11799
11800 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011801
11802 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
Oliver Smith735b47c2023-02-15 16:03:54 +010011803 activate(as_Media_mgw());
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011804
11805 var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
11806 f_rslem_register(0, chan_nr);
11807
11808 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
11809 BSSAP.send(ass_cmd);
11810
11811
11812 /* Wait for the Channel Activ for the TCH channel */
11813 var ASP_RSL_Unitdata rx_rsl_ud;
11814 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
11815
11816 /* make the original SDCCH disappear */
11817 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
11818
11819 /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
11820 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
11821
11822 interleave {
11823 [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
11824 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
11825 }
11826
11827 BSSAP.send(ts_BSSMAP_ClearCommand(0));
11828 BSSAP.receive(tr_BSSMAP_ClearComplete);
11829 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11830
11831 var MgcpCommand mgcp;
Vadim Yanitskiy6be4cf42022-06-04 21:25:47 +060011832 var MGCP_RecvFrom mrf;
11833 var template MgcpMessage msg_dlcx := { command := tr_DLCX };
11834 alt {
11835 [g_pars.aoip] MGCP.receive(tr_DLCX) -> value mgcp {
11836 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
11837 }
11838 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
11839 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
11840 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
11841 }));
11842 }
11843 }
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011844
11845 f_sleep(0.5);
11846}
11847testcase TC_lost_sdcch_during_assignment() runs on test_CT {
11848 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11849 var MSC_ConnHdlr vc_conn;
11850
Oliver Smith735b47c2023-02-15 16:03:54 +010011851 pars.fail_on_dlcx := false;
11852
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011853 f_init(1, true);
11854 f_sleep(1.0);
11855
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011856 vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
11857 vc_conn.done;
11858
11859 f_shutdown_helper();
11860}
11861
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011862const CounterNameVals counternames_bsc_bts_all_available_allocated := {
11863 { "all_allocated:sdcch", 0 },
11864 { "all_allocated:static_sdcch", 0 },
11865 { "all_allocated:tch", 0 },
11866 { "all_allocated:static_tch", 0 }
11867}
11868
11869private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
11870{
11871 /* Make sure counters settle first */
11872 f_sleep(1.0);
11873
11874 /* Take a baseline of counters */
11875 f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
11876
11877 /* Elapse some time so that we see changes in counters, hopefully where expected */
11878 f_sleep(2.0);
11879
11880 /* Get new counters */
11881 var charstring_list all_changed := {};
11882 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
11883 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
11884
11885 /* Compare with expectations */
11886 var charstring_list all_expect_changed := {};
11887 for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
11888 all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
11889 }
11890 f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
11891}
11892
11893testcase TC_ratectr_all_available_allocated() runs on test_CT {
11894 var ASP_RSL_Unitdata rsl_ud;
11895 var integer i;
11896 var integer chreq_total, chreq_nochan;
11897
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011898 f_init(1, guard_timeout := 60.0);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011899 f_sleep(1.0);
11900
11901 /* Exhaust all dedicated SDCCH lchans.
11902 /* GSM 44.018 Table 9.1.8.2:
11903 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11904 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011905 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011906 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011907 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 +020011908 }
11909
11910 /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
11911 * level.
11912 * All SDCCH are now occupied. */
11913 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11914
11915 /* Also fill up all remaining (TCH) channels */
11916 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011917 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 +020011918 }
11919
11920 /* All TCH are now also occupied */
11921 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11922 "all_allocated:tch", "all_allocated:static_tch"});
11923
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011924 /* Clean up SDCCH lchans */
11925 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11926 f_perform_clear_test_ct(chan_cleanup[i]);
11927 }
11928
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011929 f_shutdown_helper();
11930}
11931
11932testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
11933 var ASP_RSL_Unitdata rsl_ud;
11934 var integer i;
11935 var integer chreq_total, chreq_nochan;
11936
11937 f_init_vty();
11938 f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
11939 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11940 /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
11941
11942 f_init(1, guard_timeout := 60.0);
11943 f_sleep(1.0);
11944
11945 /* The dyn TS wants to activate PDCH mode, ACK that. */
11946 var RslChannelNr chan_nr;
11947 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011948 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11949 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011950
11951 /* Exhaust all dedicated SDCCH lchans.
11952 /* GSM 44.018 Table 9.1.8.2:
11953 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11954 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011955 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011956 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011957 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 +020011958 }
11959
11960 /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
11961 * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
11962 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
11963
11964 /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
11965 * Will release them later, so remember all the DchanTuples. */
11966 var DchanTuples dyn_sddch := {};
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011967 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 +020011968
11969 /* Also occupy the seven other SDCCH of the dyn TS */
11970 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011971 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 +020011972 }
11973
11974 /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
11975 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11976
11977 /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
11978 for (i := 0; i < 5; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011979 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 +020011980 }
11981
11982 /* All TCH lchans are now also occupied, both static and dynamic */
11983 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11984 "all_allocated:tch", "all_allocated:static_tch"});
11985
11986 /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
11987 * incrementing. */
11988 var BssmapCause cause := 0;
11989 var DchanTuple dt := dyn_sddch[0];
11990 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011991 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011992
11993 /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
11994 * count as occupied, so those still both increment. */
11995 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
11996 "all_allocated:tch", "all_allocated:static_tch"});
11997
11998 /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
11999 for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
12000 dt := dyn_sddch[i];
12001 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060012002 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012003 }
12004
12005 /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
12006 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060012007 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
12008 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012009
12010 /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
12011 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
12012
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010012013 /* Clean up SDCCH lchans */
12014 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
12015 f_perform_clear_test_ct(chan_cleanup[i]);
12016 }
12017
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012018 /* clean up config */
12019 f_ts_reset_chcomb(0);
12020
12021 f_shutdown_helper();
12022}
12023
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012024private function f_TC_chan_alloc_algo(DchanTuple dt, BtsTrxIdx idx)
12025runs on test_CT {
12026 /* MSC sends an Assignment Request */
12027 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12028 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12029 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12030 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
12031
12032 /* Expect the BSC to allocate a TCH channel on the given BTS/TRX */
12033 var RSL_Message rsl_chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
12034 /* Send CHAN ACT NACK, so that the requested TCH channel becomes BORKEN */
12035 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(rsl_chan_act.ies[0].body.chan_nr, RSL_ERR_EQUIPMENT_FAIL), idx);
12036 /* Expect to receive an Assignment Failure */
12037 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail));
12038}
12039
12040testcase TC_chan_alloc_algo_ascending() runs on test_CT {
12041 /* We need to access BTS2, which has 4 TRXs */
12042 f_init(nr_bts := 3);
12043
12044 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012045 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012046
12047 f_vty_enter_cfg_bts(BSCVTY, 2);
12048 f_vty_transceive(BSCVTY, "channel allocator ascending");
12049 f_vty_transceive(BSCVTY, "end");
12050
12051 /* Expect the BSC to allocate 4 x TCH/F channels on BTS2/TRX0 */
12052 for (var integer i := 0; i < 4; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012053 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012054 f_TC_chan_alloc_algo(dt, {2, 0});
12055 f_perform_clear_test_ct(dt);
12056 }
12057
12058 /* At this point all 4 x TCH/F channels are BORKEN, but they will be
12059 * resurrected upon the A-bis/OML link re-establishment. */
12060 f_shutdown_helper();
12061}
12062
12063testcase TC_chan_alloc_algo_descending() runs on test_CT {
12064 /* We need to access BTS2, which has 4 TRXs */
12065 f_init(nr_bts := 3);
12066
12067 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012068 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012069
12070 f_vty_enter_cfg_bts(BSCVTY, 2);
12071 f_vty_transceive(BSCVTY, "channel allocator descending");
12072 f_vty_transceive(BSCVTY, "end");
12073
12074 /* Expect the BSC to allocate 5 x TCH/F channels on BTS2/TRX3 */
12075 for (var integer i := 0; i < 5; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012076 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012077 f_TC_chan_alloc_algo(dt, {2, 3});
12078 f_perform_clear_test_ct(dt);
12079 }
12080
12081 /* At this point all 5 x TCH/F channels are BORKEN, but they will be
12082 * resurrected upon the A-bis/OML link re-establishment. */
12083 f_shutdown_helper();
12084}
12085
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012086testcase TC_chan_alloc_algo_ass_dynamic() runs on test_CT {
12087 const BtsTrxIdx TRX0 := {2, 0};
12088 const BtsTrxIdx TRX3 := {2, 3};
12089
12090 /* We need to access BTS2, which has 4 TRXs */
12091 f_init(nr_bts := 3);
12092
12093 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012094 vc_MGCP[0].stop;
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012095
12096 f_vty_enter_cfg_bts(BSCVTY, 2);
12097 f_vty_transceive(BSCVTY, "channel allocator mode assignment dynamic");
12098 f_vty_transceive(BSCVTY, "channel allocator dynamic-param ul-rxlev thresh 50 avg-num 2");
12099 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 0");
12100 f_vty_transceive(BSCVTY, "end");
12101
12102 var DchanTuple dt;
12103
12104 f_logp(BSCVTY, "Case a) Unknown Uplink RxLev, fall-back to ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012105 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012106 f_TC_chan_alloc_algo(dt, TRX0);
12107 f_perform_clear_test_ct(dt);
12108
12109 f_logp(BSCVTY, "Case b) Not enough RxLev samples, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012110 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012111 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12112 ts_RSL_IE_UplinkMeas(30, 0),
12113 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012114 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012115 f_TC_chan_alloc_algo(dt, TRX0);
12116 f_perform_clear_test_ct(dt);
12117
12118 f_logp(BSCVTY, "Case c) Uplink RxLev below the threshold, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012119 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012120 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12121 ts_RSL_IE_UplinkMeas(45, 0),
12122 ts_RSL_IE_BS_Power(0)), TRX0);
12123 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12124 ts_RSL_IE_UplinkMeas(48, 0),
12125 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012126 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012127 f_TC_chan_alloc_algo(dt, TRX0);
12128 f_perform_clear_test_ct(dt);
12129
12130 f_logp(BSCVTY, "Case d) Uplink RxLev above the threshold, use descending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012131 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012132 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12133 ts_RSL_IE_UplinkMeas(50, 0),
12134 ts_RSL_IE_BS_Power(0)), TRX0);
12135 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12136 ts_RSL_IE_UplinkMeas(58, 0),
12137 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012138 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012139 f_TC_chan_alloc_algo(dt, TRX3);
12140 f_perform_clear_test_ct(dt);
12141
12142 f_vty_enter_cfg_bts(BSCVTY, 2);
12143 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 90");
12144 f_vty_transceive(BSCVTY, "end");
12145
12146 f_logp(BSCVTY, "Case e) Uplink RxLev above the threshold, but C0 load is not");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012147 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012148 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12149 ts_RSL_IE_UplinkMeas(50, 0),
12150 ts_RSL_IE_BS_Power(0)), TRX0);
12151 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12152 ts_RSL_IE_UplinkMeas(58, 0),
12153 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012154 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012155 f_TC_chan_alloc_algo(dt, TRX0);
12156 f_perform_clear_test_ct(dt);
12157
12158 f_vty_enter_cfg_bts(BSCVTY, 2);
12159 f_vty_transceive(BSCVTY, "channel allocator ascending");
12160 f_vty_transceive(BSCVTY, "end");
12161
12162 /* At this point some TCH/F channels are BORKEN, but they will be
12163 * resurrected upon the A-bis/OML link re-establishment. */
12164 f_shutdown_helper();
12165}
12166
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012167private function f_vty_mgw_enable(integer mgw_nr := 1) runs on test_CT {
12168 var rof_charstring cmds := {
12169 "remote-ip " & mp_test_ip,
12170 "remote-port " & int2str(2427 + mgw_nr)
12171 };
12172 f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
12173 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " reconnect")
12174}
12175private function f_vty_mgw_disable(integer mgw_nr := 1) runs on test_CT {
12176 f_vty_config3(BSCVTY, {"network"}, { "no mgw " &int2str(mgw_nr) });
12177}
12178private function f_vty_mgw_block(integer mgw_nr := 1, boolean blocked := true) runs on test_CT {
12179 var charstring arg;
12180 if (blocked) {
12181 arg := "block";
12182 } else {
12183 arg := "unblock";
12184 }
12185 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " " & arg);
12186}
Pau Espin Pedrolbd598422023-06-15 17:29:09 +020012187private function f_vty_mgw_cfg_keepalive(integer mgw_nr := 1, integer req_intval := 0, charstring req_endp := "null", integer rx_timeout := 0) runs on test_CT {
12188 var charstring arg;
12189 var rof_charstring cmds := {
12190 "keepalive request-interval " & int2str(req_intval),
12191 "keepalive request-endpoint " & req_endp,
12192 "keepalive timeout " & int2str(rx_timeout)
12193 };
12194 f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
12195}
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012196private const charstring COORD_CMD_ESTABLISHED := "COORD_CMD_ESTABLISHED";
12197private function f_TC_mgwpool_call_seq_1(charstring id) runs on MSC_ConnHdlr {
12198 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Pau Espin Pedrolb522e1c2023-09-28 13:38:50 +020012199 var PDU_BSSAP ass_cmd := f_gen_ass_req(ass_cid := 0);
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012200 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12201 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12202
12203 f_establish_fully(ass_cmd, exp_compl);
12204 COORD.send(COORD_CMD_ESTABLISHED);
12205
12206 COORD.receive(COORD_CMD_ESTABLISHED);
12207 f_perform_clear()
12208 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12209}
12210private function f_TC_mgwpool_call_seq_2(charstring id) runs on MSC_ConnHdlr {
12211 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Pau Espin Pedrolb522e1c2023-09-28 13:38:50 +020012212 var PDU_BSSAP ass_cmd := f_gen_ass_req(ass_cid := 1);
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012213 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12214 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12215
12216
12217 COORD.receive(COORD_CMD_ESTABLISHED);
12218 f_establish_fully(ass_cmd, exp_compl);
12219 COORD.send(COORD_CMD_ESTABLISHED);
12220
12221 f_perform_clear()
12222 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12223}
12224/* Test load is spread around 2 available MGWs */
12225testcase TC_mgwpool_all_used() runs on test_CT {
12226 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12227 var MSC_ConnHdlr vc_conn1;
12228 pars1.mgwpool_idx := 0;
12229
12230 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12231 var MSC_ConnHdlr vc_conn2;
12232 pars2.mgwpool_idx := 1;
Pau Espin Pedrol577688b2023-09-28 14:51:42 +020012233 pars2.media_nr := 2;
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012234
12235 f_init(1, true, nr_mgw := 2);
12236 f_sleep(1.0);
12237
12238 f_vty_mgw_enable(1);
12239
12240 vc_conn1 := f_start_handler_create(pars1);
12241 vc_conn2 := f_start_handler_create(pars2);
12242 connect(vc_conn1:COORD, vc_conn2:COORD);
12243 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12244 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12245 vc_conn1.done;
12246 vc_conn2.done;
12247
12248 f_vty_mgw_disable(1);
12249
12250 f_shutdown_helper();
12251}
12252
12253/* Test blocked MGW in the pool are not selected */
12254testcase TC_mgwpool_blocked_not_used() runs on test_CT {
12255 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12256 var MSC_ConnHdlr vc_conn1;
12257 pars1.mgwpool_idx := 0;
12258
12259 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12260 var MSC_ConnHdlr vc_conn2;
12261 pars2.mgwpool_idx := 0; /* expect it in the first one, since the second will be blocked */
12262 pars2.media_nr := 2;
12263
12264 f_init(1, true, nr_mgw := 2);
12265 f_sleep(1.0);
12266
12267 f_vty_mgw_enable(1);
12268 f_vty_mgw_block(1, true);
12269
12270 vc_conn1 := f_start_handler_create(pars1);
12271 vc_conn2 := f_start_handler_create(pars2);
12272 connect(vc_conn1:COORD, vc_conn2:COORD);
12273 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12274 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12275 vc_conn1.done;
12276 vc_conn2.done;
12277
12278 f_vty_mgw_disable(1);
12279
12280 f_shutdown_helper();
12281}
12282
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012283/* Test BTS pinning to an MGW is applied */
12284testcase TC_mgwpool_pin_bts() runs on test_CT {
12285 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12286 var MSC_ConnHdlr vc_conn1;
12287 pars1.mgwpool_idx := 0;
12288
12289 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12290 var MSC_ConnHdlr vc_conn2;
12291 pars2.mgwpool_idx := 0; /* expect it in the first one, since the BTS is pinned to the first MGW */
12292 pars2.media_nr := 2;
12293
12294 f_init(1, true, nr_mgw := 2);
12295 f_sleep(1.0);
12296
12297 f_vty_mgw_enable(1);
12298 f_vty_cfg_bts(BSCVTY, 0, { "mgw pool-target 0" });
12299
12300 vc_conn1 := f_start_handler_create(pars1);
12301 vc_conn2 := f_start_handler_create(pars2);
12302 connect(vc_conn1:COORD, vc_conn2:COORD);
12303 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12304 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12305 vc_conn1.done;
12306 vc_conn2.done;
12307
12308 f_vty_cfg_bts(BSCVTY, 0, { "no mgw pool-target" } );
Vadim Yanitskiy389d7e02022-10-25 17:44:05 +070012309 f_vty_mgw_disable(1);
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012310
12311 f_shutdown_helper();
12312}
12313
Pau Espin Pedrolbd598422023-06-15 17:29:09 +020012314/* Test keepalive procedure on the MGW */
12315private function f_TC_mgwpool_keepalive_mgw0(charstring id) runs on MSC_ConnHdlr {
12316 /* Make sure the MGW is considered DOWN by the keepalive. See "timeout"
12317 * param in TC_mgwpool_keepalive. */
12318 f_sleep(3.0);
12319
12320 COORD.send(COORD_CMD_ESTABLISHED);
12321
12322 /* Wait for signal that call was established successfully over the other MSC/MGW: */
12323 COORD.receive(COORD_CMD_ESTABLISHED);
12324}
12325private function f_TC_mgwpool_keepalive_mgw1(charstring id) runs on MSC_ConnHdlr {
12326 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12327 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12328 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12329 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12330
12331 /* Wait for other MSC/MGW component to tell us the timeout is done and
12332 * we can start the call, which will be assigned to use because the other
12333 * MGW will be seen as DOWN. */
12334 COORD.receive(COORD_CMD_ESTABLISHED);
12335 f_establish_fully(ass_cmd, exp_compl);
12336 /* signal that call was established successfully over the other MSC/MGW: */
12337 COORD.send(COORD_CMD_ESTABLISHED);
12338
12339 f_perform_clear()
12340 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12341}
12342testcase TC_mgwpool_keepalive_down_not_used() runs on test_CT {
12343 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12344 var MSC_ConnHdlr vc_conn1;
12345 pars1.mgwpool_idx := 0;
12346
12347 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12348 var MSC_ConnHdlr vc_conn2;
12349 pars2.mgwpool_idx := 1; /* expect it in the second one, since the first will be considered DOWN */
12350 pars2.media_nr := 2;
12351
12352 f_init(1, true, nr_mgw := 2);
12353 f_sleep(1.0);
12354
Vadim Yanitskiycf25a3a2023-06-20 17:27:18 +070012355 f_vty_mgw_cfg_keepalive(0, req_intval := 1, req_endp := "null", rx_timeout := 3);
Pau Espin Pedrolbd598422023-06-15 17:29:09 +020012356 f_vty_mgw_enable(1);
12357 f_vty_mgw_block(1, false);
Pau Espin Pedrolbd598422023-06-15 17:29:09 +020012358
12359 vc_conn1 := f_start_handler_create(pars1);
12360 vc_conn2 := f_start_handler_create(pars2);
12361 connect(vc_conn1:COORD, vc_conn2:COORD);
12362 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_keepalive_mgw0), pars1);
12363 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_keepalive_mgw1), pars2);
12364 vc_conn1.done;
12365 vc_conn2.done;
12366
12367 f_vty_mgw_disable(1);
12368 /* disable keepalive (default status): */
12369 f_vty_mgw_cfg_keepalive(0, req_intval := 0, req_endp := "null", rx_timeout := 0);
12370
12371 f_shutdown_helper();
12372}
12373
Oliver Smithc9a5f532022-10-21 11:32:23 +020012374private function f_tc_ho_meas_rep_multi_band(charstring id) runs on MSC_ConnHdlr {
12375 g_pars := f_gen_test_hdlr_pars();
12376 var PDU_BSSAP ass_req := f_gen_ass_req();
12377 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12378 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12379 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12380 f_establish_fully(ass_req, exp_compl);
12381
12382 /* Send a measurement report with bad rxlev except on 3rd entry. The
12383 * measurement report is divided into two sub lists, as described in
12384 * 3GPP TS 04.08 § 10.5.2.20. */
12385 var NcellReports neighbor_rep := {
12386 /* Sub list 1: same band */
Oliver Smitha6773042022-10-24 12:56:30 +020012387 { rxlev := 0, bcch_freq := 0, bsic := 12 }, /* ARFCN 800, band 1800, LAC 98 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012388 /* Sub list 2: different band */
Oliver Smitha6773042022-10-24 12:56:30 +020012389 { rxlev := 0, bcch_freq := 1, bsic := 13 }, /* ARFCN 200, band 850, LAC 97 */
12390 { rxlev := 40, bcch_freq := 2, bsic := 14 }, /* ARFCN 1000, band 900, LAC 99 */
12391 { rxlev := 0, bcch_freq := 3, bsic := 11 } /* ARFCN 0, band 900, LAC 96 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012392 };
12393 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
12394 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
12395 l3_mr, 0));
12396
12397 /* Expect a handover to the third entry. If the BSC parsed the report
Oliver Smitha6773042022-10-24 12:56:30 +020012398 * correctly, the third entry has LAC 99. */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012399 var template BSSMAP_FIELD_CellIdentificationList cid_list := {
Oliver Smitha6773042022-10-24 12:56:30 +020012400 cIl_LAC := { ts_BSSMAP_CI_LAC(99) }
Oliver Smithc9a5f532022-10-21 11:32:23 +020012401 };
12402 alt {
12403 [] BSSAP.receive(tr_BSSMAP_HandoverRequired(cid_list := cid_list)) {
12404 setverdict(pass);
12405 }
12406 [] BSSAP.receive(tr_BSSMAP_HandoverRequired()) {
12407 setverdict(fail, "Handover has unexpected LAC in Cell Identification List. The BSC probably"
12408 & " didn't parse the multi-band measurement report correctly.");
12409 }
12410 }
12411
12412 f_ho_out_of_this_bsc(skip_meas_rep := true);
12413}
12414testcase TC_ho_meas_rep_multi_band() runs on test_CT {
12415 /* Verify that the BSC parses the measurement report correctly when
12416 * neighbors in multiple bands are configured (OS#5717). See
12417 * gsm_arfcn2band_rc() in libosmocore src/gsm/gsm_utils.c for the
12418 * ARFCN -> band mapping. The MS is connected to band 1800. */
12419 var MSC_ConnHdlr vc_conn;
12420
12421 f_init_vty();
12422 f_bts_0_cfg(BSCVTY,
12423 {"neighbor-list mode automatic",
12424 "handover 1",
12425 "handover algorithm 2",
12426 "handover2 window rxlev averaging 1",
12427 "no neighbors",
12428 "neighbor lac 99 arfcn 1000 bsic any", /* band 900 */
12429 "neighbor lac 98 arfcn 800 bsic any", /* band 1800 */
12430 "neighbor lac 97 arfcn 200 bsic any", /* band 850 */
Oliver Smitha6773042022-10-24 12:56:30 +020012431 "neighbor lac 96 arfcn 0 bsic any"}); /* band 900 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012432 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
12433
12434 f_init(1, true);
12435 f_sleep(1.0);
12436
12437 f_ctrs_bsc_and_bts_handover_init();
12438
12439 vc_conn := f_start_handler(refers(f_tc_ho_meas_rep_multi_band));
12440 vc_conn.done;
12441
12442 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
12443 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
12444 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
12445 f_ctrs_bsc_and_bts_add(0, "handover:completed");
12446 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
12447 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
12448 f_ctrs_bsc_and_bts_verify();
12449 f_shutdown_helper(ho := true);
12450}
12451
Harald Welte28d943e2017-11-25 15:00:50 +010012452control {
Harald Welte898113b2018-01-31 18:32:21 +010012453 /* CTRL interface testing */
Harald Welte4003d112017-12-09 22:35:39 +010012454 execute( TC_ctrl_msc_connection_status() );
Stefan Sperlingb041b3d2018-01-03 17:14:55 +010012455 execute( TC_ctrl_msc0_connection_status() );
Neels Hofmeyrf65ce872021-09-23 18:40:10 +020012456 /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
12457 * these in the AoIP test suite. */
12458 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12459 execute( TC_stat_num_msc_connected_1() );
12460 execute( TC_stat_num_msc_connected_2() );
12461 execute( TC_stat_num_msc_connected_3() );
12462 }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020012463 execute( TC_stat_num_bts_connected_1() );
12464 execute( TC_stat_num_bts_connected_2() );
12465 execute( TC_stat_num_bts_connected_3() );
Harald Welte96c94412017-12-09 03:12:45 +010012466 execute( TC_ctrl() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012467 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +020012468 execute( TC_ctrl_location() );
12469 }
Harald Welte898113b2018-01-31 18:32:21 +010012470
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012471 execute( TC_si_default() );
Neels Hofmeyr66aeba42020-07-06 02:21:21 +020012472 execute( TC_si2quater_2_earfcns() );
12473 execute( TC_si2quater_3_earfcns() );
12474 execute( TC_si2quater_4_earfcns() );
12475 execute( TC_si2quater_5_earfcns() );
12476 execute( TC_si2quater_6_earfcns() );
Neels Hofmeyrad132f22020-07-08 02:20:16 +020012477 execute( TC_si2quater_12_earfcns() );
12478 execute( TC_si2quater_23_earfcns() );
12479 execute( TC_si2quater_32_earfcns() );
12480 execute( TC_si2quater_33_earfcns() );
12481 execute( TC_si2quater_42_earfcns() );
12482 execute( TC_si2quater_48_earfcns() );
12483 execute( TC_si2quater_49_earfcns() );
Pau Espin Pedrol85a84432020-07-20 18:45:03 +020012484 execute( TC_si_acc_rotate() );
Alexander Couzens4ad3a352020-09-10 22:29:12 +020012485 execute( TC_si_acc_ramp_rotate() );
Oliver Smith45a6dd32023-09-27 10:52:50 +020012486 execute( TC_si2_ncc_permitted() ); /* TODO: test in SI6 too */
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012487
Harald Welte898113b2018-01-31 18:32:21 +010012488 /* RSL DCHAN Channel ACtivation / Deactivation */
Harald Welteae026692017-12-09 01:03:01 +010012489 execute( TC_chan_act_noreply() );
Harald Welte4003d112017-12-09 22:35:39 +010012490 execute( TC_chan_act_counter() );
Harald Welteae026692017-12-09 01:03:01 +010012491 execute( TC_chan_act_ack_noest() );
Philipp Maier9c60a622020-07-09 15:08:46 +020012492 execute( TC_chan_act_ack_noest_emerg() );
Philipp Maier606f07d2020-08-12 17:21:58 +020012493 execute( TC_chan_rqd_emerg_deny() );
Harald Welteae026692017-12-09 01:03:01 +010012494 execute( TC_chan_act_ack_est_ind_noreply() );
12495 execute( TC_chan_act_ack_est_ind_refused() );
Harald Welte618ef642017-12-14 14:58:20 +010012496 execute( TC_chan_act_nack() );
Harald Welte799c97b2017-12-14 17:50:30 +010012497 execute( TC_chan_exhaustion() );
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +070012498 execute( TC_chan_deact_silence() );
Harald Welte4003d112017-12-09 22:35:39 +010012499 execute( TC_chan_rel_rll_rel_ind() );
12500 execute( TC_chan_rel_conn_fail() );
12501 execute( TC_chan_rel_hard_clear() );
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +020012502 execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
12503 execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
Harald Welte99787102019-02-04 10:41:36 +010012504 execute( TC_chan_rel_hard_clear_csfb() );
Harald Welted8c36cd2017-12-09 23:05:31 +010012505 execute( TC_chan_rel_hard_rlsd() );
Harald Welte550daf92018-06-11 19:22:13 +020012506 execute( TC_chan_rel_hard_rlsd_ms_dead() );
Harald Welte85804d42017-12-10 14:11:58 +010012507 execute( TC_chan_rel_a_reset() );
Pau Espin Pedrolc675b612020-01-09 19:55:40 +010012508 execute( TC_chan_rel_sccp_tiar_timeout() );
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +020012509 execute( TC_chan_rel_rr_cause() );
Harald Welte6f521d82017-12-11 19:52:02 +010012510
Harald Weltecfe2c962017-12-15 12:09:32 +010012511 execute( TC_outbound_connect() );
Harald Welte898113b2018-01-31 18:32:21 +010012512
12513 /* Assignment related */
Harald Welte16a4adf2017-12-14 18:54:01 +010012514 execute( TC_assignment_cic_only() );
Harald Welte235ebf12017-12-15 14:18:16 +010012515 execute( TC_assignment_csd() );
12516 execute( TC_assignment_ctm() );
12517 execute( TC_assignment_sign() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012518 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12519 execute( TC_assignment_aoip_tla_v6() );
12520 }
Harald Welte235ebf12017-12-15 14:18:16 +010012521 execute( TC_assignment_fr_a5_0() );
12522 execute( TC_assignment_fr_a5_1() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012523 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte8f67d1d2018-05-25 20:38:42 +020012524 execute( TC_assignment_fr_a5_1_codec_missing() );
12525 }
Harald Welte235ebf12017-12-15 14:18:16 +010012526 execute( TC_assignment_fr_a5_3() );
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +020012527 execute( TC_assignment_fr_a5_4() );
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +020012528 execute( TC_assignment_fr_a5_4_fail() );
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +020012529 execute( TC_assignment_fr_a5_not_sup() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012530 execute( TC_ciph_mode_a5_0() );
12531 execute( TC_ciph_mode_a5_1() );
Oliver Smith50b98122021-07-09 15:00:28 +020012532 execute( TC_ciph_mode_a5_2_0() );
Oliver Smith1dff88d2021-07-09 08:45:51 +020012533 execute( TC_ciph_mode_a5_2_1() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012534 execute( TC_ciph_mode_a5_3() );
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +020012535 execute( TC_ciph_mode_a5_4() );
Harald Welte16a4adf2017-12-14 18:54:01 +010012536
Harald Welte60aa5762018-03-21 19:33:13 +010012537 execute( TC_assignment_codec_fr() );
Neels Hofmeyr559d5d02021-04-16 16:50:49 +020012538 execute( TC_assignment_codec_fr_by_mode_modify() );
Harald Welte60aa5762018-03-21 19:33:13 +010012539 execute( TC_assignment_codec_hr() );
12540 execute( TC_assignment_codec_efr() );
12541 execute( TC_assignment_codec_amr_f() );
12542 execute( TC_assignment_codec_amr_h() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012543
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012544 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier8a581d22019-03-26 18:32:48 +010012545 execute( TC_assignment_codec_amr_f_S1() );
12546 execute( TC_assignment_codec_amr_h_S1() );
12547 execute( TC_assignment_codec_amr_f_S124() );
12548 execute( TC_assignment_codec_amr_h_S124() );
12549 execute( TC_assignment_codec_amr_f_S0() );
12550 execute( TC_assignment_codec_amr_f_S02() );
12551 execute( TC_assignment_codec_amr_f_S024() );
12552 execute( TC_assignment_codec_amr_f_S0247() );
12553 execute( TC_assignment_codec_amr_h_S0() );
12554 execute( TC_assignment_codec_amr_h_S02() );
12555 execute( TC_assignment_codec_amr_h_S024() );
12556 execute( TC_assignment_codec_amr_h_S0247() );
12557 execute( TC_assignment_codec_amr_f_S01234567() );
12558 execute( TC_assignment_codec_amr_f_S0234567() );
12559 execute( TC_assignment_codec_amr_f_zero() );
12560 execute( TC_assignment_codec_amr_f_unsupp() );
12561 execute( TC_assignment_codec_amr_h_S7() );
Neels Hofmeyr21863562020-11-26 00:34:33 +000012562 execute( TC_assignment_codec_amr_f_start_mode_auto() );
12563 execute( TC_assignment_codec_amr_h_start_mode_auto() );
Neels Hofmeyr3eb94562020-11-26 02:40:26 +000012564 execute( TC_assignment_codec_amr_f_start_mode_4() );
12565 execute( TC_assignment_codec_amr_h_start_mode_4() );
Neels Hofmeyr454d7922020-11-26 02:24:57 +000012566 execute( TC_assignment_codec_amr_startmode_cruft() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012567 }
Harald Welte60aa5762018-03-21 19:33:13 +010012568
Philipp Maierac09bfc2019-01-08 13:41:39 +010012569 execute( TC_assignment_codec_fr_exhausted_req_hr() );
12570 execute( TC_assignment_codec_fr_exhausted_req_fr() );
12571 execute( TC_assignment_codec_fr_exhausted_req_fr_hr() );
12572 execute( TC_assignment_codec_fr_exhausted_req_hr_fr() );
12573 execute( TC_assignment_codec_hr_exhausted_req_fr() );
12574 execute( TC_assignment_codec_hr_exhausted_req_hr() );
12575 execute( TC_assignment_codec_hr_exhausted_req_hr_fr() );
12576 execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
12577 execute( TC_assignment_codec_req_hr_fr() );
12578 execute( TC_assignment_codec_req_fr_hr() );
Pau Espin Pedrol14475352021-07-22 15:48:16 +020012579 execute( TC_assignment_sdcch_exhausted_req_signalling() );
12580 execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
12581 execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
Philipp Maierac09bfc2019-01-08 13:41:39 +010012582
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +020012583 execute( TC_assignment_codec_hr_osmux_on() );
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +020012584 execute( TC_assignment_osmux() );
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020012585 execute( TC_assignment_osmux_cn() );
12586 execute( TC_assignment_osmux_bts() );
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +020012587
Harald Welte898113b2018-01-31 18:32:21 +010012588 /* RLL Establish Indication on inactive DCHAN / SAPI */
Harald Welte5cd20ed2017-12-13 21:03:20 +010012589 execute( TC_rll_est_ind_inact_lchan() );
12590 execute( TC_rll_est_ind_inval_sapi1() );
12591 execute( TC_rll_est_ind_inval_sapi3() );
12592 execute( TC_rll_est_ind_inval_sacch() );
12593
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +070012594 /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
12595 execute( TC_tch_dlci_link_id_sapi() );
12596
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012597 /* SAPI N Reject triggered by RLL establishment failures */
12598 execute( TC_rll_rel_ind_sapi_n_reject() );
12599 execute( TC_rll_err_ind_sapi_n_reject() );
12600 execute( TC_rll_timeout_sapi_n_reject() );
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +070012601 execute( TC_rll_sapi_n_reject_dlci_cc() );
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012602
Harald Welte898113b2018-01-31 18:32:21 +010012603 /* Paging related tests */
Harald Welte6f521d82017-12-11 19:52:02 +010012604 execute( TC_paging_imsi_nochan() );
12605 execute( TC_paging_tmsi_nochan() );
12606 execute( TC_paging_tmsi_any() );
12607 execute( TC_paging_tmsi_sdcch() );
12608 execute( TC_paging_tmsi_tch_f() );
12609 execute( TC_paging_tmsi_tch_hf() );
12610 execute( TC_paging_imsi_nochan_cgi() );
12611 execute( TC_paging_imsi_nochan_lac_ci() );
12612 execute( TC_paging_imsi_nochan_ci() );
12613 execute( TC_paging_imsi_nochan_lai() );
12614 execute( TC_paging_imsi_nochan_lac() );
12615 execute( TC_paging_imsi_nochan_all() );
Harald Welte751d3eb2018-01-31 15:51:06 +010012616 execute( TC_paging_imsi_nochan_plmn_lac_rnc() );
12617 execute( TC_paging_imsi_nochan_rnc() );
12618 execute( TC_paging_imsi_nochan_lac_rnc() );
12619 execute( TC_paging_imsi_nochan_lacs() );
12620 execute( TC_paging_imsi_nochan_lacs_empty() );
Stefan Sperling049a86e2018-03-20 15:51:00 +010012621 execute( TC_paging_imsi_nochan_cgi_unknown_cid() );
Harald Welte10985002017-12-12 09:29:15 +010012622 execute( TC_paging_imsi_a_reset() );
Harald Weltee65d40e2017-12-13 00:09:06 +010012623 execute( TC_paging_imsi_load() );
Philipp Maier779a7922018-02-16 11:00:37 +010012624 execute( TC_paging_counter() );
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +010012625 execute( TC_paging_resp_unsol() );
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +020012626 execute( TC_paging_500req() );
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +020012627 execute( TC_paging_450req_no_paging_load_ind() );
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +010012628 execute( TC_paging_imsi_nochan_ci_resp_invalid_mi() );
Harald Welte4e9b9cc2017-12-14 18:31:02 +010012629
12630 execute( TC_rsl_drop_counter() );
Stefan Sperling830dc9d2018-02-12 21:08:28 +010012631 execute( TC_rsl_unknown_unit_id() );
12632
12633 execute( TC_oml_unknown_unit_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012634
12635 execute( TC_classmark() );
Harald Welteeddf0e92020-06-21 19:42:15 +020012636 execute( TC_common_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012637 execute( TC_unsol_ass_fail() );
Harald Welteea99a002018-01-31 20:46:43 +010012638 execute( TC_unsol_ass_compl() );
Harald Weltefbf9b5e2018-01-31 20:41:23 +010012639 execute( TC_unsol_ho_fail() );
Harald Weltee3bd6582018-01-31 22:51:25 +010012640 execute( TC_err_82_short_msg() );
Harald Weltee9e02e42018-01-31 23:36:25 +010012641 execute( TC_err_84_unknown_msg() );
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012642
Harald Welte261af4b2018-02-12 21:20:39 +010012643 execute( TC_ho_int() );
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +020012644 execute( TC_ho_int_a5_0() );
12645 execute( TC_ho_int_a5_1() );
12646 execute( TC_ho_int_a5_3() );
12647 execute( TC_ho_int_a5_4() );
Neels Hofmeyr5f144212020-11-03 15:41:58 +000012648 execute( TC_ho_int_radio_link_failure() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012649
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012650 /* TC_ho_out_of_this_bsc is run last, see comment below */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +020012651 execute( TC_ho_out_fail_no_msc_response() );
12652 execute( TC_ho_out_fail_rr_ho_failure() );
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +020012653 execute( TC_ho_out_fail_no_result_after_ho_cmd() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012654
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012655 execute( TC_ho_into_this_bsc() );
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +020012656 execute( TC_ho_into_this_bsc_a5_0() );
12657 execute( TC_ho_into_this_bsc_a5_1() );
12658 execute( TC_ho_into_this_bsc_a5_3() );
12659 execute( TC_ho_into_this_bsc_a5_4() );
Neels Hofmeyr93182e02022-02-17 21:59:07 +010012660 execute( TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() );
12661 execute( TC_ho_into_this_bsc_a5_1_3() );
Neels Hofmeyr907b23b2022-02-17 21:58:47 +010012662 execute( TC_ho_into_this_bsc_a5_mismatch() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012663 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12664 execute( TC_ho_into_this_bsc_tla_v6() );
12665 }
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +020012666 execute( TC_srvcc_eutran_to_geran() );
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +030012667 execute( TC_srvcc_eutran_to_geran_a5_3() );
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +010012668 execute( TC_srvcc_eutran_to_geran_src_sai() );
Pau Espin Pedrol35801c32021-04-19 13:03:20 +020012669 execute( TC_srvcc_eutran_to_geran_ho_out() );
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +020012670 execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
12671 execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012672 execute( TC_ho_in_fail_msc_clears() );
12673 execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
12674 execute( TC_ho_in_fail_no_detect() );
12675 execute( TC_ho_in_fail_no_detect2() );
Oliver Smith7a8594a2023-02-13 14:30:49 +010012676 execute( TC_ho_in_fail_mgw_mdcx_timeout() );
Oliver Smith4eed06f2023-02-15 15:43:19 +010012677 execute( TC_ho_in_fail_ipa_crcx_timeout() );
Neels Hofmeyra23f3b12022-03-02 19:57:12 +010012678 execute( TC_ho_into_this_bsc_sccp_cr_without_bssap() );
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012679
Neels Hofmeyr91401012019-07-11 00:42:35 +020012680 execute( TC_ho_neighbor_config_1() );
12681 execute( TC_ho_neighbor_config_2() );
12682 execute( TC_ho_neighbor_config_3() );
12683 execute( TC_ho_neighbor_config_4() );
12684 execute( TC_ho_neighbor_config_5() );
12685 execute( TC_ho_neighbor_config_6() );
12686 execute( TC_ho_neighbor_config_7() );
12687
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012688 execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() );
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010012689 execute( TC_bssmap_clear_does_not_cause_bssmap_reset() );
Neels Hofmeyrfd445c32018-03-09 15:39:31 +010012690 execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() );
Harald Welte94e0c342018-04-07 11:33:23 +020012691
12692 execute( TC_dyn_pdch_ipa_act_deact() );
12693 execute( TC_dyn_pdch_ipa_act_nack() );
12694 execute( TC_dyn_pdch_osmo_act_deact() );
12695 execute( TC_dyn_pdch_osmo_act_nack() );
Pau Espin Pedrol37a4c152021-11-16 19:02:23 +010012696 execute( TC_dyn_ts_sdcch8_act_deact() );
12697 execute( TC_dyn_ts_sdcch8_all_subslots_used() );
12698 execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
12699 execute( TC_dyn_ts_sdcch8_act_nack() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012700
Stefan Sperling0796a822018-10-05 13:01:39 +020012701 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +020012702 execute( TC_chopped_ipa_payload() );
Stefan Sperling0796a822018-10-05 13:01:39 +020012703
Pau Espin Pedrol8f773632019-11-05 11:46:53 +010012704 /* Power control related */
12705 execute( TC_assignment_verify_ms_power_params_ie() );
Vadim Yanitskiy4b233042021-06-30 00:58:43 +020012706 execute( TC_c0_power_red_mode() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012707
12708 /* MSC pooling */
12709 /* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
12710 * RESET->RESET-ACK is unconditionally negotiated for all configured MSCs, they always all appear as connected
12711 * to osmo-bsc. The MSC pooling tests however require disconnecting selected MSCs, and hence don't work out as
12712 * intended on SCCPlite. So for now, run these only for SCCP/M3UA. */
12713 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12714 execute( TC_mscpool_L3Compl_on_1_msc() );
12715 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
12716 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
12717 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
12718 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
12719 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
12720 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
12721 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
12722 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
12723 execute( TC_mscpool_paging_and_response_imsi() );
12724 execute( TC_mscpool_paging_and_response_tmsi() );
12725 execute( TC_mscpool_no_allow_attach_round_robin() );
12726 execute( TC_mscpool_no_allow_attach_valid_nri() );
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +020012727
12728 execute( TC_mscpool_sccp_n_pcstate_detaches_msc() );
Neels Hofmeyr38632aa2023-04-05 03:50:51 +020012729 execute( TC_mscpool_sccp_n_pcstate_attaches_msc() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012730 }
12731
Harald Welte99f3ca02018-06-14 13:40:29 +020012732 execute( TC_early_conn_fail() );
12733 execute( TC_late_conn_fail() );
Oliver Smithaf03bef2021-08-24 15:34:51 +020012734 execute( TC_stats_conn_fail() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012735
Philipp Maier783681c2020-07-16 16:47:06 +020012736 /* Emergency call handling (deny / allow) */
12737 execute( TC_assignment_emerg_setup_allow() );
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +010012738 execute( TC_assignment_emerg_setup_allow_imei() );
Philipp Maier783681c2020-07-16 16:47:06 +020012739 execute( TC_assignment_emerg_setup_deny_msc() );
12740 execute( TC_assignment_emerg_setup_deny_bts() );
Philipp Maier82812002020-08-13 18:48:27 +020012741 execute( TC_emerg_premption() );
12742
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +070012743 /* Frequency hopping parameters handling */
12744 execute( TC_fh_params_chan_activ() );
12745 execute( TC_fh_params_imm_ass() );
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070012746 execute( TC_fh_params_assignment_cmd() );
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070012747 execute( TC_fh_params_handover_cmd() );
Vadim Yanitskiyca974032020-09-01 07:20:39 +070012748 execute( TC_fh_params_si4_cbch() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012749
12750 if (mp_enable_lcs_tests) {
12751 execute( TC_lcs_loc_req_for_active_ms() );
12752 execute( TC_lcs_loc_req_for_active_ms_ta_req() );
12753 execute( TC_lcs_loc_req_for_idle_ms() );
12754 execute( TC_lcs_loc_req_no_subscriber() );
12755 execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
12756 execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
12757 execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
12758 execute( TC_cm_service_during_lcs_loc_req() );
12759 execute( TC_ho_during_lcs_loc_req() );
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020012760 execute( TC_emerg_call_and_lcs_loc_req() );
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020012761 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() );
12762 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012763 }
Neels Hofmeyrbf037052020-10-28 22:52:02 +000012764
12765 execute( TC_no_msc() );
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000012766
12767 execute( TC_refuse_chan_act_to_vamos() );
12768 execute( TC_refuse_mode_modif_to_vamos() );
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000012769
12770 execute( TC_reassignment_fr() );
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020012771
12772 execute( TC_cm_reestablishment() );
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020012773
12774 execute( TC_imm_ass_post_chan_ack() );
12775 execute( TC_imm_ass_pre_chan_ack() );
Neels Hofmeyr23158742021-09-07 19:08:07 +020012776 execute( TC_imm_ass_pre_ts_ack() );
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020012777 execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020012778 execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020012779
12780 execute( TC_ctrl_trx_rf_locked() );
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012781
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012782 execute( TC_ratectr_all_available_allocated() );
12783 execute( TC_ratectr_all_available_allocated_dyn() );
12784
Neels Hofmeyrb7581872021-11-07 14:02:49 +010012785 execute( TC_cm_serv_rej() );
12786
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012787 execute( TC_lost_sdcch_during_assignment() );
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012788
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012789 /* Channel allocator */
12790 execute( TC_chan_alloc_algo_ascending() );
12791 execute( TC_chan_alloc_algo_descending() );
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012792 execute( TC_chan_alloc_algo_ass_dynamic() );
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012793
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012794 /* MGW pool */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +010012795 execute( TC_mgwpool_all_used() );
12796 execute( TC_mgwpool_blocked_not_used() );
12797 execute( TC_mgwpool_pin_bts() );
Pau Espin Pedrolbd598422023-06-15 17:29:09 +020012798 execute( TC_mgwpool_keepalive_down_not_used() );
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012799
Oliver Smithc9a5f532022-10-21 11:32:23 +020012800 execute( TC_ho_meas_rep_multi_band() );
12801
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012802 /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
12803 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
12804 execute( TC_ho_out_of_this_bsc() );
Harald Welte28d943e2017-11-25 15:00:50 +010012805}
12806
12807}