blob: ba0858c47d84f2df551b92567d4d0af9449b74b5 [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 Pedrol07866632020-09-03 19:10:55 +02001729function f_gen_ass_req(boolean osmux_enabled := false, integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4") return PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001730 var PDU_BSSAP ass_cmd;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001731 var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
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 {
1741 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrol096d73d2019-06-06 12:49:17 +02001742 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(cic, omit));
Harald Welteed848512018-05-24 22:27:58 +02001743 }
1744 return ass_cmd;
1745}
1746
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02001747function f_gen_handover_req(integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4",
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001748 template (value) BSSMAP_IE_CellIdentifier cell_id_source := ts_CellID_LAC_CI(1, 1),
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001749 template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit,
1750 template (omit) TestHdlrEncrParams enc := omit) return PDU_BSSAP {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001751 var PDU_BSSAP ho_req;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001752
1753 var BSSMAP_IE_EncryptionInformation encryptionInformation :=
1754 valueof(ts_BSSMAP_IE_EncrInfo('0000000000000000'O,'01'O));
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03001755 var template (omit) BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := omit;
1756 var template (omit) BSSMAP_IE_KC128 kc128 := omit;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001757 if (ispresent(enc)) {
1758 var TestHdlrEncrParams v_enc := valueof(enc);
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01001759 encryptionInformation := valueof(ts_BSSMAP_IE_EncrInfo(v_enc.enc_key, v_enc.enc_alg_permitted));
1760 if (ispresent(v_enc.enc_alg_chosen)) {
1761 chosenEncryptionAlgorithm := valueof(
1762 ts_BSSMAP_IE_ChosenEncryptionAlgorithm(int2oct(enum2int(
1763 f_cipher_mode_bssmap_to_rsl(v_enc.enc_alg_chosen)), 1)));
1764 }
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001765 if (ispresent(v_enc.enc_kc128)) {
1766 kc128 := ts_BSSMAP_IE_Kc128(v_enc.enc_kc128);
1767 }
1768 }
1769
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001770 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001771 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001772 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001773 ho_req := valueof(ts_BSSMAP_HandoverRequest(omit, tla,
1774 cell_id_source := cell_id_source,
1775 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001776 encryptionInformation := encryptionInformation,
1777 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
Neels Hofmeyr9fe13202022-03-04 00:05:43 +01001778 kC128 := kc128,
1779 /* on AoIP, allow "all" codecs (until we add more concise
1780 * tests) */
1781 codecList := ts_BSSMAP_IE_CodecList(
1782 {ts_CodecAMR_F, ts_CodecAMR_H,
1783 ts_CodecEFR, ts_CodecFR, ts_CodecHR})));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001784 } else {
1785 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001786 ho_req := valueof(ts_BSSMAP_HandoverRequest(cic, omit,
1787 cell_id_source := cell_id_source,
1788 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001789 encryptionInformation := encryptionInformation,
1790 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
1791 kC128 := kc128));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001792 }
1793 return ho_req;
1794}
1795
Harald Welteed848512018-05-24 22:27:58 +02001796/* generate an assignment complete template for either AoIP or SCCPlite */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001797function f_gen_exp_compl(integer bssap_idx := 0)
1798runs on MSC_ConnHdlr return template PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001799 var template PDU_BSSAP exp_compl;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001800 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001801 var template BSSMAP_IE_Osmo_OsmuxCID exp_osmux_cid := omit;
1802 if (g_pars.use_osmux_cn) {
1803 var template (present) INT1 exp_cid := ?;
1804 if (isbound(g_media.mgcp_conn[0].local_osmux_cid) and isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1805 exp_cid := (g_media.mgcp_conn[0].local_osmux_cid, g_media.mgcp_conn[1].local_osmux_cid);
1806 } else if (isbound(g_media.mgcp_conn[0].local_osmux_cid)) {
1807 exp_cid := g_media.mgcp_conn[0].local_osmux_cid;
1808 } else if (isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1809 exp_cid := g_media.mgcp_conn[1].local_osmux_cid;
1810 }
1811 exp_osmux_cid := tr_OsmuxCID(exp_cid);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001812 }
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001813 exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, exp_osmux_cid);
Harald Welteed848512018-05-24 22:27:58 +02001814 } else {
1815 /* CIC is optional "*" as the MSC allocated it */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001816 exp_compl := tr_BSSMAP_AssignmentComplete(*, omit, omit);
Harald Welteed848512018-05-24 22:27:58 +02001817 }
1818 return exp_compl;
1819}
1820
Harald Welte235ebf12017-12-15 14:18:16 +01001821/* Run everything required up to sending a caller-specified assignment command and expect response */
1822function f_assignment_exp(PDU_BSSAP ass_cmd, template PDU_BSSAP exp, charstring fail_text)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001823runs on test_CT return DchanTuple {
Harald Welte235ebf12017-12-15 14:18:16 +01001824 var BSSAP_N_CONNECT_ind rx_c_ind;
1825 var RSL_Message rx_rsl;
1826 var DchanTuple dt;
1827
Harald Welte89d42e82017-12-17 16:42:41 +01001828 f_init(1);
Harald Welte235ebf12017-12-15 14:18:16 +01001829
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001830 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte235ebf12017-12-15 14:18:16 +01001831 /* send assignment without AoIP IEs */
1832 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
1833 alt {
1834 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1835 if (ischosen(exp.pdu.bssmap.assignmentComplete)) {
1836 setverdict(pass);
1837 } else {
1838 setverdict(fail, fail_text);
1839 }
1840 }
1841 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1842 if (ischosen(exp.pdu.bssmap.assignmentFailure)) {
1843 setverdict(pass);
1844 } else {
1845 setverdict(fail, fail_text);
1846 }
1847 }
1848 [] BSSAP.receive { repeat; }
1849 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001850 return dt;
Harald Welte235ebf12017-12-15 14:18:16 +01001851}
Oliver Smithdd002752023-02-21 13:35:00 +01001852
Oliver Smith545492d2023-04-19 13:05:30 +02001853private 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 +01001854 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welteed848512018-05-24 22:27:58 +02001855 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Oliver Smithbc392a82023-04-17 14:06:42 +02001856 var SDP_FIELD_PayloadType pt_csd := PT_CSD;
Oliver Smithdd002752023-02-21 13:35:00 +01001857
Harald Welte235ebf12017-12-15 14:18:16 +01001858 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smithdd002752023-02-21 13:35:00 +01001859 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecCSData}));
1860
Oliver Smith545492d2023-04-19 13:05:30 +02001861 /* Non-transparent service (3GPP TS 48.008 § 3.2.2.11, oct 5, bit 7) */
1862 if (not transp) {
1863 data_rate := data_rate or4b '40'O;
1864 }
1865
Oliver Smithcb617912023-04-18 11:29:10 +02001866 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := data_rate;
1867
1868 log("-----------------------------------------------");
1869 log("Assignment req with data rate: " & data_rate_str);
1870 log("-----------------------------------------------");
Oliver Smithdd002752023-02-21 13:35:00 +01001871
1872 f_establish_fully(ass_cmd, exp_compl);
Oliver Smithbc392a82023-04-17 14:06:42 +02001873
1874 if (g_media.bts.rtp_pt != enum2int(pt_csd)) {
1875 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("unexpected RTP payload type: ", g_media.bts.rtp_pt));
1876 }
1877
Oliver Smithdd002752023-02-21 13:35:00 +01001878 f_perform_clear();
Oliver Smithace447a2023-05-08 14:07:21 +02001879 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Oliver Smithdd002752023-02-21 13:35:00 +01001880}
Oliver Smithcb617912023-04-18 11:29:10 +02001881private function f_tc_assignment_csd_all(charstring id) runs on MSC_ConnHdlr {
1882 /* Data rates that require multi-slot HSCSD assignment are not tested
Oliver Smith545492d2023-04-19 13:05:30 +02001883 * on purpose (not supported): T_32k0, T_28k8, NT_43k5, NT_29k0 */
Oliver Smithcb617912023-04-18 11:29:10 +02001884 f_tc_assignment_csd("T_14k4", GSM0808_DATA_RATE_TRANSP_14k4);
1885 f_tc_assignment_csd("T_9k6", GSM0808_DATA_RATE_TRANSP_9k6);
1886 f_tc_assignment_csd("T_4k8", GSM0808_DATA_RATE_TRANSP_4k8);
1887 f_tc_assignment_csd("T_2k4", GSM0808_DATA_RATE_TRANSP_2k4);
1888 f_tc_assignment_csd("T_1k2", GSM0808_DATA_RATE_TRANSP_1k2);
1889 f_tc_assignment_csd("T_600", GSM0808_DATA_RATE_TRANSP_600);
1890 f_tc_assignment_csd("T_1200_75", GSM0808_DATA_RATE_TRANSP_1200_75);
Oliver Smith545492d2023-04-19 13:05:30 +02001891
1892 f_tc_assignment_csd("NT_12000_6000", GSM0808_DATA_RATE_NON_TRANSP_12000_6000, false);
1893 f_tc_assignment_csd("NT_14k5", GSM0808_DATA_RATE_NON_TRANSP_14k5, false);
1894 f_tc_assignment_csd("NT_12k0", GSM0808_DATA_RATE_NON_TRANSP_12k0, false);
1895 f_tc_assignment_csd("NT_6k0", GSM0808_DATA_RATE_NON_TRANSP_6k0, false);
Oliver Smithcb617912023-04-18 11:29:10 +02001896}
Oliver Smithdd002752023-02-21 13:35:00 +01001897testcase TC_assignment_csd() runs on test_CT {
1898 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.10.0 */
1899 var MSC_ConnHdlr vc_conn;
1900 var TestHdlrParams pars := f_gen_test_hdlr_pars();
1901 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
1902
Oliver Smith545492d2023-04-19 13:05:30 +02001903 f_init(1, true, guard_timeout := 120.0);
Oliver Smithdd002752023-02-21 13:35:00 +01001904 f_sleep(1.0);
Oliver Smithcb617912023-04-18 11:29:10 +02001905 vc_conn := f_start_handler(refers(f_tc_assignment_csd_all), pars);
Oliver Smithdd002752023-02-21 13:35:00 +01001906 vc_conn.done;
1907 } else {
1908 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
1909 var PDU_BSSAP ass_cmd := f_gen_ass_req();
1910 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
1911 //exp_fail.pdu.bssmap.assignmentFailure.cause.causeValue := int2bit(enum2int(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL), 7);
1912 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for CSD");
1913 f_perform_clear_test_ct(dt);
1914 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001915 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001916}
1917
1918testcase TC_assignment_ctm() runs on test_CT {
1919 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001920 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001921 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
1922 //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 +01001923 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
1924 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001925 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001926}
1927
Harald Welte4003d112017-12-09 22:35:39 +01001928type record DchanTuple {
1929 integer sccp_conn_id,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001930 RslChannelNr rsl_chan_nr,
1931 BtsTrxIdx idx
Harald Weltea5d2ab22017-12-09 14:21:42 +01001932}
1933
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +02001934type record of DchanTuple DchanTuples;
1935
Harald Welted6939652017-12-13 21:02:46 +01001936/* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001937private function f_chreq_act_ack(OCT1 ra := '23'O,
1938 GsmFrameNumber fn := 23,
1939 BtsTrxIdx idx := {0, 0})
Harald Welted6939652017-12-13 21:02:46 +01001940runs on test_CT return RslChannelNr {
1941 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001942 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
1943 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Harald Welted6939652017-12-13 21:02:46 +01001944 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001945 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10), idx);
1946 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Harald Welted6939652017-12-13 21:02:46 +01001947 return chan_nr;
1948}
1949
Harald Welte4003d112017-12-09 22:35:39 +01001950/* helper function to establish a dedicated channel via BTS and MSC */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001951function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1952 BtsTrxIdx idx := {0, 0})
Harald Welte4003d112017-12-09 22:35:39 +01001953runs on test_CT return DchanTuple {
1954 var BSSAP_N_CONNECT_ind rx_c_ind;
Harald Welte4003d112017-12-09 22:35:39 +01001955 var DchanTuple dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001956
Harald Welte4003d112017-12-09 22:35:39 +01001957 /* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001958 dt.rsl_chan_nr := f_chreq_act_ack(ra, fn, idx);
Harald Welte4003d112017-12-09 22:35:39 +01001959
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001960 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3), idx);
Harald Welte4003d112017-12-09 22:35:39 +01001961
1962 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1963 dt.sccp_conn_id := rx_c_ind.connectionId;
1964 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1965
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001966 dt.idx := idx;
Harald Welte4003d112017-12-09 22:35:39 +01001967 return dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001968}
1969
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001970/* 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 +06001971function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1972 BtsTrxIdx idx := {0, 0})
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001973runs on test_CT return DchanTuple {
1974 var BSSAP_N_CONNECT_ind rx_c_ind;
1975 var DchanTuple dt;
1976
1977 /* Send CHAN RQD */
1978 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001979 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001980
1981 /* The dyn TS first deactivates PDCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001982 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 +02001983 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001984 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001985
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001986 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001987 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1988
1989 /* Now activates the signalling channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001990 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10), idx);
1991 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001992
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001993 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 +02001994
1995 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1996 dt.sccp_conn_id := rx_c_ind.connectionId;
1997 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1998
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001999 dt.idx := idx;
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02002000 return dt;
2001}
2002
Harald Welte641fcbe2018-06-14 10:58:35 +02002003/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002004private function f_exp_chan_rel_and_clear(DchanTuple dt)
2005runs on test_CT {
Harald Welte641fcbe2018-06-14 10:58:35 +02002006 var RSL_Message rx_rsl;
2007 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002008 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 +02002009 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002010 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), dt.idx);
Harald Welte641fcbe2018-06-14 10:58:35 +02002011
2012 /* expect Clear Complete from BSC */
2013 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2014
2015 /* MSC disconnects as instructed. */
2016 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2017}
2018
Harald Welte4003d112017-12-09 22:35:39 +01002019/* Test behavior of channel release after unilateral RLL REL IND (DISC from MS) */
2020testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002021 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002022 var DchanTuple dt;
Harald Welte96c94412017-12-09 03:12:45 +01002023
Harald Welte89d42e82017-12-17 16:42:41 +01002024 f_init(1);
Harald Welte96c94412017-12-09 03:12:45 +01002025
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002026 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002027
2028 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002029 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Harald Welte4003d112017-12-09 22:35:39 +01002030
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002031 /* expect Clear Request on MSC side */
2032 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2033
2034 /* Instruct BSC to clear channel */
2035 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2036 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2037
Harald Welte4003d112017-12-09 22:35:39 +01002038 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002039 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002040
2041 /* wait for SCCP emulation to do its job */
2042 f_sleep(1.0);
Harald Welte4003d112017-12-09 22:35:39 +01002043
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002044 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002045}
2046
2047/* Test behavior of channel release after CONN FAIL IND from BTS */
2048testcase TC_chan_rel_conn_fail() runs on test_CT {
2049 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002050 var DchanTuple dt;
2051
Harald Welte89d42e82017-12-17 16:42:41 +01002052 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002053
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002054 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002055
Vadim Yanitskiy01d0a902022-12-14 22:41:42 +07002056 /* Sending CONN FAIL IND immediately may trigger a race condition.
2057 * Give the BSC some time to process a new SCCP connection (OS#5823). */
2058 f_sleep(0.2);
2059
Harald Welte4003d112017-12-09 22:35:39 +01002060 /* simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002061 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte4003d112017-12-09 22:35:39 +01002062 /* TODO: different cause values? */
2063
Harald Welte4003d112017-12-09 22:35:39 +01002064 /* expect Clear Request from BSC */
2065 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2066
2067 /* Instruct BSC to clear channel */
2068 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2069 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2070
Harald Welte6ff76ea2018-01-28 13:08:01 +01002071 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002072 f_exp_chan_rel_and_clear(dt);
Harald Welte4003d112017-12-09 22:35:39 +01002073
2074 /* wait for SCCP emulation to do its job */
2075 f_sleep(1.0);
2076
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002077 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002078}
2079
Harald Welte99f3ca02018-06-14 13:40:29 +02002080/* Test behavior of early CONN FAIL IND from BTS (before EST IND!) */
2081/* See also https://www.osmocom.org/issues/3182 */
2082testcase TC_early_conn_fail() runs on test_CT {
2083 var RSL_Message rx_rsl;
2084 var DchanTuple dt;
2085
2086 f_init(1);
2087
2088 /* BTS->BSC: Send CHAN RQD and wait for allocation; acknowledge it */
Harald Weltec46ea3c2020-10-10 18:46:12 +02002089 dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_ra_cs(), 23);
Harald Welte99f3ca02018-06-14 13:40:29 +02002090
2091 /* BTS->BSC: simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002092 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002093
2094 /* BTS->BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002095 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002096
2097 /* BTS<-BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002098 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002099
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002100 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002101}
2102
2103/* Test behavior of late CONN FAIL IND from BTS (ater REL IND!) */
2104/* See also https://www.osmocom.org/issues/3182 */
2105testcase TC_late_conn_fail() runs on test_CT {
2106 var RSL_Message rx_rsl;
2107 var DchanTuple dt;
2108
2109 f_init(1);
2110
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002111 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99f3ca02018-06-14 13:40:29 +02002112
2113 /* BSC<-MSC: Instruct BSC to clear connection */
2114 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(0)));
2115
2116 /* BTS->BSC: expect BSC to deactivate SACCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002117 rx_rsl := f_exp_ipa_rx(tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002118
2119 /* BTS->BSC: simulate a late CONN FAIL IND from BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002120 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002121
2122 /* BTS<-BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002123 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002124 /* BTS->BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002125 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002126
2127 /* BSC->MSC: expect Clear Complete from BSC */
2128 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2129
2130 /* BSC<-MSC: MSC disconnects as requested. */
2131 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2132
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002133 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002134}
2135
Oliver Smithaf03bef2021-08-24 15:34:51 +02002136private function f_TC_stats_conn_fail(charstring id) runs on MSC_ConnHdlr {
2137 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
2138 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2139
2140 f_statsd_reset();
2141
Oliver Smith15890b42023-03-08 14:12:28 +01002142 /* Establish SDCCH (invalid DataIndicator for exp_fail) */
Oliver Smithaf03bef2021-08-24 15:34:51 +02002143 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smith15890b42023-03-08 14:12:28 +01002144 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := 'ff'O;
Oliver Smithaf03bef2021-08-24 15:34:51 +02002145 f_establish_fully(ass_cmd, exp_fail);
2146
2147 /* Expect stats to be 0 */
2148 var StatsDExpects expect := {
2149 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
2150 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
2151 };
2152 f_statsd_expect(expect);
2153
2154 /* Simulate CONN FAIL IND on SDCCH */
2155 RSL.send(ts_ASP_RSL_UD(
2156 ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
2157 IPAC_PROTO_RSL_TRX0));
2158
Neels Hofmeyr58be48a2021-09-07 18:39:21 +02002159 f_sleep(1.0);
2160
Oliver Smithaf03bef2021-08-24 15:34:51 +02002161 /* Expect stats to be 1 */
2162 expect := {
2163 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
2164 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
2165 };
2166 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002167 BSSAP.receive(tr_BSSMAP_ClearRequest);
2168 f_perform_clear();
Oliver Smithaf03bef2021-08-24 15:34:51 +02002169}
2170testcase TC_stats_conn_fail() runs on test_CT {
2171 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2172 var MSC_ConnHdlr vc_conn;
2173
2174 f_init(1, true);
2175 f_sleep(1.0);
2176
2177 vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
2178 vc_conn.done;
2179
2180 f_shutdown_helper();
2181}
2182
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002183function f_expect_chan_rel(RslChannelNr rsl_chan_nr,
2184 BtsTrxIdx idx := {0, 0},
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002185 boolean expect_deact_sacch := true,
2186 boolean expect_rr_chan_rel := true,
2187 boolean expect_rll_rel_req := true,
Harald Welte99787102019-02-04 10:41:36 +01002188 boolean handle_rll_rel := true,
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002189 template CellSelIndValue expect_cells := omit,
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002190 template (present) RR_Cause expect_rr_cause := ?
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002191 ) runs on test_CT {
Harald Welte91d54a52018-01-28 15:35:07 +01002192
2193 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002194 var boolean got_deact_sacch := false;
2195 var boolean got_rr_chan_rel := false;
2196 var boolean got_rll_rel_req := false;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002197 var ASP_RSL_Unitdata ud;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002198 var RSL_IE_Body l3_ie;
2199 var PDU_ML3_NW_MS l3;
2200 var RR_Cause got_cause;
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002201 log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
2202 " expect_rll_rel_req=", expect_rll_rel_req);
Harald Welte91d54a52018-01-28 15:35:07 +01002203 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002204 [] 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 +01002205 got_deact_sacch := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002206 repeat;
2207 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002208 [] 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 +01002209 got_rr_chan_rel := true;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002210
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002211 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2212 setverdict(fail, "cannot find L3");
2213 mtc.stop;
2214 }
2215 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2216
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002217 if (not istemplatekind(expect_cells, "omit")) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002218 var CellSelIndValue cells := dec_CellSelIndValue(
2219 l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
2220
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002221 log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
2222 if (match(cells, expect_cells)) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002223 setverdict(pass);
2224 } else {
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002225 log("EXPECTED CELLS: ", expect_cells);
2226 setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002227 }
2228 }
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002229
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002230 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2231 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2232 if (match(got_cause, expect_rr_cause)) {
2233 setverdict(pass);
2234 } else {
2235 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2236 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002237 }
Harald Welte99787102019-02-04 10:41:36 +01002238 repeat;
2239 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002240 [] 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 +01002241 got_rll_rel_req := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002242 /* FIXME: Why are we getting this for LinkID SACCH? */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002243 if (handle_rll_rel) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002244 f_ipa_tx(ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002245 }
Harald Welte91d54a52018-01-28 15:35:07 +01002246 repeat;
2247 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002248 [] 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 +01002249 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002250 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
Harald Welte91d54a52018-01-28 15:35:07 +01002251 }
2252 /* ignore any user data */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002253 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002254 repeat;
2255 }
2256 }
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002257
2258 log("f_expect_chan_rel() summary: got_deact_sacch=", got_deact_sacch, " got_rr_chan_rel=", got_rr_chan_rel,
2259 " got_rll_rel_req=", got_rll_rel_req);
2260
2261 if (expect_deact_sacch != got_deact_sacch) {
2262 setverdict(fail, "f_expect_chan_rel(): expect_deact_sacch=", expect_deact_sacch, " got_deact_sacch=", got_deact_sacch);
2263 }
2264 if (expect_rr_chan_rel != got_rr_chan_rel) {
2265 setverdict(fail, "f_expect_chan_rel(): expect_rr_chan_rel=", expect_rr_chan_rel, " got_rr_chan_rel=", got_rr_chan_rel);
2266 }
2267 if (expect_rll_rel_req != got_rll_rel_req) {
2268 setverdict(fail, "f_expect_chan_rel(): expect_rll_rel_req=", expect_rll_rel_req, " got_rll_rel_req=", got_rll_rel_req);
2269 }
Harald Welte91d54a52018-01-28 15:35:07 +01002270}
2271
Harald Welte4003d112017-12-09 22:35:39 +01002272/* Test behavior of channel release after hard Clear Command from MSC */
2273testcase TC_chan_rel_hard_clear() runs on test_CT {
2274 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002275 var DchanTuple dt;
Harald Welte4003d112017-12-09 22:35:39 +01002276
Harald Welte89d42e82017-12-17 16:42:41 +01002277 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002278
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002279 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002280
2281 /* Instruct BSC to clear channel */
2282 var BssmapCause cause := 0;
2283 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2284
2285 /* expect Clear Complete from BSC on A */
2286 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2287 /* release the SCCP connection */
2288 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2289 }
2290
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002291 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002292 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002293}
2294
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002295function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
2296 var BSSAP_N_DATA_ind rx_di;
2297 var DchanTuple dt;
2298
2299 f_init(1);
2300
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002301 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002302 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2303 /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
2304 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
2305
2306 /* Instruct BSC to clear channel */
2307 var BssmapCause cause := 0;
2308 if (tx_csfb_ind) {
2309 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2310 } else {
2311 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2312 }
2313
2314 /* expect Clear Complete from BSC on A */
2315 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2316 /* release the SCCP connection */
2317 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2318 }
2319
2320 /* 1 neighbor is added by default in osmo-bts.cfg and
2321 SystemInformationConfig_default, use that: */
2322 var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
2323
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002324 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 +02002325 f_shutdown_helper();
2326}
2327
2328/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
2329 from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
2330 PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2331 EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
2332 Indicator or not shouldn't matter at all. */
2333testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
2334 f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
2335}
2336
2337/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
2338 MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
2339 Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2340 EUTRAN neighbor list sent later on by BSC in RR Channel. */
2341testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
2342 f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
2343}
2344
2345/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
2346 MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
2347 Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
2348 CSFB Indicator should not be used anymore, and hence, there should be no
2349 EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
2350 Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
Harald Welte99787102019-02-04 10:41:36 +01002351testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
2352 var BSSAP_N_DATA_ind rx_di;
2353 var DchanTuple dt;
2354
2355 f_init(1);
2356
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002357 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99787102019-02-04 10:41:36 +01002358
2359 /* Instruct BSC to clear channel */
2360 var BssmapCause cause := 0;
2361 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2362
2363 /* expect Clear Complete from BSC on A */
2364 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2365 /* release the SCCP connection */
2366 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2367 }
2368
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002369 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002370 f_shutdown_helper();
Harald Welte99787102019-02-04 10:41:36 +01002371}
2372
Harald Welted8c36cd2017-12-09 23:05:31 +01002373/* Test behavior of channel release after hard RLSD from MSC */
2374testcase TC_chan_rel_hard_rlsd() runs on test_CT {
Harald Welted8c36cd2017-12-09 23:05:31 +01002375 var DchanTuple dt;
Harald Welted8c36cd2017-12-09 23:05:31 +01002376
Harald Welte89d42e82017-12-17 16:42:41 +01002377 f_init(1);
Harald Welted8c36cd2017-12-09 23:05:31 +01002378
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002379 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welted8c36cd2017-12-09 23:05:31 +01002380
2381 /* release the SCCP connection */
2382 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2383
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002384 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002385 f_shutdown_helper();
Harald Welted8c36cd2017-12-09 23:05:31 +01002386}
2387
Harald Welte550daf92018-06-11 19:22:13 +02002388/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
2389testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
2390 var DchanTuple dt;
2391
2392 f_init(1);
2393
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002394 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte550daf92018-06-11 19:22:13 +02002395
2396 /* release the SCCP connection */
2397 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2398
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002399 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002400 f_shutdown_helper();
Harald Welte550daf92018-06-11 19:22:13 +02002401}
2402
Harald Welte85804d42017-12-10 14:11:58 +01002403/* Test behavior of channel release after BSSMAP RESET from MSC */
2404testcase TC_chan_rel_a_reset() runs on test_CT {
Harald Welte85804d42017-12-10 14:11:58 +01002405 var DchanTuple dt;
Harald Welte85804d42017-12-10 14:11:58 +01002406
Harald Welte89d42e82017-12-17 16:42:41 +01002407 f_init(1);
Harald Welte85804d42017-12-10 14:11:58 +01002408
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002409 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte85804d42017-12-10 14:11:58 +01002410
2411 /* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002412 IPA_RSL[0][0].clear;
Harald Welte85804d42017-12-10 14:11:58 +01002413
2414 /* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002415 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 +01002416 interleave {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002417 [] 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 +01002418 [] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
2419 }
2420
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002421 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002422 f_shutdown_helper();
Harald Welte85804d42017-12-10 14:11:58 +01002423}
2424
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002425/* Verify T(iar) triggers and releases the channel */
2426testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
2427 var DchanTuple dt;
2428
2429 /* Set T(iar) in BSC low enough that it will trigger before other side
2430 has time to keep alive with a T(ias). Keep recommended ratio of
2431 T(iar) >= T(ias)*2 */
2432 g_bsc_sccp_timer_ias := 2;
2433 g_bsc_sccp_timer_iar := 5;
2434
2435 f_init(1);
2436
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002437 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002438 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002439 f_shutdown_helper();
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002440}
2441
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002442private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause,
2443 template (present) RR_Cause expect_rr_cause)
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002444runs on test_CT
2445{
2446 var DchanTuple dt;
2447
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002448 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002449 var BssmapCause cause := 0;
2450 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
2451 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2452 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2453 }
2454
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002455 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 +02002456}
2457
2458/* Test that Clear Command cause codes affect the RR Channel Release cause code */
2459testcase TC_chan_rel_rr_cause() runs on test_CT {
2460 f_init(1);
2461
2462 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
2463 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
2464 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
2465 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
2466 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
2467 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
Vadim Yanitskiye18aebb2021-01-03 13:10:43 +01002468
2469 f_shutdown_helper();
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002470}
2471
Harald Welte5cd20ed2017-12-13 21:03:20 +01002472/* Test behavior if RSL EST IND for non-active channel */
2473testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
2474 timer T := 2.0;
2475
Harald Welte89d42e82017-12-17 16:42:41 +01002476 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002477
Harald Welte5cd20ed2017-12-13 21:03:20 +01002478 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002479 var octetstring l3_payload := gen_l3_valid_payload();
2480 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002481
2482 T.start;
2483 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002484 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002485 setverdict(fail, "MSC received COMPL L3 for non-active lchan");
2486 }
2487 [] BSSAP.receive {}
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002488 [] IPA_RSL[0][0].receive {}
Harald Welte5cd20ed2017-12-13 21:03:20 +01002489 [] T.timeout {}
2490 }
2491
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002492 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002493}
2494
2495/* Test behavior if RSL EST IND for invalid SAPI */
2496testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
2497 var RslChannelNr chan_nr;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002498 var octetstring l3_payload;
Harald Welte5cd20ed2017-12-13 21:03:20 +01002499
Harald Welte89d42e82017-12-17 16:42:41 +01002500 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002501
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002502 chan_nr := f_chreq_act_ack();
2503 l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002504
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002505 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002506
2507 timer T := 2.0;
2508 T.start;
2509 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002510 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002511 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
2512 }
2513 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002514 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002515 [] T.timeout {}
2516 }
2517
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002518 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002519}
2520
2521/* Test behavior if RSL EST IND for invalid SAPI */
2522testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
2523 timer T := 2.0;
2524
Harald Welte89d42e82017-12-17 16:42:41 +01002525 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002526
2527 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002528 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002529
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002530 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002531
2532 T.start;
2533 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002534 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002535 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
2536 }
2537 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002538 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002539 [] T.timeout {}
2540 }
2541
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002542 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002543}
2544
2545/* Test behavior if RSL EST IND for invalid SACCH */
2546testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
2547 timer T := 2.0;
2548
Harald Welte89d42e82017-12-17 16:42:41 +01002549 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002550
2551 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002552 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002553
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002554 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002555
2556 T.start;
2557 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002558 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002559 setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
2560 }
2561 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002562 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002563 [] T.timeout {}
2564 }
2565
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002566 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002567}
2568
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002569/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
2570private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
2571 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
2572 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2573
2574 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
2575 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
2576
2577 f_establish_fully(ass_cmd, exp_compl);
2578
2579 /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
2580 RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
2581 /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
2582 BSSAP.receive(PDU_BSSAP:{
2583 discriminator := '1'B,
2584 spare := '0000000'B,
2585 dlci := 'C3'O,
2586 lengthIndicator := ?,
2587 pdu := { dtap := '0904'O }
2588 });
2589
2590 /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
2591 for (var integer i := 0; i < 32; i := i + 1) {
2592 var octetstring l3 := '09'O & f_rnd_octstring(14);
2593 var template (value) RslLinkId link_id;
2594 var template (value) OCT1 dlci;
2595
2596 if (i mod 2 == 0) {
2597 /* SAPI0 on FACCH or SDCCH */
2598 link_id := ts_RslLinkID_DCCH(0);
2599 dlci := '80'O;
2600 } else {
2601 /* SAPI3 on SACCH */
2602 link_id := ts_RslLinkID_SACCH(3);
2603 dlci := 'C3'O;
2604 }
2605
2606 /* Send MO message: RSL -> BSSAP */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002607 f_mo_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002608 /* Send MT message: BSSAP -> RSL */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002609 f_mt_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002610 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002611 f_perform_clear();
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002612}
2613testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
2614 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2615 var MSC_ConnHdlr vc_conn;
2616
2617 f_init(1, true);
2618 f_sleep(1.0);
2619
2620 vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
2621 vc_conn.done;
2622
2623 f_shutdown_helper();
2624}
2625
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002626private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002627 template (present) myBSSMAP_Cause cause := ?,
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002628 template (present) BIT2 cc := ?,
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002629 float T_val := 2.0)
2630runs on test_CT {
2631 var BSSAP_N_DATA_ind rx_di;
2632 timer T;
2633
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002634 var template (present) BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
2635 var template (present) PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002636
2637 T.start(T_val);
2638 alt {
2639 [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
2640 var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
2641 if (not match(rx_cause, tr_cause)) {
2642 setverdict(fail, "Rx unexpected Cause IE: ",
2643 rx_cause, " vs expected ", tr_cause);
2644 }
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002645
2646 /* Who ever on the earth decided to define this field as two separate bits?!? */
2647 var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
2648 & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
2649 if (not match(rx_cc, cc)) {
2650 setverdict(fail, "Rx unexpected Control Channel type: ",
2651 rx_cc, " vs expected ", cc);
2652 }
2653
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002654 setverdict(pass);
2655 }
2656 [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
2657 setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
2658 }
2659 [] T.timeout {
2660 setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
2661 }
2662 }
2663}
2664
2665/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
2666testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002667 var RSL_Message rx_rsl;
2668 var DchanTuple dt;
2669
2670 f_init(1);
2671
2672 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002673 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002674
2675 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002676 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 +07002677 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002678 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 +07002679
2680 /* MS sends unexpected RELease INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002681 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002682 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2683 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
2684
2685 /* Clean up the connection */
2686 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002687 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002688
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002689 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002690}
2691
2692/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
2693testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002694 var RSL_Message rx_rsl;
2695 var DchanTuple dt;
2696
2697 f_init(1);
2698
2699 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002700 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002701
2702 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002703 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 +07002704 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002705 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 +07002706
2707 /* BTS sends unexpected ERROR INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002708 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002709 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2710 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
2711
2712 /* Clean up the connection */
2713 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002714 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002715
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002716 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002717}
2718
2719/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
2720testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002721 var RSL_Message rx_rsl;
2722 var DchanTuple dt;
2723
2724 f_init(1);
2725
2726 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002727 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002728
2729 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002730 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 +07002731 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002732 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 +07002733
2734 /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
2735 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
2736
2737 /* Clean up the connection */
2738 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002739 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002740
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002741 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002742}
2743
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002744/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
2745testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002746 var RSL_Message rx_rsl;
2747 var DchanTuple dt;
2748
2749 f_init(1);
2750
2751 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002752 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002753
2754 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002755 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 +07002756 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002757 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 +07002758
2759 /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002760 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Pau Espin Pedrol121f27f2022-01-12 12:02:10 +01002761 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, '10'B);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002762
2763 /* Clean up the connection */
2764 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002765 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002766
2767 f_shutdown_helper();
2768}
2769
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002770testcase TC_si_default() runs on test_CT {
2771 f_init(0);
2772 f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002773 f_shutdown_helper();
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002774}
Harald Welte4003d112017-12-09 22:35:39 +01002775
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002776/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
2777 * the entire value range. This function provides the same EARFCN numbers for the same earfcn_index */
2778private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uint16_t
2779{
2780 select (earfcn_index) {
2781 case (0) {
2782 /* E-ARFCN 111 is already added in the osmo-bsc.cfg */
2783 return 111;
2784 }
2785 case (1) {
2786 return 1;
2787 }
2788 case (2) {
2789 return 0;
2790 }
2791 case (3) {
2792 return 65535;
2793 }
2794 case else {
2795 return 23 * (earfcn_index - 3);
2796 }
2797 }
2798}
2799
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002800function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
2801 template CellSelIndValue expect_cells := omit) runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002802
2803 f_init(0);
2804
2805 /* E-ARFCN 111 is already added in the osmo-bsc.cfg, so only add more arfcns if total_earfcns > 1 */
2806 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002807 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2808 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002809 }
2810
2811 f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
2812
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002813 if (not istemplatekind(expect_cells, "omit")) {
2814 /* Also check that RR Channel Release contains these EARFCNs.
2815 * (copied code from TC_chan_rel_hard_clear_csfb) */
2816 var BSSAP_N_DATA_ind rx_di;
2817 var DchanTuple dt;
2818
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002819 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrold0046312021-04-19 16:35:58 +02002820 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2821 * yet when generating the EUTRAN neigh list in RR CHannel Release) */
2822 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002823
2824 /* Instruct BSC to clear channel */
2825 var BssmapCause cause := 0;
2826 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2827
2828 /* expect Clear Complete from BSC on A */
2829 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2830 /* release the SCCP connection */
2831 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2832 }
2833
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002834 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := expect_cells);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002835 }
2836
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002837 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002838 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 +02002839 }
2840}
2841
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002842private function f_tr_si2quater_earfcns(integer count) return template SI2quaterRestOctetsList
2843{
2844 var template SI2quaterRestOctetsList si2quater := {};
2845 var integer si2quater_count := (count + 2) / 3;
2846
2847 for (var integer i := 0; i < count; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002848 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002849 var integer index := i / 3;
2850 var integer earfcn_index := i mod 3;
2851 if (index >= lengthof(si2quater)) {
2852 si2quater[index] := tr_SI2quaterRestOctets_EUTRAN(index := index, count := si2quater_count - 1);
2853 }
2854 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);
2855 }
2856
2857 return si2quater;
2858}
2859
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002860private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
2861{
2862 var template CellSelIndValue_EUTRAN_Descrs cells := {};
2863
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002864 /* the lte neighbors must match the config & vty to pass this test */
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002865 for (var integer i := 0; i < count; i := i + 1) {
2866 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002867 cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002868 }
2869
2870 return tr_CellSelIndValue_EUTRAN(cells);
2871}
2872
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002873private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
2874{
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002875 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrol8ab62e42020-12-18 16:19:11 +01002876 sic.si2quater := f_tr_si2quater_earfcns(n);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002877 var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
2878 f_test_si2quater(n, sic, cells);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002879}
2880
2881testcase TC_si2quater_2_earfcns() runs on test_CT {
2882 f_tc_si2quater_n_earfcns(2);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002883 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002884}
2885
2886testcase TC_si2quater_3_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002887 f_tc_si2quater_n_earfcns(3);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002888 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002889}
2890
2891testcase TC_si2quater_4_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002892 f_tc_si2quater_n_earfcns(4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002893 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002894}
2895
2896testcase TC_si2quater_5_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002897 f_tc_si2quater_n_earfcns(5);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002898 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002899}
2900
2901testcase TC_si2quater_6_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002902 f_tc_si2quater_n_earfcns(6);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002903 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002904}
2905
2906testcase TC_si2quater_12_earfcns() runs on test_CT {
2907 f_tc_si2quater_n_earfcns(12);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002908 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002909}
2910
2911testcase TC_si2quater_23_earfcns() runs on test_CT {
2912 f_tc_si2quater_n_earfcns(23);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002913 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002914}
2915
2916testcase TC_si2quater_32_earfcns() runs on test_CT {
2917 f_tc_si2quater_n_earfcns(32);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002918 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002919}
2920
2921testcase TC_si2quater_33_earfcns() runs on test_CT {
2922 f_tc_si2quater_n_earfcns(33);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002923 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002924}
2925
2926testcase TC_si2quater_42_earfcns() runs on test_CT {
2927 f_tc_si2quater_n_earfcns(42);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002928 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002929}
2930
2931testcase TC_si2quater_48_earfcns() runs on test_CT {
2932 f_tc_si2quater_n_earfcns(48);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002933 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002934}
2935
2936/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
2937 * 48 EARFCNs. */
2938testcase TC_si2quater_49_earfcns() runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002939 var template SystemInformationConfig sic := SystemInformationConfig_default;
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002940 sic.si2quater := f_tr_si2quater_earfcns(48); /* 48, not 49! */
2941 f_init(0);
2942
2943 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002944 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2945 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002946 }
2947
2948 /* The 49th EARFCN no longer fits, expect VTY error */
2949 f_vty_enter_cfg_bts(BSCVTY, 0);
2950 var charstring vty_error;
2951 vty_error := f_vty_transceive_ret(BSCVTY,
2952 "si2quater neighbor-list add earfcn 70 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3")
2953 f_vty_transceive(BSCVTY, "end");
2954
2955 if (f_strstr(vty_error, "Unable to add ARFCN 70") >= 0) {
2956 log("Got expected VTY error: ", vty_error);
2957 setverdict(pass);
2958 } else {
2959 setverdict(fail, "Expected the 49th EUTRAN ARFCN to be rejected by vty config, got: ", vty_error);
2960 }
2961
2962 f_init_bts_and_check_sysinfo(0, expect_si := sic);
2963
2964 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002965 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 +02002966 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002967 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002968}
2969
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002970private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
2971{
2972 var uint8_t count := 0;
2973 for (var integer i := 5; i < 16; i := i + 1) {
2974 if (acc[i] == '0'B) { /* the list marks barred, we count allowed */
2975 count := count + 1;
2976 }
2977 }
2978 return count;
2979}
2980
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002981private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return SystemInformationType1
2982{
2983 var ASP_RSL_Unitdata rx_rsl_ud;
2984 var SystemInformationType1 last_si1;
2985
2986 timer T := 30.0;
2987 T.start;
2988 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002989 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
2990 tr_RSL_BCCH_INFO,
2991 tr_RSL_NO_SACCH_FILL,
2992 tr_RSL_SACCH_FILL))) -> value rx_rsl_ud {
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002993 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
2994 if (g_system_information[rsl_idx].si1 == omit) {
2995 repeat;
2996 }
2997 last_si1 := g_system_information[rsl_idx].si1;
2998 g_system_information[rsl_idx].si1 := omit;
2999 T.stop;
3000 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003001 [] IPA_RSL[rsl_idx][0].receive { repeat; }
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003002 [] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
3003 }
3004 return last_si1;
3005}
3006
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003007/* verify ACC rotate feature */
3008testcase TC_si_acc_rotate() runs on test_CT {
3009 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003010 var SystemInformationType1 last_si1;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003011 var AccessControlClass acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003012 var uint8_t count;
3013 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3014
3015 f_init(0, guard_timeout := 60.0);
3016
3017 f_bts_0_cfg(BSCVTY, {"rach access-control-class 5 barred",
3018 "access-control-class-rotate 3",
3019 "access-control-class-rotate-quantum 1"});
3020
3021 /* Init and get first sysinfo */
3022 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3023
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003024 for (var integer i:= 0; i < 20; i := i + 1) {
3025 last_si1 := f_recv_next_si1(0);
3026 acc := last_si1.rach_control.acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003027 count := f_acc09_count_allowed(acc);
3028 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3029
3030 if (count != 3) {
3031 log("RSL: EXPECTED SI ACC len=3");
3032 setverdict(fail, "received SI does not match expectations");
3033 break;
3034 }
3035
3036 for (var integer j := 0; j < 10; j := j + 1) {
3037 if (acc[16 - 1 - j] == '0'B) { /* the list marks barred, we count allowed */
3038 times_allowed[j] := times_allowed[j] + 1;
3039 }
3040 }
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003041 }
3042
3043 for (var integer j := 0; j < 10; j := j + 1) {
3044 log("ACC", j, " allowed ", times_allowed[j], " times" );
3045 if (j != 5 and times_allowed[j] < 3) {
3046 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " < 1 times");
3047 } else if (j == 5 and times_allowed[j] > 0) {
3048 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " > 0 times");
3049 }
3050 }
3051
3052 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3053 "rach access-control-class 5 allowed"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003054 f_shutdown_helper();
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003055}
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02003056
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003057/* verify ACC startup ramp+rotate feature */
3058testcase TC_si_acc_ramp_rotate() runs on test_CT {
3059 var template SystemInformationConfig sic := SystemInformationConfig_default;
3060 var SystemInformationType1 last_si1;
3061 var AccessControlClass acc;
3062 var ASP_RSL_Unitdata rx_rsl_ud;
3063 var uint8_t count;
3064 var uint8_t prev_count;
3065 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3066
3067 f_init(0, guard_timeout := 80.0);
3068
3069 f_bts_0_cfg(BSCVTY, {"rach access-control-class 4 barred",
3070 "access-control-class-rotate 0",
3071 "access-control-class-rotate-quantum 1",
3072 "access-control-class-ramping",
3073 "access-control-class-ramping-step-interval 5",
3074 "access-control-class-ramping-step-size 5"});
3075
3076 /* Init and get first sysinfo */
3077 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3078 last_si1 := g_system_information[0].si1;
3079 acc := last_si1.rach_control.acc;
3080 count := f_acc09_count_allowed(acc);
3081 /* Adm subset size was set to 0 above, so wait until all ACC are barred */
3082 while (count > 0) {
3083 last_si1 := f_recv_next_si1(0);
3084 acc := last_si1.rach_control.acc;
3085 count := f_acc09_count_allowed(acc);
3086 log("RSL: wait len()=0: GOT SI1 ACC len=", count, ": ", acc);
3087 }
3088
3089 /* Increase adm subset size, we should see ramping start up */
3090 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10"});
3091 prev_count := 0;
3092 while (true) {
3093 last_si1 := f_recv_next_si1(0);
3094 acc := last_si1.rach_control.acc;
3095 count := f_acc09_count_allowed(acc);
3096 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3097
3098 if (prev_count > count) {
3099 setverdict(fail, "ACC allowed count dropped while expecting grow: ", prev_count, " -> ", count);
3100 break;
3101 }
3102
3103 if (count == 9) {
3104 break; /* Maximum reached (10 - 1 perm barred), done here */
3105 }
3106
3107 prev_count := count;
3108 }
3109
3110 setverdict(pass);
3111
3112 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3113 "rach access-control-class 4 allowed",
3114 "no access-control-class-ramping"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003115 f_shutdown_helper();
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003116}
3117
Harald Welte4003d112017-12-09 22:35:39 +01003118testcase TC_ctrl_msc_connection_status() runs on test_CT {
3119 var charstring ctrl_resp;
3120
Harald Welte89d42e82017-12-17 16:42:41 +01003121 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003122
3123 /* See https://osmocom.org/issues/2729 */
3124 f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003125 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01003126}
3127
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003128testcase TC_ctrl_msc0_connection_status() runs on test_CT {
3129 var charstring ctrl_resp;
3130
3131 f_init(1);
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003132
3133 f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003134 f_shutdown_helper();
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003135}
3136
Neels Hofmeyr0bc470d2021-08-21 13:37:13 +02003137/* Verify correct stats on the number of configured and connected MSCs */
3138private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
3139 g_pars := f_gen_test_hdlr_pars();
3140 var StatsDExpects expect := {
3141 { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
3142 { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
3143 };
3144 f_statsd_expect(expect);
3145}
3146
3147private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
3148{
3149 var MSC_ConnHdlr vc_conn;
3150
3151 f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
3152 f_sleep(1.0);
3153 vc_conn := f_start_handler(tc_fn);
3154 vc_conn.done;
3155
3156 /* Also verify stat exposed on CTRL interface */
3157 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
3158 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
3159
3160 f_shutdown_helper();
3161}
3162
3163/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
3164private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
3165 f_tc_stat_num_msc_connected_msc_connhdlr(1);
3166}
3167testcase TC_stat_num_msc_connected_1() runs on test_CT {
3168 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
3169}
3170
3171/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
3172private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
3173 f_tc_stat_num_msc_connected_msc_connhdlr(2);
3174}
3175testcase TC_stat_num_msc_connected_2() runs on test_CT {
3176 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
3177}
3178
3179/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
3180private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
3181 f_tc_stat_num_msc_connected_msc_connhdlr(3);
3182}
3183testcase TC_stat_num_msc_connected_3() runs on test_CT {
3184 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
3185}
3186
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003187/* Verify correct stats on the number of configured and connected MSCs */
3188private 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 +06003189 var integer num_trx_connected := 0;
3190 var integer num_trx_total := 0;
3191
3192 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3193 var integer trx_num := c_BtsParams[i].trx_num;
3194 num_trx_total := num_trx_total + trx_num;
3195 if (i < expect_num_bts_connected) {
3196 num_trx_connected := num_trx_connected + trx_num;
3197 }
3198 }
3199
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003200 var StatsDExpects expect := {
3201 { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
3202 { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3203 { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003204 { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := num_trx_connected, max := num_trx_connected },
3205 { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := num_trx_total, max := num_trx_total }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003206 };
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003207
3208 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003209 f_statsd_expect(expect);
3210}
3211
3212private 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 +06003213 var integer num_trx_connected := 0;
3214 var integer num_trx_total := 0;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003215 var MSC_ConnHdlr vc_conn;
3216
3217 f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
3218 f_sleep(1.0);
3219 vc_conn := f_start_handler(tc_fn);
3220 vc_conn.done;
3221
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003222 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3223 var integer trx_num := c_BtsParams[i].trx_num;
3224 num_trx_total := num_trx_total + trx_num;
3225 if (i < nr_bts) {
3226 num_trx_connected := num_trx_connected + trx_num;
3227 }
3228 }
3229
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003230 /* Also verify stat exposed on CTRL interface */
3231 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
3232 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 +06003233 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(num_trx_connected));
3234 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 +02003235
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003236 /* Verify rf_states exposed on CTRL interface */
3237 var charstring expect_net_rf_states := "";
3238 for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003239 var charstring expect_bts_rf_states := "";
3240
3241 for (var integer j := 0; j < c_BtsParams[i].trx_num; j := j + 1) {
3242 expect_bts_rf_states := expect_bts_rf_states &
3243 int2str(i) & "," & int2str(j) & ",";
3244 if (i < NUM_BTS) {
3245 /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
3246 expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
3247 } else {
3248 /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
3249 expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
3250 }
3251 /* The RF policy is still global in osmo-bsc, i.e. always "on" */
3252 expect_bts_rf_states := expect_bts_rf_states & "on,";
3253 if (i < nr_bts) {
3254 /* For BTS where RSL is connected, the RSL state will be "up" */
3255 expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
3256 } else {
3257 expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
3258 }
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003259 }
3260
3261 f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
3262 expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
3263 }
3264 f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
3265
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003266 f_shutdown_helper();
3267}
3268
3269/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
3270private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
3271 f_tc_stat_num_bts_connected_msc_connhdlr(1);
3272}
3273testcase TC_stat_num_bts_connected_1() runs on test_CT {
3274 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
3275}
3276
3277/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
3278private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
3279 f_tc_stat_num_bts_connected_msc_connhdlr(2);
3280}
3281testcase TC_stat_num_bts_connected_2() runs on test_CT {
3282 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
3283}
3284
3285/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
3286private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
3287 f_tc_stat_num_bts_connected_msc_connhdlr(3);
3288}
3289testcase TC_stat_num_bts_connected_3() runs on test_CT {
3290 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
3291}
3292
Harald Welte4003d112017-12-09 22:35:39 +01003293testcase TC_ctrl() runs on test_CT {
3294 var charstring ctrl_resp;
3295
Harald Welte89d42e82017-12-17 16:42:41 +01003296 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003297
3298 /* all below values must match the osmo-bsc.cfg config file used */
3299
Harald Welte6a129692018-03-17 17:30:14 +01003300 f_ctrl_get_exp(IPA_CTRL, "mcc", "001");
3301 f_ctrl_get_exp(IPA_CTRL, "mnc", "01");
Oliver Smith75aa0202019-08-19 14:17:50 +02003302 f_ctrl_get_exp(IPA_CTRL, "number-of-bts", "4");
Harald Welte4003d112017-12-09 22:35:39 +01003303
3304 var integer bts_nr := 0;
3305 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "location-area-code", "1");
3306 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "cell-identity", "0");
3307 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "oml-connection-state", "connected");
3308 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "gprs-mode", "gprs");
3309 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "rf_state", "operational,unlocked,on");
3310 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "arfcn", "871");
3311 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "max-power-reduction", "20");
3312
3313 var integer uptime := str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime"));
3314 f_sleep(2.0);
3315 if (str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime")) < uptime+1) {
3316 setverdict(fail, "oml-uptime not incrementing as expected");
3317 }
3318 /* TODO: Disconnect RSL, imply that OML is disconnected and check for uptime zero? */
3319
3320 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
3321
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003322 f_shutdown_helper();
Harald Welte96c94412017-12-09 03:12:45 +01003323}
3324
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003325/* Verify that Upon receival of SET "location", BSC forwards a TRAP
3326 "location-state" over the SCCPlite IPA conn */
3327testcase TC_ctrl_location() runs on test_CT {
3328 var MSC_ConnHdlr vc_conn;
3329 var integer bts_nr := 0;
3330
3331 f_init(1, true);
3332 f_sleep(1.0);
3333
3334 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234567,fix3d,0.340000,0.560000,0.780000");
3335 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3336 "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
3337
3338 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "1");
3339 f_sleep(2.0);
3340
3341 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234888,fix3d,0.350000,0.570000,0.790000");
3342 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3343 "1234888,fix3d,0.350000,0.570000,0.790000,operational,locked,off,001,01");
3344
3345 /* should match the one from config */
3346 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
3347
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003348 f_shutdown_helper();
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003349}
3350
Harald Welte6f521d82017-12-11 19:52:02 +01003351
3352/***********************************************************************
3353 * Paging Testing
3354 ***********************************************************************/
3355
3356type record Cell_Identity {
3357 GsmMcc mcc,
3358 GsmMnc mnc,
3359 GsmLac lac,
3360 GsmCellId ci
3361};
Harald Welte24135bd2018-03-17 19:27:53 +01003362private const Cell_Identity cid := { '001'H, '01'H, 1, 0 };
Stefan Sperling049a86e2018-03-20 15:51:00 +01003363private const Cell_Identity unknown_cid := { '678'H, 'f90'H, 1, 0 };
Harald Welte6f521d82017-12-11 19:52:02 +01003364
Harald Welte5d1a2202017-12-13 19:51:29 +01003365type set of integer BtsIdList;
3366
3367private function f_bts_in_list(integer bts_id, BtsIdList bts_ids) return boolean {
3368 for (var integer j := 0; j < sizeof(bts_ids); j := j + 1) {
3369 if (bts_id == bts_ids[j]) {
3370 return true;
3371 }
3372 }
3373 return false;
3374}
Harald Welte6f521d82017-12-11 19:52:02 +01003375
3376/* core paging test helper function; used by most paging test cases */
3377private function f_pageing_helper(hexstring imsi,
3378 template BSSMAP_FIELD_CellIdentificationList cid_list,
Harald Welte5d1a2202017-12-13 19:51:29 +01003379 BtsIdList bts_ids := { 0 },
Harald Welte6f521d82017-12-11 19:52:02 +01003380 template RSL_ChanNeeded rsl_chneed := omit,
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003381 template (omit) OCT4 tmsi := omit) runs on test_CT
Harald Welte6f521d82017-12-11 19:52:02 +01003382{
3383 var template BSSMAP_IE_ChannelNeeded bssmap_chneed;
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003384 var template MobileIdentityV mi;
Harald Welte6f521d82017-12-11 19:52:02 +01003385 var RSL_Message rx_rsl;
3386 var integer paging_group := hex2int(imsi[lengthof(imsi)-1]);
Harald Welte5d1a2202017-12-13 19:51:29 +01003387 var integer i;
Harald Welte6f521d82017-12-11 19:52:02 +01003388
3389 f_init();
Harald Welte6f521d82017-12-11 19:52:02 +01003390
3391 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Harald Weltec3068592018-03-17 19:55:31 +01003392 for (i := 0; i < NUM_BTS; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003393 IPA_RSL[i][0].clear;
Harald Welte5d1a2202017-12-13 19:51:29 +01003394 }
Harald Welte6f521d82017-12-11 19:52:02 +01003395
3396 if (isvalue(rsl_chneed)) {
3397 /* The values of 08.08 3.2.2.36 and 08.58 9.3.40 are luckily identical */
3398 bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
3399 } else {
3400 bssmap_chneed := omit;
3401 }
3402
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003403 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
3404 ts_BSSMAP_Paging(imsi, cid_list, tmsi, bssmap_chneed)));
Harald Welte6f521d82017-12-11 19:52:02 +01003405
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003406 if (not istemplatekind(tmsi, "omit")) {
3407 mi := t_MI_TMSI(tmsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003408 } else {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003409 mi := tr_MI_IMSI(imsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003410 }
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003411
Harald Welte5d1a2202017-12-13 19:51:29 +01003412 for (i := 0; i < sizeof(bts_ids); i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003413 rx_rsl := f_exp_ipa_rx(tr_RSL_PAGING_CMD(mi), idx := {bts_ids[i], 0});
Harald Welte5d1a2202017-12-13 19:51:29 +01003414 /* check channel type, paging group */
3415 if (rx_rsl.ies[1].body.paging_group != paging_group) {
3416 setverdict(fail, "Paging for wrong paging group");
3417 }
3418 if (ispresent(rsl_chneed) and
3419 rx_rsl.ies[3].body.chan_needed.chan_needed != valueof(rsl_chneed)) {
3420 setverdict(fail, "RSL Channel Needed != BSSMAP Channel Needed");
3421 }
Harald Welte6f521d82017-12-11 19:52:02 +01003422 }
Harald Welte2fccd982018-01-31 15:48:19 +01003423 f_sleep(2.0);
Harald Welte5d1a2202017-12-13 19:51:29 +01003424 /* do a quick check on all not-included BTSs if they received paging */
3425 for (i := 0; i < NUM_BTS; i := i + 1) {
3426 timer T := 0.1;
3427 if (f_bts_in_list(i, bts_ids)) {
3428 continue;
3429 }
3430 T.start;
3431 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003432 [] IPA_RSL[i][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003433 setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
3434 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003435 [] IPA_RSL[i][0].receive { repeat; }
Harald Welte5d1a2202017-12-13 19:51:29 +01003436 [] T.timeout { }
3437 }
Harald Welte6f521d82017-12-11 19:52:02 +01003438 }
3439
3440 setverdict(pass);
3441}
3442
Harald Welte5d1a2202017-12-13 19:51:29 +01003443const BtsIdList c_BtsId_all := { 0, 1, 2 };
Harald Welte751d3eb2018-01-31 15:51:06 +01003444const BtsIdList c_BtsId_none := { };
Harald Welte5d1a2202017-12-13 19:51:29 +01003445const BtsIdList c_BtsId_LAC1 := { 0, 1 };
3446const BtsIdList c_BtsId_LAC2 := { 2 };
3447
Harald Welte6f521d82017-12-11 19:52:02 +01003448/* PAGING by IMSI + TMSI */
3449testcase TC_paging_imsi_nochan() runs on test_CT {
3450 var BSSMAP_FIELD_CellIdentificationList cid_list;
3451 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Philipp Maier8c04b0a2018-02-23 13:48:48 +01003452 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, omit);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003453 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003454}
3455
3456/* PAGING by IMSI + TMSI */
3457testcase TC_paging_tmsi_nochan() runs on test_CT {
3458 var BSSMAP_FIELD_CellIdentificationList cid_list;
3459 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003460 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, 'A1B2C301'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003461 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003462}
3463
3464/* Paging with different "channel needed' values */
3465testcase TC_paging_tmsi_any() runs on test_CT {
3466 var BSSMAP_FIELD_CellIdentificationList cid_list;
3467 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003468 f_pageing_helper('001010100000002'H, cid_list, c_BtsId_all, RSL_CHANNEED_ANY, 'A1B2C302'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003469 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003470}
3471testcase TC_paging_tmsi_sdcch() runs on test_CT {
3472 var BSSMAP_FIELD_CellIdentificationList cid_list;
3473 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003474 f_pageing_helper('001010100000003'H, cid_list, c_BtsId_all, RSL_CHANNEED_SDCCH, 'A1B2C303'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003475 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003476}
3477testcase TC_paging_tmsi_tch_f() runs on test_CT {
3478 var BSSMAP_FIELD_CellIdentificationList cid_list;
3479 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003480 f_pageing_helper('001010000000004'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_F, 'A1B2C304'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003481 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003482}
3483testcase TC_paging_tmsi_tch_hf() runs on test_CT {
3484 var BSSMAP_FIELD_CellIdentificationList cid_list;
3485 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003486 f_pageing_helper('001010000000005'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_ForH, 'A1B2C305'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003487 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003488}
3489
3490/* Paging by CGI */
3491testcase TC_paging_imsi_nochan_cgi() runs on test_CT {
3492 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3493 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(cid.mcc, cid.mnc, cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003494 f_pageing_helper('001010000000006'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003495 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003496}
3497
3498/* Paging by LAC+CI */
3499testcase TC_paging_imsi_nochan_lac_ci() runs on test_CT {
3500 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3501 cid_list := { cIl_LAC_CI := { ts_BSSMAP_CI_LAC_CI(cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003502 f_pageing_helper('001010000000007'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003503 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003504}
3505
3506/* Paging by CI */
3507testcase TC_paging_imsi_nochan_ci() runs on test_CT {
3508 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3509 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003510 f_pageing_helper('001010000000008'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003511 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003512}
3513
3514/* Paging by LAI */
3515testcase TC_paging_imsi_nochan_lai() runs on test_CT {
3516 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3517 cid_list := { cIl_LAI := { ts_BSSMAP_CI_LAI(cid.mcc, cid.mnc, cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003518 f_pageing_helper('001010000000009'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003519 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003520}
3521
3522/* Paging by LAC */
3523testcase TC_paging_imsi_nochan_lac() runs on test_CT {
3524 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3525 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003526 f_pageing_helper('001010000000010'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003527 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003528}
3529
3530/* Paging by "all in BSS" */
3531testcase TC_paging_imsi_nochan_all() runs on test_CT {
3532 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3533 cid_list := { cIl_allInBSS := ''O };
Harald Welte5d1a2202017-12-13 19:51:29 +01003534 f_pageing_helper('001010000000011'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003535 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003536}
3537
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003538/* Paging by PLMN+LAC+RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003539testcase TC_paging_imsi_nochan_plmn_lac_rnc() runs on test_CT {
3540 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3541 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 +01003542 f_pageing_helper('001010000000012'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003543 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003544}
Harald Welte6f521d82017-12-11 19:52:02 +01003545
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003546/* Paging by RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003547testcase TC_paging_imsi_nochan_rnc() runs on test_CT {
3548 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3549 cid_list := { cIl_RNC := { int2oct(13, 2) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003550 f_pageing_helper('001010000000013'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003551 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003552}
3553
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003554/* Paging by LAC+RNC; We do not implement; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003555testcase TC_paging_imsi_nochan_lac_rnc() runs on test_CT {
3556 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3557 cid_list := { cIl_LAC_RNC := { ts_BSSMAP_CI_LAC_RNC(cid.lac, 14) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003558 f_pageing_helper('001010000000014'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003559 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003560}
3561
Harald Welte6f521d82017-12-11 19:52:02 +01003562/* Paging on multiple cells (multiple entries in list): Verify all of them page */
Harald Welte751d3eb2018-01-31 15:51:06 +01003563testcase TC_paging_imsi_nochan_lacs() runs on test_CT {
3564 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3565 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(1), ts_BSSMAP_CI_LAC(2) } };
3566 f_pageing_helper('001010000000015'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003567 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003568}
3569
3570/* Paging on empty list: Verify none of them page */
3571testcase TC_paging_imsi_nochan_lacs_empty() runs on test_CT {
3572 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3573 cid_list := { cIl_LAC := { } };
3574 f_pageing_helper('001010000000016'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003575 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003576}
3577
Stefan Sperling049a86e2018-03-20 15:51:00 +01003578/* Paging by CGI with unknown MCC/MNC: Verify nothing is paged. */
3579testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
3580 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3581 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(unknown_cid.mcc, unknown_cid.mnc, unknown_cid.lac, unknown_cid.ci) } };
3582 f_pageing_helper('001010000000006'H, cid_list, c_BtsId_none);
3583 f_shutdown_helper();
3584}
3585
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +01003586/* Send paging response containing invalid (wrongly formatted) MobileIdentity IE. */
3587testcase TC_paging_imsi_nochan_ci_resp_invalid_mi() runs on test_CT {
3588 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3589 var BSSAP_N_CONNECT_ind rx_c_ind;
3590 var DchanTuple dt;
3591 var octetstring rr_pag_resp := '06270003535992617965720000'O;
3592 /* { 06 27 } is { GSM48_PDISC_RR, GSM48_MT_RR_PAG_RESP }
3593 * see 3GPP TS 44.018, table 9.1.25.1
3594 * { 00 } or { 01 } is CKSN + Spare Half Octet, not important
3595 * { 03 53 59 92 } is Mobile Station Classmark
3596 * { 61 79 65 72 00 00 } is the invalid Mobile Identity IE (3GPP TS 24.008, 10.5.1.4),
3597 * Length is 0x61 (97 in decimal).
3598 */
3599
3600 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
3601 f_pageing_helper('001010000000008'H, cid_list, { 0 });
3602
3603 /* Send CHAN RQD and wait for allocation; acknowledge it */
3604 dt.rsl_chan_nr := f_chreq_act_ack();
3605 dt.idx := {0, 0};
3606
3607 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
3608 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), rr_pag_resp));
3609
3610 /* Expevct a CR with a matching Paging response on the A-Interface */
3611 timer T := 5.0;
3612 T.start;
3613 alt {
3614 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
3615 setverdict(pass);
3616 dt.sccp_conn_id := rx_c_ind.connectionId;
3617 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
3618 }
3619 [] BSSAP.receive {
3620 setverdict(fail, "Received unexpected message on A-Interface!");
3621 }
3622 [] T.timeout {
3623 setverdict(fail, "Received nothing on A-Interface!");
3624 }
3625 }
3626
3627 f_perform_clear_test_ct(dt);
3628 f_shutdown_helper();
3629}
3630
Harald Welte6f521d82017-12-11 19:52:02 +01003631/* Verify paging retransmission interval + count */
3632/* Verify paging stops after channel establishment */
Harald Welte6f521d82017-12-11 19:52:02 +01003633/* Test behavior under paging overload */
Harald Welteae026692017-12-09 01:03:01 +01003634
Harald Weltee65d40e2017-12-13 00:09:06 +01003635/* Verify PCH load */
3636testcase TC_paging_imsi_load() runs on test_CT {
3637 var BSSMAP_FIELD_CellIdentificationList cid_list;
3638 timer T := 4.0;
Harald Welte2caa1062018-03-17 18:19:05 +01003639 timer T_retrans := 1.0;
Harald Weltee65d40e2017-12-13 00:09:06 +01003640 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003641 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Weltee65d40e2017-12-13 00:09:06 +01003642
3643 /* tell BSC there is no paging space anymore */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003644 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte3b57ab52018-03-17 18:01:10 +01003645 f_sleep(0.2);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003646 IPA_RSL[0][0].clear;
Harald Weltee65d40e2017-12-13 00:09:06 +01003647
3648 /* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
3649 * there would be 8 retransmissions during 4 seconds */
3650 T.start;
Harald Welte2caa1062018-03-17 18:19:05 +01003651 T_retrans.start;
Harald Weltee65d40e2017-12-13 00:09:06 +01003652 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003653 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Weltee65d40e2017-12-13 00:09:06 +01003654 setverdict(fail, "Received PAGING after LOAD_IND(0)");
Daniel Willmannafce8662018-07-06 23:11:32 +02003655 mtc.stop;
Harald Weltee65d40e2017-12-13 00:09:06 +01003656 }
Harald Welte2caa1062018-03-17 18:19:05 +01003657 [] T_retrans.timeout {
3658 /* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003659 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte2caa1062018-03-17 18:19:05 +01003660 T_retrans.start;
3661 repeat;
3662 }
Harald Weltee65d40e2017-12-13 00:09:06 +01003663 [] T.timeout {
3664 setverdict(pass);
3665 }
3666 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003667
3668 f_shutdown_helper();
Harald Weltee65d40e2017-12-13 00:09:06 +01003669}
3670
Harald Welte235ebf12017-12-15 14:18:16 +01003671/* Verify Paging Counter */
Harald Welte1ff69992017-12-14 12:31:17 +01003672testcase TC_paging_counter() runs on test_CT {
3673 var BSSMAP_FIELD_CellIdentificationList cid_list;
3674 timer T := 4.0;
3675 var integer i;
3676 var integer paging_attempted_bsc;
3677 var integer paging_attempted_bts[NUM_BTS];
Oliver Smith8b343d32021-11-26 13:01:42 +01003678 var integer paging_expired_bsc;
Harald Welte1ff69992017-12-14 12:31:17 +01003679 var integer paging_expired_bts[NUM_BTS];
3680 cid_list := valueof(ts_BSSMAP_CIL_noCell);
3681
3682 f_init();
3683
3684 /* read counters before paging */
3685 paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003686 paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
Harald Welte1ff69992017-12-14 12:31:17 +01003687 for (i := 0; i < NUM_BTS; i := i+1) {
3688 paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
3689 paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
3690 }
3691
3692 f_pageing_helper('001230000000001'H, cid_list, c_BtsId_all);
3693
3694 /* expect the attempted pages on BSC and each BTSs to have incremented by one */
3695 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", paging_attempted_bsc+1);
3696 for (i := 0; i < NUM_BTS; i := i+1) {
3697 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted",
3698 paging_attempted_bts[i]+1);
3699 }
3700
3701 /* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
3702 f_sleep(12.0);
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003703 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
Harald Welte1ff69992017-12-14 12:31:17 +01003704 for (i := 0; i < NUM_BTS; i := i+1) {
3705 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
3706 paging_expired_bts[i]+1);
3707 }
Harald Welte1ff69992017-12-14 12:31:17 +01003708
Philipp Maier282ca4b2018-02-27 17:17:00 +01003709 f_shutdown_helper();
Harald Welte1ff69992017-12-14 12:31:17 +01003710}
3711
3712
Harald Welte10985002017-12-12 09:29:15 +01003713/* Verify paging stops after A-RESET */
3714testcase TC_paging_imsi_a_reset() runs on test_CT {
3715 var BSSMAP_FIELD_CellIdentificationList cid_list;
3716 timer T := 3.0;
3717 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003718 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Welte10985002017-12-12 09:29:15 +01003719
3720 /* Perform a BSSMAP Reset and wait for ACK */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003721 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 +01003722 alt {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003723 [] 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 +01003724 [] BSSAP.receive { repeat; }
3725 }
3726
Daniel Willmanncbef3982018-07-30 09:22:40 +02003727 /* Wait to avoid a possible race condition if a paging message is
3728 * received right before the reset ACK. */
3729 f_sleep(0.2);
3730
Harald Welte10985002017-12-12 09:29:15 +01003731 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Philipp Maier1e6b4422018-02-23 14:02:13 +01003732 for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003733 IPA_RSL[i][0].clear;
Philipp Maier1e6b4422018-02-23 14:02:13 +01003734 }
Harald Welte10985002017-12-12 09:29:15 +01003735
3736 /* Wait for 3 seconds if any more PAGING CMD are received on RSL */
3737 T.start;
3738 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003739 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte10985002017-12-12 09:29:15 +01003740 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003741 mtc.stop;
Harald Welte10985002017-12-12 09:29:15 +01003742 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003743 [] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003744 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003745 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003746 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003747 [] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003748 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003749 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003750 }
Harald Welte10985002017-12-12 09:29:15 +01003751 [] T.timeout {
3752 setverdict(pass);
3753 }
3754 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003755
3756 f_shutdown_helper();
Harald Welte10985002017-12-12 09:29:15 +01003757}
Harald Welteae026692017-12-09 01:03:01 +01003758
Philipp Maierf45824a2019-08-14 14:44:10 +02003759/* Verify how we handle unsolicited Paging Response. In case of an unsolicit
3760 * paging response we can not know which MSC is in charge, so we will blindly
3761 * pick the first configured MSC. This behavior is required in order to make
3762 * MT-CSFB calls working because in those cases the BSC can not know that the
3763 * MSC has already paged the subscriver via SGs. So any MT-CSFB call will look
3764 * like an unsolicited Paging Response to the MSC.
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003765 */
3766testcase TC_paging_resp_unsol() runs on test_CT {
3767
3768 f_init(1);
Philipp Maierf45824a2019-08-14 14:44:10 +02003769 timer T := 5.0;
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003770
3771 var BSSAP_N_CONNECT_ind rx_c_ind;
3772 var DchanTuple dt;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02003773 var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010008880018'H)));
Philipp Maierf45824a2019-08-14 14:44:10 +02003774 var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003775
3776 /* Send CHAN RQD and wait for allocation; acknowledge it */
3777 dt.rsl_chan_nr := f_chreq_act_ack();
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003778 dt.idx := {0, 0};
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003779
3780 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
Pau Espin Pedrole8a51012023-01-03 11:59:59 +01003781 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 +01003782
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003783
Philipp Maierf45824a2019-08-14 14:44:10 +02003784 /* Expevct a CR with a matching Paging response on the A-Interface */
3785 T.start;
3786 alt {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003787 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
Philipp Maierf45824a2019-08-14 14:44:10 +02003788 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003789 dt.sccp_conn_id := rx_c_ind.connectionId;
3790 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
Philipp Maierf45824a2019-08-14 14:44:10 +02003791 }
3792 [] BSSAP.receive {
3793 setverdict(fail, "Received unexpected message on A-Interface!");
3794 }
3795 [] T.timeout {
3796 setverdict(fail, "Received nothing on A-Interface!");
3797 }
3798 }
3799
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003800 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003801 f_shutdown_helper();
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003802}
3803
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003804/* Verify BSC can schedule N paging requests under one minute if BTS buffer is good enough */
3805function f_TC_paging_Nreq(integer num_subscribers, boolean send_pag_load_ind) runs on test_CT {
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003806 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003807 var Hexstrings imsis := {};
3808 var Booleans rx_paging_done := {};
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003809 var integer rx_paging_num := 0;
3810 var integer i;
3811 timer T_rx := 60.0;
3812 timer T_load_ind := 1.0;
3813
3814 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003815 imsis := imsis & {f_gen_imsi(i)};
3816 rx_paging_done := rx_paging_done & { false };
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003817 }
3818
3819 f_init(1, guard_timeout := 100.0);
3820
3821 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003822 IPA_RSL[0][0].clear;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003823 if (send_pag_load_ind) {
3824 /* Tell there's plenty of space at the BTS (UINT16_MAX): */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003825 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(65535));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003826 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003827
3828 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003829 /* Page on LAC-CI of BTS0: */
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003830 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 +02003831 ts_BSSMAP_Paging(imsis[i], valueof(ts_BSSMAP_CIL_LAC_CI({ts_BSSMAP_CI_LAC_CI(1, 0)})),
3832 omit, omit)));
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003833 }
3834
3835 T_rx.start;
3836 T_load_ind.start;
3837 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003838 [] 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 +02003839 var hexstring imsi := rx_rsl_ud.rsl.ies[2].body.ms_identity.mobileIdentityV.oddEvenInd_identity.imsi.digits;
3840 var hexstring imsi_suffix := substr(imsi, lengthof(imsi)-6, 6);
3841 var charstring imsi_str := hex2str(imsi_suffix);
3842 var integer imsi_idx := str2int(imsi_str);
3843 if (rx_paging_done[imsi_idx] == false) {
3844 rx_paging_done[imsi_idx] := true;
3845 rx_paging_num := rx_paging_num + 1;
Pau Espin Pedrolef7ef632022-04-25 13:34:57 +02003846 } else {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003847 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 +02003848 mtc.stop;
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003849 }
3850 if (rx_paging_num < num_subscribers) {
3851 repeat;
3852 }
3853 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003854 [] IPA_RSL[0][0].receive { repeat; }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003855 [] T_load_ind.timeout {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003856 log("[CCH Load Ind timer] received paging requests so far: ", rx_paging_num);
3857 if (send_pag_load_ind) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003858 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(40));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003859 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003860 T_load_ind.start;
3861 repeat;
3862 }
3863 [] T_rx.timeout {
3864 setverdict(fail, "Timeout expecting paging requests, so far ", rx_paging_num);
3865 mtc.stop;
3866 }
3867 }
3868
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003869 /* Drop OML connection to have all paging requests flushed: */
3870 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
3871
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003872 f_shutdown_helper();
3873}
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003874/* Verify BSC can schedule 500 paging requests under one minute if BTS buffer is good enough */
3875testcase TC_paging_500req() runs on test_CT {
3876 f_TC_paging_Nreq(500, true);
3877}
3878/* Same as TC_paging_500req, but without sending CCCH Load Indication, which
3879 * means BTS is always under CCH Load Threshold, aka capable of sending tons of requests.
3880 * Since No CCCH Load Ind, BSC uses a conservative estimation of BTS load, which
3881 * for current config yields ~8req/sec, so 480req/min maximum. */
3882testcase TC_paging_450req_no_paging_load_ind() runs on test_CT {
3883 f_TC_paging_Nreq(450, false);
3884}
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003885
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003886/* Test RSL link drop causes counter increment */
3887testcase TC_rsl_drop_counter() runs on test_CT {
3888 var integer rsl_fail;
3889
Harald Welte89d42e82017-12-17 16:42:41 +01003890 f_init(1);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003891
3892 rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
3893
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003894 f_ipa_rsl_stop(bts[0][0].rsl);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003895
3896 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
3897
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003898 f_shutdown_helper();
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003899}
3900
3901/* TODO: Test OML link drop causes counter increment */
3902
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003903/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
3904function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003905 var IPA_Client client;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003906 timer T := 10.0;
3907
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003908 client.id := "IPA-BTS0-TRX0-RSL";
3909 client.vc_IPA := IPA_Emulation_CT.create(client.id & "-IPA") alive;
3910 client.ccm_pars := c_IPA_default_ccm_pars;
3911 client.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
3912 client.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003913
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01003914 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003915
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003916 f_init_mgcp(0, "VirtMGW");
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003917
3918 /* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003919 map(client.vc_IPA:IPA_PORT, system:IPA);
3920 connect(client.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0][0]);
3921 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 +01003922
3923 /* wait for IPA OML link to connect and then disconnect */
3924 T.start;
3925 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003926 [] IPA_RSL[0][0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003927 T.stop;
3928 return true;
3929 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003930 [] IPA_RSL[0][0].receive { repeat }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003931 [] T.timeout {
Daniel Willmannafce8662018-07-06 23:11:32 +02003932 return false;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003933 }
3934 }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003935 return false;
3936}
3937
3938/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3939testcase TC_rsl_unknown_unit_id() runs on test_CT {
3940 if (f_ipa_unknown_unit_id(mp_bsc_rsl_port)) {
3941 setverdict(pass);
3942 } else {
3943 setverdict(fail, "Timeout RSL waiting for connection to close");
3944 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003945 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003946}
3947
3948
3949/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3950testcase TC_oml_unknown_unit_id() runs on test_CT {
3951 if (f_ipa_unknown_unit_id(mp_bsc_oml_port)) {
3952 setverdict(pass);
3953 } else {
3954 setverdict(fail, "Timeout OML waiting for connection to close");
3955 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003956 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003957}
3958
3959
Harald Weltec1a2fff2017-12-17 11:06:19 +01003960/***********************************************************************
Harald Welte6811d102019-04-14 22:23:14 +02003961 * "New world" test cases using RSL_Emulation + RAN_Emulation
Harald Weltec1a2fff2017-12-17 11:06:19 +01003962 ***********************************************************************/
3963
Harald Welte6811d102019-04-14 22:23:14 +02003964import from RAN_Emulation all;
Harald Welte47cd0e32020-08-21 12:39:11 +02003965import from BSSAP_LE_Emulation all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01003966import from RSL_Emulation all;
3967import from MSC_ConnectionHandler all;
3968
3969type function void_fn(charstring id) runs on MSC_ConnHdlr;
3970
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003971/* helper function to create and connect a MSC_ConnHdlr component
3972 * TODO: allow connecting to TRX1..N, not only TRX0 */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003973private 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 +02003974 connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003975 connect(vc_conn:RSL, bts[0][0].rsl.vc_RSL:CLIENT_PT);
3976 connect(vc_conn:RSL_PROC, bts[0][0].rsl.vc_RSL:RSL_PROC);
3977 if (isvalue(bts[1][0])) {
3978 connect(vc_conn:RSL1, bts[1][0].rsl.vc_RSL:CLIENT_PT);
3979 connect(vc_conn:RSL1_PROC, bts[1][0].rsl.vc_RSL:RSL_PROC);
Philipp Maier956a92f2018-02-16 10:58:07 +01003980 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003981 if (isvalue(bts[2][0])) {
3982 connect(vc_conn:RSL2, bts[2][0].rsl.vc_RSL:CLIENT_PT);
3983 connect(vc_conn:RSL2_PROC, bts[2][0].rsl.vc_RSL:RSL_PROC);
Neels Hofmeyr91401012019-07-11 00:42:35 +02003984 }
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003985 connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02003986 if (mp_enable_lcs_tests) {
3987 connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
3988 connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
3989 }
Daniel Willmannebdecc02020-08-12 15:30:17 +02003990 connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003991 connect(vc_conn:MGCP_PROC, vc_MGCP[mgwpool_idx]:MGCP_PROC);
3992 connect(vc_conn:MGCP, vc_MGCP[mgwpool_idx]:MGCP_CLIENT);
3993 connect(vc_conn:MGCP_MULTI, vc_MGCP[mgwpool_idx]:MGCP_CLIENT_MULTI);
Harald Welte336820c2018-05-31 20:34:52 +02003994}
3995
Neels Hofmeyrda436782021-07-20 22:09:06 +02003996function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
Harald Welte336820c2018-05-31 20:34:52 +02003997runs on test_CT return MSC_ConnHdlr {
3998 var charstring id := testcasename();
3999 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004000 var integer bssap_idx := 0;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004001 var integer mgwpool_idx := 0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004002 if (isvalue(pars)) {
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004003 var TestHdlrParams pars_val := valueof(pars);
4004 bssap_idx := pars_val.mscpool.bssap_idx;
4005 mgwpool_idx := pars_val.mgwpool_idx;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004006 }
Harald Welte336820c2018-05-31 20:34:52 +02004007 vc_conn := MSC_ConnHdlr.create(id);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004008 f_connect_handler(vc_conn, bssap_idx, mgwpool_idx);
Neels Hofmeyrda436782021-07-20 22:09:06 +02004009 return vc_conn;
4010}
4011
4012function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
4013runs on test_CT return MSC_ConnHdlr {
4014 var charstring id := testcasename();
Harald Weltea0630032018-03-20 21:09:55 +01004015 vc_conn.start(f_handler_init(fn, id, pars));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004016 return vc_conn;
4017}
4018
Neels Hofmeyrda436782021-07-20 22:09:06 +02004019function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
4020runs on test_CT return MSC_ConnHdlr {
4021 return f_start_handler_run(f_start_handler_create(pars), fn, pars);
4022}
4023
Harald Weltea0630032018-03-20 21:09:55 +01004024/* first function inside ConnHdlr component; sets g_pars + starts function */
4025private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
4026runs on MSC_ConnHdlr {
4027 if (isvalue(pars)) {
4028 g_pars := valueof(pars);
4029 }
4030 fn.apply(id);
4031}
4032
Oliver Smith26a3db72021-07-09 13:51:29 +02004033private function f_vty_encryption_a5(charstring options) runs on test_CT {
4034 f_vty_transceive(BSCVTY, "configure terminal");
4035 f_vty_transceive(BSCVTY, "network");
4036 f_vty_transceive(BSCVTY, "encryption a5 " & options);
4037 f_vty_transceive(BSCVTY, "exit");
4038 f_vty_transceive(BSCVTY, "exit");
4039}
4040
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004041const charstring VTY_A5_DEFAULT := "0 1 3";
4042
Oliver Smith26a3db72021-07-09 13:51:29 +02004043private function f_vty_encryption_a5_reset() runs on test_CT {
4044 /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004045 f_vty_encryption_a5(VTY_A5_DEFAULT);
Oliver Smith26a3db72021-07-09 13:51:29 +02004046}
4047
Harald Welte3c86ea02018-05-10 22:28:05 +02004048/* Establish signalling channel (non-assignment case) followed by cipher mode */
4049private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004050 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4051 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte3c86ea02018-05-10 22:28:05 +02004052 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Philipp Maier23000732018-05-18 11:25:37 +02004053 ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode := omit;
4054 ass_cmd.pdu.bssmap.assignmentRequest.aoIPTransportLayer := omit;
4055 exp_compl.pdu.bssmap.assignmentComplete.circuitIdentityCode := omit;
4056 exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
Harald Welte3c86ea02018-05-10 22:28:05 +02004057
Philipp Maier23000732018-05-18 11:25:37 +02004058 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004059 f_perform_clear();
Harald Welte3c86ea02018-05-10 22:28:05 +02004060}
4061testcase TC_ciph_mode_a5_0() runs on test_CT {
4062 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004063 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004064 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
4065
4066 f_init(1, true);
4067 f_sleep(1.0);
4068 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4069 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004070 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004071}
4072testcase TC_ciph_mode_a5_1() runs on test_CT {
4073 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004074 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004075 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
4076
4077 f_init(1, true);
4078 f_sleep(1.0);
4079 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4080 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004081 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004082}
Oliver Smith50b98122021-07-09 15:00:28 +02004083/* OS#4975: verify that A5/2 is preferred over A5/0 */
4084testcase TC_ciph_mode_a5_2_0() runs on test_CT {
4085 var MSC_ConnHdlr vc_conn;
4086 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4087
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004088 pars.encr := f_encr_params('05'O, '04'O); /* A5/0 and A5/2 (0x01|0x04)*/
Oliver Smith50b98122021-07-09 15:00:28 +02004089
4090 f_init(1, true);
4091 f_vty_encryption_a5("0 1 2 3");
4092 f_sleep(1.0);
4093 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4094 vc_conn.done;
4095 f_vty_encryption_a5_reset();
4096 f_shutdown_helper();
4097}
Oliver Smith1dff88d2021-07-09 08:45:51 +02004098/* OS#4975: verify that A5/1 is preferred over A5/2 */
4099testcase TC_ciph_mode_a5_2_1() runs on test_CT {
4100 var MSC_ConnHdlr vc_conn;
4101 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4102
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004103 pars.encr := f_encr_params('06'O, '02'O); /* A5/1 and A5/2 (0x02|0x04)*/
Oliver Smith1dff88d2021-07-09 08:45:51 +02004104
4105 f_init(1, true);
4106 f_vty_encryption_a5("1 2");
4107 f_sleep(1.0);
4108 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4109 vc_conn.done;
4110 f_vty_encryption_a5_reset();
4111 f_shutdown_helper();
4112}
Harald Welte3c86ea02018-05-10 22:28:05 +02004113testcase TC_ciph_mode_a5_3() runs on test_CT {
4114 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004115 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004116 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
4117
4118 f_init(1, true);
4119 f_sleep(1.0);
4120 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4121 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004122 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004123}
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004124/* Establish a Signalling channel with A5/4 encryption. */
4125testcase TC_ciph_mode_a5_4() runs on test_CT {
4126 var MSC_ConnHdlr vc_conn;
4127 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4128 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Harald Welte3c86ea02018-05-10 22:28:05 +02004129
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004130 f_init(1, true);
Oliver Smith26a3db72021-07-09 13:51:29 +02004131 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004132 f_sleep(1.0);
4133 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4134 vc_conn.done;
Oliver Smith26a3db72021-07-09 13:51:29 +02004135 f_vty_encryption_a5_reset();
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004136 f_shutdown_helper();
4137}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004138/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
4139private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
4140 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4141 var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
4142 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4143 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4144
4145 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004146 f_perform_clear();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004147}
4148testcase TC_assignment_aoip_tla_v6() runs on test_CT {
4149 var MSC_ConnHdlr vc_conn;
4150 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4151
4152 f_init(1, true);
4153 f_sleep(1.0);
4154 vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
4155 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004156 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004157}
4158
Harald Welte3c86ea02018-05-10 22:28:05 +02004159
4160/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
Harald Welte651fcdc2018-05-10 20:23:16 +02004161private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004162 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4163 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004164
Harald Welte552620d2017-12-16 23:21:36 +01004165 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4166 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte73cd2712017-12-17 00:44:52 +01004167
Harald Weltea0630032018-03-20 21:09:55 +01004168 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004169 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004170}
Harald Welte552620d2017-12-16 23:21:36 +01004171testcase TC_assignment_fr_a5_0() runs on test_CT {
4172 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004173 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004174 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
Harald Welte552620d2017-12-16 23:21:36 +01004175
Harald Welte89d42e82017-12-17 16:42:41 +01004176 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004177 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004178 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004179 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004180 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004181}
Harald Welte552620d2017-12-16 23:21:36 +01004182testcase TC_assignment_fr_a5_1() runs on test_CT {
Harald Weltec1a2fff2017-12-17 11:06:19 +01004183 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004184 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004185 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004186
Harald Welte89d42e82017-12-17 16:42:41 +01004187 f_init(1, true);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004188 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004189 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4190 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004191 f_shutdown_helper();
Harald Welte651fcdc2018-05-10 20:23:16 +02004192}
4193testcase TC_assignment_fr_a5_3() runs on test_CT {
4194 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004195 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004196 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004197
Harald Welte651fcdc2018-05-10 20:23:16 +02004198 f_init(1, true);
4199 f_sleep(1.0);
4200 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004201 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004202 f_shutdown_helper();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004203}
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004204/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
4205testcase TC_assignment_fr_a5_4() runs on test_CT {
4206 var MSC_ConnHdlr vc_conn;
4207 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4208 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
4209
4210 f_init(1, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02004211 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004212 f_sleep(1.0);
4213 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4214 vc_conn.done;
Oliver Smith7eabd312021-07-12 14:18:56 +02004215 f_vty_encryption_a5_reset();
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004216 f_shutdown_helper();
4217}
Harald Weltec1a2fff2017-12-17 11:06:19 +01004218
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +02004219/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
4220testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
4221 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4222 var MSC_ConnHdlr vc_conn;
4223
4224 f_init(1, true);
4225 f_sleep(1.0);
4226
4227 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
4228 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
4229 vc_conn.done;
4230 f_shutdown_helper();
4231}
4232
Harald Welte552620d2017-12-16 23:21:36 +01004233/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
4234private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004235 g_pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004236 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02004237 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004238
4239 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02004240 /* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
4241
Harald Weltea0630032018-03-20 21:09:55 +01004242 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004243 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004244}
Harald Welte552620d2017-12-16 23:21:36 +01004245testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
4246 var MSC_ConnHdlr vc_conn;
4247
Harald Welte89d42e82017-12-17 16:42:41 +01004248 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004249 f_sleep(1.0);
4250
Harald Welte8863fa12018-05-10 20:15:27 +02004251 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
Harald Welte552620d2017-12-16 23:21:36 +01004252 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004253 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004254}
4255
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004256private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
4257 var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
4258 var PDU_BSSAP exp_ass_req := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004259
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004260 exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4261 exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4262
4263 /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
4264
4265 var BSSMAP_FIELD_CodecType codecType;
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004266
4267 codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
4268 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
4269
4270 f_create_chan_and_exp();
4271 /* we should now have a COMPL_L3 at the MSC */
4272
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004273 /* Start ciphering, expect Cipher Mode Reject */
Neels Hofmeyr6c388f22021-06-11 02:36:56 +02004274 f_cipher_mode(g_pars.encr, exp_fail := true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004275 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004276}
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004277testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
4278 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004279 var MSC_ConnHdlr vc_conn;
4280
Harald Welte89d42e82017-12-17 16:42:41 +01004281 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004282 f_sleep(1.0);
4283
Neels Hofmeyr0588cad2021-06-11 01:38:18 +02004284 pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004285 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004286 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004287 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004288}
4289
4290
Harald Welte4532e0a2017-12-23 02:05:44 +01004291private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004292 g_pars := f_gen_test_hdlr_pars();
Harald Welte4532e0a2017-12-23 02:05:44 +01004293 var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
Philipp Maier48604732018-10-09 15:00:37 +02004294 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte4532e0a2017-12-23 02:05:44 +01004295 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004296
4297 f_statsd_reset();
Harald Weltea0630032018-03-20 21:09:55 +01004298 f_establish_fully(ass_cmd, exp_compl);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004299
4300 var StatsDExpects expect := {
Daniel Willmannc5398f72020-09-21 10:41:35 +02004301 { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
4302 { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
Daniel Willmannebdecc02020-08-12 15:30:17 +02004303 { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
4304 { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
4305 };
4306 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004307 f_perform_clear();
Harald Welte4532e0a2017-12-23 02:05:44 +01004308}
4309
4310testcase TC_assignment_sign() runs on test_CT {
4311 var MSC_ConnHdlr vc_conn;
4312
4313 f_init(1, true);
4314 f_sleep(1.0);
4315
Harald Welte8863fa12018-05-10 20:15:27 +02004316 vc_conn := f_start_handler(refers(f_tc_assignment_sign));
Harald Welte4532e0a2017-12-23 02:05:44 +01004317 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004318 f_shutdown_helper();
Harald Welte4532e0a2017-12-23 02:05:44 +01004319}
4320
Harald Welte60aa5762018-03-21 19:33:13 +01004321/***********************************************************************
4322 * Codec (list) testing
4323 ***********************************************************************/
4324
4325/* check if the given rsl_mode is compatible with the a_elem */
4326private function f_match_codec(BSSMAP_FIELD_CodecElement a_elem, RSL_IE_ChannelMode rsl_mode)
4327return boolean {
4328 select (a_elem.codecType) {
4329 case (GSM_FR) {
4330 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1))) {
4331 return true;
4332 }
4333 }
4334 case (GSM_HR) {
4335 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1))) {
4336 return true;
4337 }
4338 }
4339 case (GSM_EFR) {
4340 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2))) {
4341 return true;
4342 }
4343 }
4344 case (FR_AMR) {
4345 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3))) {
4346 return true;
4347 }
4348 }
4349 case (HR_AMR) {
4350 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3))) {
4351 return true;
4352 }
4353 }
4354 case else { }
4355 }
4356 return false;
4357}
4358
4359/* check if the given rsl_mode is compatible with the a_list */
4360private function f_match_codecs(BSSMAP_IE_SpeechCodecList a_list, RSL_IE_ChannelMode rsl_mode)
4361return boolean {
4362 for (var integer i := 0; i < sizeof(a_list); i := i+1) {
4363 if (f_match_codec(a_list.codecElements[i], rsl_mode)) {
4364 return true;
4365 }
4366 }
4367 return false;
4368}
4369
4370/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
Philipp Maier61f6b572018-07-06 14:03:38 +02004371function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
Harald Welte60aa5762018-03-21 19:33:13 +01004372return BSSMAP_IE_ChannelType {
4373 /* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
4374 var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
4375 select (a_elem.codecType) {
4376 case (GSM_FR) {
4377 ret.channelRateAndType := ChRate_TCHF;
4378 ret.speechId_DataIndicator := Spdi_TCHF_FR;
4379 }
4380 case (GSM_HR) {
4381 ret.channelRateAndType := ChRate_TCHH;
4382 ret.speechId_DataIndicator := Spdi_TCHH_HR;
4383 }
4384 case (GSM_EFR) {
4385 ret.channelRateAndType := ChRate_TCHF;
4386 ret.speechId_DataIndicator := Spdi_TCHF_EFR;
4387 }
4388 case (FR_AMR) {
4389 ret.channelRateAndType := ChRate_TCHF;
4390 ret.speechId_DataIndicator := Spdi_TCHF_AMR;
4391 }
4392 case (HR_AMR) {
4393 ret.channelRateAndType := ChRate_TCHH;
4394 ret.speechId_DataIndicator := Spdi_TCHH_AMR;
4395 }
4396 case else {
4397 setverdict(fail, "Unsupported codec ", a_elem);
Daniel Willmannafce8662018-07-06 23:11:32 +02004398 mtc.stop;
Harald Welte60aa5762018-03-21 19:33:13 +01004399 }
4400 }
4401 return ret;
4402}
4403
Harald Weltea63b9102018-03-22 20:36:16 +01004404private function f_rsl_chmod_tmpl_from_codec(BSSMAP_FIELD_CodecElement a_elem)
4405return template RSL_IE_Body {
4406 var template RSL_IE_Body mode_ie := {
4407 chan_mode := {
4408 len := ?,
4409 reserved := ?,
4410 dtx_d := ?,
4411 dtx_u := ?,
4412 spd_ind := RSL_SPDI_SPEECH,
4413 ch_rate_type := -,
Oliver Smith0033b122023-02-28 13:30:53 +01004414 u := { speech := - }
Harald Weltea63b9102018-03-22 20:36:16 +01004415 }
4416 }
4417
4418 select (a_elem.codecType) {
4419 case (GSM_FR) {
4420 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004421 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004422 }
4423 case (GSM_HR) {
4424 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004425 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004426 }
4427 case (GSM_EFR) {
4428 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004429 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM2;
Harald Weltea63b9102018-03-22 20:36:16 +01004430 }
4431 case (FR_AMR) {
4432 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004433 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004434 }
4435 case (HR_AMR) {
4436 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004437 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004438 }
4439 }
4440 return mode_ie;
4441}
4442
Harald Welte60aa5762018-03-21 19:33:13 +01004443type record CodecListTest {
4444 BSSMAP_IE_SpeechCodecList codec_list,
4445 charstring id
4446}
4447type record of CodecListTest CodecListTests
4448
4449private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004450 f_assignment_codec(id);
4451}
4452
4453private function f_assignment_codec(charstring id, boolean do_perform_clear := true) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02004454 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02004455 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welte60aa5762018-03-21 19:33:13 +01004456
4457 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004458 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte79f3f542018-05-25 20:02:37 +02004459 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4460 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
4461 g_pars.ass_codec_list.codecElements[0];
Philipp Maierd0e64b02019-03-13 14:15:23 +01004462 if (isvalue(g_pars.expect_mr_s0_s7)) {
4463 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
4464 g_pars.expect_mr_s0_s7;
4465 }
Harald Welte79f3f542018-05-25 20:02:37 +02004466 }
Harald Welte60aa5762018-03-21 19:33:13 +01004467 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4468 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
Harald Welte60aa5762018-03-21 19:33:13 +01004469 log("expecting ASS COMPL like this: ", exp_compl);
4470
4471 f_establish_fully(ass_cmd, exp_compl);
Harald Weltea63b9102018-03-22 20:36:16 +01004472
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004473 if (not g_pars.expect_channel_mode_modify) {
4474 /* Verify that the RSL-side activation actually matches our expectations */
4475 var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
Harald Weltea63b9102018-03-22 20:36:16 +01004476
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004477 var RSL_IE_Body mode_ie;
4478 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
4479 setverdict(fail, "Couldn't find CHAN_MODE IE");
Daniel Willmannafce8662018-07-06 23:11:32 +02004480 mtc.stop;
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004481 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004482 var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
4483 if (not match(mode_ie, t_mode_ie)) {
4484 log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
4485 setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004486 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004487
4488 var RSL_IE_Body mr_conf;
4489 if (g_pars.expect_mr_conf_ie != omit) {
4490 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
4491 setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
4492 mtc.stop;
4493 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004494 log("found RSL MR CONFIG IE: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004495
4496 if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
Vadim Yanitskiy8b189372022-09-14 17:31:17 +07004497 setverdict(fail, "RSL MR CONFIG IE does not match expectation. ",
4498 "Expected: ", g_pars.expect_mr_conf_ie, ", got: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004499 }
4500 } else {
4501 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
4502 log("found RSL MR CONFIG IE: ", mr_conf);
4503 setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
4504 mtc.stop;
4505 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004506 }
4507 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004508
4509 if (do_perform_clear) {
4510 f_perform_clear();
4511 }
Harald Welte60aa5762018-03-21 19:33:13 +01004512}
4513
Philipp Maierd0e64b02019-03-13 14:15:23 +01004514private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
4515
4516 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4517 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4518
4519 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004520 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maierd0e64b02019-03-13 14:15:23 +01004521 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4522 }
4523 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4524 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
4525 log("expecting ASS FAIL like this: ", exp_fail);
4526
4527 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004528 f_perform_clear();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004529}
4530
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004531const CounterNameVals counternames_bsc_bts_assignment := {
4532 { "assignment:attempted", 0 },
4533 { "assignment:completed", 0 },
4534 { "assignment:stopped", 0 },
4535 { "assignment:no_channel", 0 },
4536 { "assignment:timeout", 0 },
4537 { "assignment:failed", 0 },
4538 { "assignment:error", 0 }
4539};
4540
4541const CounterNameVals counternames_bts_assignment := {
4542 { "assignment:attempted_sign", 0 },
4543 { "assignment:attempted_speech", 0 },
4544 { "assignment:completed_sign", 0 },
4545 { "assignment:completed_speech", 0 },
4546 { "assignment:stopped_sign", 0 },
4547 { "assignment:stopped_speech", 0 },
4548 { "assignment:no_channel_sign", 0 },
4549 { "assignment:no_channel_speech", 0 },
4550 { "assignment:timeout_sign", 0 },
4551 { "assignment:timeout_speech", 0 },
4552 { "assignment:failed_sign", 0 },
4553 { "assignment:failed_speech", 0 },
4554 { "assignment:error_sign", 0 },
4555 { "assignment:error_speech", 0 }
4556};
4557
4558function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
4559 var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
4560 f_ctrs_bts_init(bts_count, bts_names);
4561 f_ctrs_bsc_init(counternames_bsc_bts_assignment);
4562}
4563
Harald Welte60aa5762018-03-21 19:33:13 +01004564testcase TC_assignment_codec_fr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004565 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004566 var MSC_ConnHdlr vc_conn;
4567
4568 f_init(1, true);
4569 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004570 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004571
4572 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004573 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004574 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004575
4576 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4577 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4578 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4579 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4580 f_ctrs_bts_verify();
4581
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004582 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004583}
4584
4585testcase TC_assignment_codec_hr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004586 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004587 var MSC_ConnHdlr vc_conn;
4588
4589 f_init(1, true);
4590 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004591 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004592
4593 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004594 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004595 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004596
4597 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4598 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4599 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4600 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4601 f_ctrs_bts_verify();
4602
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004603 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004604}
4605
4606testcase TC_assignment_codec_efr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004607 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004608 var MSC_ConnHdlr vc_conn;
4609
4610 f_init(1, true);
4611 f_sleep(1.0);
4612
4613 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004614 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004615 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004616 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004617}
4618
Philipp Maierd0e64b02019-03-13 14:15:23 +01004619/* Allow 5,90k only (current default config) */
4620private function f_allow_amr_rate_5_90k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004621 f_vty_cfg_msc(BSCVTY, 0, {
4622 "amr-config 12_2k forbidden",
4623 "amr-config 10_2k forbidden",
4624 "amr-config 7_95k forbidden",
4625 "amr-config 7_40k forbidden",
4626 "amr-config 6_70k forbidden",
4627 "amr-config 5_90k allowed",
4628 "amr-config 5_15k forbidden",
4629 "amr-config 4_75k forbidden"
4630 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004631}
4632
4633/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
4634 * ("Config-NB-Code = 1") */
4635private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004636 f_vty_cfg_msc(BSCVTY, 0, {
4637 "amr-config 12_2k allowed",
4638 "amr-config 10_2k forbidden",
4639 "amr-config 7_95k forbidden",
4640 "amr-config 7_40k allowed",
4641 "amr-config 6_70k forbidden",
4642 "amr-config 5_90k allowed",
4643 "amr-config 5_15k forbidden",
4644 "amr-config 4_75k allowed"
4645 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004646}
4647
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004648private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
4649 var charstring tch;
4650 if (fr) {
4651 tch := "tch-f";
4652 } else {
4653 tch := "tch-h";
4654 }
4655 f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
4656}
4657
4658/* Set the AMR start-mode for this TCH back to the default configuration. */
4659private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
4660 f_vty_amr_start_mode_set(fr, "auto");
4661}
4662
Harald Welte60aa5762018-03-21 19:33:13 +01004663testcase TC_assignment_codec_amr_f() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004664 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004665 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004666
4667 /* Note: This setups the codec configuration. The parameter payload in
4668 * mr_conf must be consistant with the parameter codecElements in pars
4669 * and also must match the amr-config in osmo-bsc.cfg! */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004670 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004671 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004672 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004673 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004674
Harald Welte60aa5762018-03-21 19:33:13 +01004675 f_init(1, true);
4676 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004677 f_vty_amr_start_mode_set(true, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004678 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004679
Harald Welte8863fa12018-05-10 20:15:27 +02004680 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004681 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004682
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004683 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4684 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4685 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4686 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4687 f_ctrs_bts_verify();
4688
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004689 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004690 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004691}
4692
4693testcase TC_assignment_codec_amr_h() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004694 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004695 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004696
4697 /* See note above */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004698 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004699 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004700 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004701 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004702
Harald Welte60aa5762018-03-21 19:33:13 +01004703 f_init(1, true);
4704 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004705 f_vty_amr_start_mode_set(false, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004706 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004707
Harald Welte8863fa12018-05-10 20:15:27 +02004708 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004709 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004710
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004711 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4712 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4713 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4714 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4715 f_ctrs_bts_verify();
4716
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004717 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004718 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004719}
4720
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004721/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
4722testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
4723 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4724 var MSC_ConnHdlr vc_conn;
4725
4726 f_init(1, true);
4727 f_sleep(1.0);
4728
4729 /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
4730 * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
4731 * expecting a Channel Mode Modify if the channel type is compatible. */
4732 f_disable_all_sdcch();
4733 f_disable_all_tch_h();
4734
4735 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4736 pars.expect_channel_mode_modify := true;
4737 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4738 vc_conn.done;
4739
4740 f_enable_all_sdcch();
4741 f_enable_all_tch();
4742 f_shutdown_helper();
4743}
4744
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004745/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
4746testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
4747 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4748 var MSC_ConnHdlr vc_conn;
4749
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004750 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4751 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
4752 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy36fe9582022-09-14 15:25:04 +07004753 pars.expect_mr_conf_ie := c_mr_conf_5_90;
4754 pars.expect_mr_conf_ie.multirate_cfg.icmi := false; /* expect ICMI=0, smod=00: */
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004755
4756 f_init(1, true);
4757 f_sleep(1.0);
4758
4759 /* First set nonzero start mode bits */
4760 f_vty_amr_start_mode_set(true, "4");
4761 /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
4762 * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
4763 * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
4764 f_vty_amr_start_mode_set(true, "auto");
4765
4766 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4767 vc_conn.done;
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004768
4769 /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
4770 f_vty_amr_start_mode_set(true, "1");
4771 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004772 f_shutdown_helper();
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004773}
4774
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004775function f_TC_assignment_codec_amr(boolean fr, RSL_IE_MultirateCfg mr_cfg,
4776 bitstring s8_s0, bitstring exp_s8_s0,
4777 charstring start_mode := "1")
Philipp Maierd0e64b02019-03-13 14:15:23 +01004778runs on test_CT {
4779
4780 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4781 var MSC_ConnHdlr vc_conn;
4782
Philipp Maierd0e64b02019-03-13 14:15:23 +01004783 if (fr) {
4784 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4785 } else {
4786 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4787 }
4788 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4789 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004790 pars.expect_mr_conf_ie := { multirate_cfg := mr_cfg };
Philipp Maierd0e64b02019-03-13 14:15:23 +01004791 pars.expect_mr_s0_s7 := exp_s8_s0;
4792
4793 f_init(1, true);
4794 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004795 f_vty_amr_start_mode_set(fr, start_mode);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004796 f_sleep(1.0);
4797
4798 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4799 vc_conn.done;
4800 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004801 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004802}
4803
4804function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
4805runs on test_CT {
4806
4807 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4808 var MSC_ConnHdlr vc_conn;
4809
4810 if (fr) {
4811 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4812 } else {
4813 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4814 }
4815 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4816 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4817
4818 f_init(1, true);
4819 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004820 f_vty_amr_start_mode_set(fr, "1");
Philipp Maierd0e64b02019-03-13 14:15:23 +01004821 f_sleep(1.0);
4822
4823 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
4824 vc_conn.done;
4825 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004826 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004827}
4828
Philipp Maierd0e64b02019-03-13 14:15:23 +01004829/* Set S1, we expect an AMR multirate configuration IE with all four rates
4830 * set. */
4831testcase TC_assignment_codec_amr_f_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004832 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4833 params := '20882208'O));
4834 f_TC_assignment_codec_amr(true, mr_cfg, '00000011'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004835 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004836}
4837
4838/* Set S1, we expect an AMR multirate configuration IE with the lower three
4839 * rates set. */
4840testcase TC_assignment_codec_amr_h_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004841 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4842 params := '208820'O));
4843 f_TC_assignment_codec_amr(false, mr_cfg, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004844 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004845}
4846
4847/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4848 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4849testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004850 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4851 params := '20882208'O));
4852 f_TC_assignment_codec_amr(true, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004853 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004854}
4855
4856/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4857 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4858testcase TC_assignment_codec_amr_h_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004859 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4860 params := '208820'O));
4861 f_TC_assignment_codec_amr(false, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004862 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004863}
4864
4865/* The following block of tests selects more and more rates until all four
4866 * possible rates are in the active set (full rate) */
4867testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004868 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4869 f_TC_assignment_codec_amr(true, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004870 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004871}
4872
4873testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004874 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4875 params := '2080'O));
4876 f_TC_assignment_codec_amr(true, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004877 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004878}
4879
4880testcase TC_assignment_codec_amr_f_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004881 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4882 params := '208820'O));
4883 f_TC_assignment_codec_amr(true, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004884 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004885}
4886
4887testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004888 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4889 params := '20882208'O));
4890 f_TC_assignment_codec_amr(true, mr_cfg, '10010101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004891 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004892}
4893
4894/* The following block of tests selects more and more rates until all three
4895 * possible rates are in the active set (half rate) */
4896testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004897 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4898 f_TC_assignment_codec_amr(false, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004899 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004900}
4901
4902testcase TC_assignment_codec_amr_h_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004903 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4904 params := '2080'O));
4905 f_TC_assignment_codec_amr(false, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004906 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004907}
4908
4909testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004910 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4911 params := '208820'O));
4912 f_TC_assignment_codec_amr(false, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004913 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004914}
4915
4916/* The following block tests what happens when the MSC does offer rate
4917 * configurations that are not supported by the BSC. Normally such situations
4918 * should not happen because the MSC gets informed by the BSC in advance via
4919 * the L3 COMPLETE message which rates are applicable. The MSC should not try
4920 * to offer rates that are not applicable anyway. */
4921
4922testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004923 /* Try to include 12,2k in into the active set even though the channel
4924 * is half rate only. The BSC is expected to remove the 12,0k */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004925 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4926 params := '208820'O));
4927 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004928 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004929}
4930
4931testcase TC_assignment_codec_amr_f_S01234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004932 /* See what happens when all rates are selected at once. Since then
4933 * Also S1 is selected, this setting will be prefered and we should
4934 * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004935 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4936 params := '20882208'O));
4937 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004938 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004939}
4940
4941testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004942 /* Same as above, but with S1 missing, the MSC is then expected to
4943 * select the currently supported rates, which are also 12.2k, 7,40k,
4944 * 5,90k, and 4,75k, into the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004945 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4946 params := '20882208'O));
4947 f_TC_assignment_codec_amr(true, mr_cfg, '11111101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004948 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004949}
4950
4951testcase TC_assignment_codec_amr_f_zero() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004952 /* Try to select no rates at all */
4953 f_TC_assignment_codec_amr_fail(true, '00000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004954 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004955}
4956
4957testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004958 /* Try to select only unsupported rates */
4959 f_TC_assignment_codec_amr_fail(true, '01101000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004960 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004961}
4962
4963testcase TC_assignment_codec_amr_h_S7() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004964 /* Try to select 12,2k for half rate */
4965 f_TC_assignment_codec_amr_fail(false, '10000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004966 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004967}
4968
Neels Hofmeyr21863562020-11-26 00:34:33 +00004969testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004970 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4971 codec_modes := '10010101'B,
4972 params := '20882208'O));
4973 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004974 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004975}
4976
4977testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004978 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4979 codec_modes := '00010101'B,
4980 params := '208820'O));
4981 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B,
Neels Hofmeyr21863562020-11-26 00:34:33 +00004982 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004983 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004984}
4985
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004986testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004987 /* "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 +07004988 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 3,
4989 codec_modes := '10010101'B,
4990 params := '20882208'O));
4991 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004992 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004993}
4994
4995testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004996 /* "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 +07004997 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 2,
4998 codec_modes := '00010101'B,
4999 params := '208820'O));
5000 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01005001 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00005002}
5003
Philipp Maierac09bfc2019-01-08 13:41:39 +01005004private function f_disable_all_tch_f() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005005 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 borken");
5006 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 borken");
5007 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 borken");
5008 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005009}
5010
5011private function f_disable_all_tch_h() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005012 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 borken");
5013 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005014}
5015
5016private function f_enable_all_tch() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005017 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 unused");
5018 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 unused");
5019 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 unused");
5020 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 unused");
5021 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 unused");
5022 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005023}
5024
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02005025private function f_disable_all_sdcch() runs on test_CT {
5026 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
5027 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
5028 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
5029 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
5030}
5031
5032private function f_enable_all_sdcch() runs on test_CT {
5033 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
5034 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
5035 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
5036 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
5037}
5038
Philipp Maierac09bfc2019-01-08 13:41:39 +01005039/* Allow HR only */
5040private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs on MSC_ConnHdlr {
5041 g_pars := f_gen_test_hdlr_pars();
5042 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5043 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5044 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5045 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5046 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5047 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5048 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005049 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005050}
5051
5052/* Allow FR only */
5053private function f_TC_assignment_codec_xr_exhausted_req_fr(charstring id) runs on MSC_ConnHdlr {
5054 g_pars := f_gen_test_hdlr_pars();
5055 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5056 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5057 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5058 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5059 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5060 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5061 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005062 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005063}
5064
5065/* Allow HR only (expect assignment failure) */
5066private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) runs on MSC_ConnHdlr {
5067 g_pars := f_gen_test_hdlr_pars();
5068 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5069 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5070 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5071 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5072 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5073 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5074 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005075 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005076}
5077
5078/* Allow FR only (expect assignment failure) */
5079private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) runs on MSC_ConnHdlr {
5080 g_pars := f_gen_test_hdlr_pars();
5081 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5082 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5083 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5084 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5085 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5086 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5087 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005088 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005089}
5090
5091/* Allow FR and HR, but prefer FR */
5092private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5093 g_pars := f_gen_test_hdlr_pars();
5094 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5095 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5096 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5097 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5098 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5099 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5100 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5101 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005102 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005103}
5104
5105/* Allow FR and HR, but prefer HR */
5106private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5107 g_pars := f_gen_test_hdlr_pars();
5108 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5109 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5110 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5111 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5112 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5113 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5114 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5115 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005116 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005117}
5118
5119/* Allow FR and HR, but prefer FR */
5120private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5121 g_pars := f_gen_test_hdlr_pars();
5122 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5123 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5124 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5125 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5126 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5127 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5128 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5129 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005130 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005131}
5132
5133/* Allow FR and HR, but prefer HR */
5134private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5135 g_pars := f_gen_test_hdlr_pars();
5136 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5137 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5138 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5139 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5140 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5141 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5142 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5143 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005144 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005145}
5146
5147/* Request a HR channel while all FR channels are exhausted, this is expected
5148 * to work without conflicts */
5149testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
5150 var MSC_ConnHdlr vc_conn;
5151 f_init(1, true);
5152 f_sleep(1.0);
5153 f_enable_all_tch();
5154 f_disable_all_tch_f();
5155 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
5156 vc_conn.done;
5157 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005158 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005159}
5160
5161/* Request a FR channel while all FR channels are exhausted, this is expected
5162 * to fail. */
5163testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
5164 var MSC_ConnHdlr vc_conn;
5165 f_init(1, true);
5166 f_sleep(1.0);
5167 f_enable_all_tch();
5168 f_disable_all_tch_f();
5169 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
5170 vc_conn.done;
5171 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005172 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005173}
5174
5175/* Request a FR (prefered) or alternatively a HR channel while all FR channels
5176 * are exhausted, this is expected to be resolved by selecting a HR channel. */
5177testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
5178 var MSC_ConnHdlr vc_conn;
5179 f_init(1, true);
5180 f_sleep(1.0);
5181 f_enable_all_tch();
5182 f_disable_all_tch_f();
5183 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
5184 vc_conn.done;
5185 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005186 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005187}
5188
5189/* Request a HR (prefered) or alternatively a FR channel while all FR channels
5190 * are exhausted, this is expected to work without conflicts. */
5191testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
5192 var MSC_ConnHdlr vc_conn;
5193 f_init(1, true);
5194 f_sleep(1.0);
5195 f_enable_all_tch();
5196 f_disable_all_tch_f();
5197 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
5198 vc_conn.done;
5199 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005200 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005201}
5202
5203/* Request a FR channel while all HR channels are exhausted, this is expected
5204 * to work without conflicts */
5205testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
5206 var MSC_ConnHdlr vc_conn;
5207 f_init(1, true);
5208 f_sleep(1.0);
5209 f_enable_all_tch();
5210 f_disable_all_tch_h();
5211 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
5212 vc_conn.done;
5213 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005214 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005215}
5216
5217/* Request a HR channel while all HR channels are exhausted, this is expected
5218 * to fail. */
5219testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
5220 var MSC_ConnHdlr vc_conn;
5221 f_init(1, true);
5222 f_sleep(1.0);
5223 f_enable_all_tch();
5224 f_disable_all_tch_h();
5225 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
5226 vc_conn.done;
5227 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005228 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005229}
5230
5231/* Request a HR (prefered) or alternatively a FR channel while all HR channels
5232 * are exhausted, this is expected to be resolved by selecting a FR channel. */
5233testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
5234 var MSC_ConnHdlr vc_conn;
5235 f_init(1, true);
5236 f_sleep(1.0);
5237 f_enable_all_tch();
5238 f_disable_all_tch_h();
5239 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
5240 vc_conn.done;
5241 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005242 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005243}
5244
5245/* Request a FR (prefered) or alternatively a HR channel while all HR channels
5246 * are exhausted, this is expected to work without conflicts. */
5247testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
5248 var MSC_ConnHdlr vc_conn;
5249 f_init(1, true);
5250 f_sleep(1.0);
5251 f_enable_all_tch();
5252 f_disable_all_tch_h();
5253 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
5254 vc_conn.done;
5255 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005256 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005257}
5258
5259/* Allow FR and HR, but prefer HR */
5260private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5261 g_pars := f_gen_test_hdlr_pars();
5262 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5263 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5264 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5265 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5266 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5267 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5268 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5269 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005270 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005271}
5272
5273/* Allow FR and HR, but prefer FR */
5274private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5275 g_pars := f_gen_test_hdlr_pars();
5276 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5277 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5278 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5279 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5280 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5281 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5282 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5283 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005284 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005285}
5286
5287/* Request a HR (prefered) or alternatively a FR channel, it is expected that
5288 * HR, which is the prefered type, is selected. */
5289testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
5290 var MSC_ConnHdlr vc_conn;
5291 f_init(1, true);
5292 f_sleep(1.0);
5293 f_enable_all_tch();
5294 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
5295 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005296 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005297}
5298
5299/* Request a FR (prefered) or alternatively a HR channel, it is expected that
5300 * FR, which is the prefered type, is selected. */
5301testcase TC_assignment_codec_req_fr_hr() runs on test_CT {
5302 var MSC_ConnHdlr vc_conn;
5303 f_init(1, true);
5304 f_sleep(1.0);
5305 f_enable_all_tch();
5306 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_fr_hr));
5307 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005308 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005309}
5310
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005311/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
5312private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
5313 g_pars := f_gen_test_hdlr_pars();
5314 g_pars.ra := '02'O; /* RA containing reason=LU */
5315
5316 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5317 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5318 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5319 var template uint3_t tsc := ?;
5320
5321 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5322 f_create_bssmap_exp(l3_enc);
5323 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5324 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5325
5326 /* we should now have a COMPL_L3 at the MSC */
5327 timer T := 10.0;
5328 T.start;
5329 alt {
5330 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5331 [] T.timeout {
5332 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5333 }
5334 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005335
5336 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005337}
5338testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
5339 var MSC_ConnHdlr vc_conn;
5340 f_init(1, true);
5341 f_sleep(1.0);
5342 f_disable_all_sdcch();
5343 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
5344 vc_conn.done;
5345 f_enable_all_sdcch();
5346 f_shutdown_helper();
5347}
5348
5349/* Request a signalling channel with all SDCCH exhausted, it is
5350 expected that no TCH will be selected for signalling and assigment will fail
5351 because it's dictated by VTY config */
5352testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
5353 var RSL_Message rsl_unused, rsl_msg;
5354 var GsmRrMessage rr;
5355 f_init(1, false);
5356 f_sleep(1.0);
5357 f_vty_allow_tch_for_signalling(false, 0);
5358 f_disable_all_sdcch();
5359
5360 /* RA containing reason=LU */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005361 f_ipa_tx(ts_RSL_CHAN_RQD('02'O, 2342));
5362 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005363 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
5364 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
5365 setverdict(fail, "Expected reject");
5366 }
5367
5368 f_vty_allow_tch_for_signalling(true, 0);
5369 f_enable_all_sdcch();
5370 f_shutdown_helper();
5371}
5372
5373/* Request a voice channel with all SDCCH exhausted, it is
5374 * expected that TCH channel will be allocated since the VTY option is only
5375 * aimed at signalling requests */
5376private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
5377 g_pars := f_gen_test_hdlr_pars();
5378 g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
5379
5380 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5381 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5382 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5383 var template uint3_t tsc := ?;
5384
5385 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5386 f_create_bssmap_exp(l3_enc);
5387 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5388 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5389
5390 /* we should now have a COMPL_L3 at the MSC */
5391 timer T := 10.0;
5392 T.start;
5393 alt {
5394 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5395 [] T.timeout {
5396 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5397 }
5398 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005399 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005400}
5401testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
5402 var MSC_ConnHdlr vc_conn;
5403 f_init(1, true);
5404 f_sleep(1.0);
5405 f_vty_allow_tch_for_signalling(false, 0);
5406 f_disable_all_sdcch();
5407
5408 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
5409 vc_conn.done;
5410
5411 f_vty_allow_tch_for_signalling(true, 0);
5412 f_enable_all_sdcch();
5413 f_shutdown_helper();
5414}
5415
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005416/* Test Osmux setup BSC<->MSC */
5417testcase TC_assignment_osmux_cn() runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005418 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5419 var MSC_ConnHdlr vc_conn;
5420
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005421 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5422 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5423 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiyb9bf00f2022-09-14 15:35:37 +07005424 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02005425 pars.use_osmux_cn := true;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005426
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02005427 g_osmux_enabled_cn := true;
5428 f_init(1, true);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005429 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005430 f_vty_amr_start_mode_set(false, "1");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005431
5432 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5433 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005434
5435 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01005436 f_shutdown_helper();
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005437}
5438
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005439/* Test Osmux setup BTS<->BSC */
5440testcase TC_assignment_osmux_bts() runs on test_CT {
5441 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5442 var MSC_ConnHdlr vc_conn;
5443
5444 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5445 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5446 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005447 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005448 pars.use_osmux_bts := true;
5449
5450 g_osmux_enabled_bts := true;
5451 f_init(1, true);
5452 f_sleep(1.0);
5453 f_vty_amr_start_mode_set(false, "1");
5454
5455 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5456 vc_conn.done;
5457
5458 f_vty_amr_start_mode_restore(false);
5459 f_shutdown_helper();
5460}
5461
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +02005462/* Test non-AMR codecs still work fine as RTP when Osmux is enabled BTS<->BSC<->MSC */
5463testcase TC_assignment_codec_hr_osmux_on() runs on test_CT {
5464 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5465 var MSC_ConnHdlr vc_conn;
5466
5467 g_osmux_enabled_cn := true;
5468 g_osmux_enabled_bts := true;
5469 f_init(1, true);
5470 f_sleep(1.0);
5471 f_ctrs_bsc_and_bts_assignment_init(1);
5472
5473 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5474 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5475 vc_conn.done;
5476
5477 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
5478 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
5479 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
5480 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
5481 f_ctrs_bts_verify();
5482
5483 f_shutdown_helper();
5484}
5485
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005486/* Test Osmux setup BTS<->BSC<->MSC */
5487testcase TC_assignment_osmux() runs on test_CT {
5488 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5489 var MSC_ConnHdlr vc_conn;
5490
5491 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5492 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5493 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005494 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005495 pars.use_osmux_cn := true;
5496 pars.use_osmux_bts := true;
5497
5498 g_osmux_enabled_cn := true;
5499 g_osmux_enabled_bts := true;
5500 f_init(1, true);
5501 f_sleep(1.0);
5502 f_vty_amr_start_mode_set(false, "1");
5503
5504 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5505 vc_conn.done;
5506
5507 f_vty_amr_start_mode_restore(false);
5508 f_shutdown_helper();
5509}
5510
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005511/* test the procedure of the MSC requesting a Classmark Update:
5512 * a) BSSMAP Classmark Request should result in RR CLASSMARK ENQUIRY,
5513 * b) L3 RR CLASSMARK CHANGE should result in BSSMAP CLASSMARK UPDATE */
Harald Welte898113b2018-01-31 18:32:21 +01005514private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005515 g_pars := f_gen_test_hdlr_pars();
5516
Harald Weltea0630032018-03-20 21:09:55 +01005517 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005518 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005519
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005520 BSSAP.send(ts_BSSMAP_ClassmarkRequest);
5521 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
5522
Harald Welte898113b2018-01-31 18:32:21 +01005523 f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
5524 BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
5525 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005526
5527 f_perform_clear();
Harald Welte898113b2018-01-31 18:32:21 +01005528}
5529testcase TC_classmark() runs on test_CT {
5530 var MSC_ConnHdlr vc_conn;
5531 f_init(1, true);
5532 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005533 vc_conn := f_start_handler(refers(f_tc_classmark));
Harald Welte898113b2018-01-31 18:32:21 +01005534 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005535 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005536}
5537
Harald Welteeddf0e92020-06-21 19:42:15 +02005538/* Send a CommonID from the simulated MSC and verify that the information is used to
5539 * fill BSC-internal data structures (specifically, bsc_subscr associated with subscr_conn) */
5540private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
5541 g_pars := f_gen_test_hdlr_pars();
5542 f_MscConnHdlr_init_vty();
5543
5544 f_create_chan_and_exp();
5545 /* we should now have a COMPL_L3 at the MSC */
Harald Welteeddf0e92020-06-21 19:42:15 +02005546
5547 /* Send CommonID */
5548 BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
5549
5550 /* Use VTY to verify that the IMSI of the subscr_conn is set */
5551 var charstring regex := "*(IMSI: " & hex2str(g_pars.imsi) & ")*";
5552 f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
5553
5554 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005555
5556 f_perform_clear();
Harald Welteeddf0e92020-06-21 19:42:15 +02005557}
5558testcase TC_common_id() runs on test_CT {
5559 var MSC_ConnHdlr vc_conn;
5560 f_init(1, true);
5561 f_sleep(1.0);
5562 vc_conn := f_start_handler(refers(f_tc_common_id));
5563 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005564 f_shutdown_helper();
Harald Welteeddf0e92020-06-21 19:42:15 +02005565}
5566
Harald Weltee3bd6582018-01-31 22:51:25 +01005567private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005568 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005569 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005570 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005571
Harald Weltee3bd6582018-01-31 22:51:25 +01005572 /* send the single message we want to send */
5573 f_rsl_send_l3(l3);
5574}
5575
5576private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr {
5577 timer T := sec;
5578 var PDU_BSSAP bssap;
Harald Welte898113b2018-01-31 18:32:21 +01005579 T.start;
5580 alt {
Harald Weltee3bd6582018-01-31 22:51:25 +01005581 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap {
5582 setverdict(fail, "Unexpected BSSMAP ", bssap);
Daniel Willmannafce8662018-07-06 23:11:32 +02005583 mtc.stop;
Harald Welte898113b2018-01-31 18:32:21 +01005584 }
5585 [] T.timeout {
5586 setverdict(pass);
5587 }
5588 }
5589}
5590
Harald Weltee3bd6582018-01-31 22:51:25 +01005591/* unsolicited ASSIGNMENT FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5592private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
5593 f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
5594 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005595 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005596}
Harald Welte898113b2018-01-31 18:32:21 +01005597testcase TC_unsol_ass_fail() runs on test_CT {
5598 var MSC_ConnHdlr vc_conn;
5599 f_init(1, true);
5600 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005601 vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
Harald Welte898113b2018-01-31 18:32:21 +01005602 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005603 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005604}
Harald Welte552620d2017-12-16 23:21:36 +01005605
Harald Welteea99a002018-01-31 20:46:43 +01005606
5607/* unsolicited ASSIGNMENT COMPLETE (without ASSIGN) from MS shouldn't bring BSC down */
5608private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005609 f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
5610 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005611 f_perform_clear();
Harald Welteea99a002018-01-31 20:46:43 +01005612}
5613testcase TC_unsol_ass_compl() runs on test_CT {
5614 var MSC_ConnHdlr vc_conn;
5615 f_init(1, true);
5616 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005617 vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
Harald Welteea99a002018-01-31 20:46:43 +01005618 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005619 f_shutdown_helper();
Harald Welteea99a002018-01-31 20:46:43 +01005620}
5621
5622
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005623/* unsolicited HANDOVER FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5624private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005625 f_est_single_l3(ts_RRM_HandoverFailure('00'O));
5626 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005627 f_perform_clear();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005628}
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005629testcase TC_unsol_ho_fail() runs on test_CT {
5630 var MSC_ConnHdlr vc_conn;
5631 f_init(1, true);
5632 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005633 vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005634 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005635 f_shutdown_helper();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005636}
5637
5638
Harald Weltee3bd6582018-01-31 22:51:25 +01005639/* short message from MS should be ignored */
5640private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005641 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005642 f_create_chan_and_exp();
Harald Weltee3bd6582018-01-31 22:51:25 +01005643 /* we should now have a COMPL_L3 at the MSC */
Harald Weltee3bd6582018-01-31 22:51:25 +01005644
5645 /* send short message */
5646 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
5647 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005648 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005649}
5650testcase TC_err_82_short_msg() runs on test_CT {
5651 var MSC_ConnHdlr vc_conn;
5652 f_init(1, true);
5653 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005654 vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
Harald Weltee3bd6582018-01-31 22:51:25 +01005655 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005656 f_shutdown_helper();
Harald Weltee3bd6582018-01-31 22:51:25 +01005657}
5658
5659
Harald Weltee9e02e42018-01-31 23:36:25 +01005660/* 24.008 8.4 Unknown message must trigger RR STATUS */
5661private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
5662 f_est_single_l3(ts_RRM_UL_REL('00'O));
5663 timer T := 3.0
5664 alt {
5665 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
5666 setverdict(pass);
5667 }
5668 [] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
Harald Welte458fd372018-03-21 11:26:23 +01005669 [] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
Harald Weltee9e02e42018-01-31 23:36:25 +01005670 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005671 f_perform_clear();
Harald Weltee9e02e42018-01-31 23:36:25 +01005672}
5673testcase TC_err_84_unknown_msg() runs on test_CT {
5674 var MSC_ConnHdlr vc_conn;
5675 f_init(1, true);
5676 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005677 vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
Harald Weltee9e02e42018-01-31 23:36:25 +01005678 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005679 f_shutdown_helper();
Harald Weltee9e02e42018-01-31 23:36:25 +01005680}
5681
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005682/***********************************************************************
5683 * Handover
5684 ***********************************************************************/
5685
Harald Welte94e0c342018-04-07 11:33:23 +02005686/* execute a "bts <0-255> trx <0-255> timeslot <0-7> " command on given Dchan */
5687private function f_vty_ts_action(charstring suffix, integer bts_nr, integer trx_nr, integer ts_nr)
5688runs on test_CT {
5689 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5690 " timeslot "&int2str(ts_nr)&" ";
5691 f_vty_transceive(BSCVTY, cmd & suffix);
5692}
5693
Harald Welte261af4b2018-02-12 21:20:39 +01005694/* 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 +07005695private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
5696 uint8_t bts_nr, uint8_t trx_nr,
5697 in RslChannelNr chan_nr)
5698{
Harald Welte261af4b2018-02-12 21:20:39 +01005699 /* FIXME: resolve those from component-global state */
5700 var integer ts_nr := chan_nr.tn;
5701 var integer ss_nr;
5702 if (ischosen(chan_nr.u.ch0)) {
5703 ss_nr := 0;
5704 } else if (ischosen(chan_nr.u.lm)) {
5705 ss_nr := chan_nr.u.lm.sub_chan;
5706 } else if (ischosen(chan_nr.u.sdcch4)) {
5707 ss_nr := chan_nr.u.sdcch4.sub_chan;
5708 } else if (ischosen(chan_nr.u.sdcch8)) {
5709 ss_nr := chan_nr.u.sdcch8.sub_chan;
5710 } else {
5711 setverdict(fail, "Invalid ChanNr ", chan_nr);
Daniel Willmannafce8662018-07-06 23:11:32 +02005712 mtc.stop;
Harald Welte261af4b2018-02-12 21:20:39 +01005713 }
5714
5715 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5716 " timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005717 f_vty_transceive(pt, cmd & suffix);
Harald Welte261af4b2018-02-12 21:20:39 +01005718}
5719
Neels Hofmeyr91401012019-07-11 00:42:35 +02005720/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
5721 * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor
5722 * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
5723 * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
5724 * pair, not really to a specific BTS number. */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005725private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
5726 in RslChannelNr chan_nr, uint8_t new_bts_nr)
5727{
5728 f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
Harald Welte261af4b2018-02-12 21:20:39 +01005729}
5730
5731/* intra-BSC hand-over between BTS0 and BTS1 */
5732private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02005733 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5734 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte261af4b2018-02-12 21:20:39 +01005735
5736 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5737 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5738
Harald Weltea0630032018-03-20 21:09:55 +01005739 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005740 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Harald Welte261af4b2018-02-12 21:20:39 +01005741
5742 var HandoverState hs := {
5743 rr_ho_cmpl_seen := false,
5744 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005745 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005746 expect_target_tsc := c_BtsParams[1].tsc
Harald Welte261af4b2018-02-12 21:20:39 +01005747 };
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005748 /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005749 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
Harald Welte261af4b2018-02-12 21:20:39 +01005750 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5751 f_rslem_suspend(RSL1_PROC);
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005752
5753 /* From the MGW perspective, a handover is is characterized by
5754 * performing one MDCX operation with the MGW. So we expect to see
5755 * one more MDCX during handover. */
5756 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5757
Harald Welte261af4b2018-02-12 21:20:39 +01005758 alt {
5759 [] as_handover(hs);
Harald Welte261af4b2018-02-12 21:20:39 +01005760 }
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005761
Philipp Maier4dae0652018-11-12 12:03:26 +01005762 /* Since this is an internal handover we expect the BSC to inform the
5763 * MSC about the event */
5764 BSSAP.receive(tr_BSSMAP_HandoverPerformed);
5765
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005766 /* Check the amount of MGCP transactions is still consistant with the
5767 * test expectation */
5768 f_check_mgcp_expectations()
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005769
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005770 var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
5771
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005772 /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
5773 * 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 +02005774 f_verify_encr_info(chan_act);
5775
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005776 f_chan_act_verify_tsc(chan_act, c_BtsParams[1].tsc);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005777
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005778 f_perform_clear(RSL1, RSL1_PROC);
5779
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005780 f_sleep(0.5);
Harald Welte261af4b2018-02-12 21:20:39 +01005781}
5782
5783testcase TC_ho_int() runs on test_CT {
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005784 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte261af4b2018-02-12 21:20:39 +01005785 var MSC_ConnHdlr vc_conn;
5786 f_init(2, true);
5787 f_sleep(1.0);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005788
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005789 pars.expect_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005790
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005791 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005792
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005793 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
Harald Welte261af4b2018-02-12 21:20:39 +01005794 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005795
5796 /* from f_establish_fully() */
5797 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5798 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5799 /* from handover */
5800 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5801 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5802 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5803 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005804 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5805 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005806 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005807 f_shutdown_helper(ho := true);
Harald Welte261af4b2018-02-12 21:20:39 +01005808}
Harald Weltee9e02e42018-01-31 23:36:25 +01005809
Oliver Smith7eabd312021-07-12 14:18:56 +02005810function 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 +02005811 var MSC_ConnHdlr vc_conn;
5812 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5813 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
5814
5815 f_init(2, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02005816 f_vty_encryption_a5(enc_a5);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005817 f_sleep(1.0);
5818
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005819 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005820
5821 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
5822 vc_conn.done;
5823
5824 /* from f_establish_fully() */
5825 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5826 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5827 /* from handover */
5828 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5829 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5830 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5831 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005832 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5833 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005834 f_ctrs_bsc_and_bts_verify();
Oliver Smith7eabd312021-07-12 14:18:56 +02005835 f_vty_encryption_a5_reset();
Oliver Smith39f53072022-10-27 14:44:04 +02005836 f_shutdown_helper(ho := true);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005837}
5838
5839testcase TC_ho_int_a5_0() runs on test_CT {
5840 f_tc_ho_int_a5('01'O);
5841}
5842
5843testcase TC_ho_int_a5_1() runs on test_CT {
5844 f_tc_ho_int_a5('02'O);
5845}
5846
5847testcase TC_ho_int_a5_3() runs on test_CT {
5848 f_tc_ho_int_a5('08'O);
5849}
5850
5851testcase TC_ho_int_a5_4() runs on test_CT {
Oliver Smith7eabd312021-07-12 14:18:56 +02005852 f_tc_ho_int_a5('10'O, "0 1 3 4");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005853}
5854
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005855/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
5856private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
5857 g_pars := f_gen_test_hdlr_pars();
5858 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5859 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005860
5861 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5862 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5863
5864 f_establish_fully(ass_cmd, exp_compl);
5865 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
5866
5867 var HandoverState hs := {
5868 rr_ho_cmpl_seen := false,
5869 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005870 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005871 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005872 };
5873 /* issue hand-over command on VTY */
5874 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
5875 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5876 f_rslem_suspend(RSL1_PROC);
5877
5878 /* From the MGW perspective, a handover is is characterized by
5879 * performing one MDCX operation with the MGW. So we expect to see
5880 * one more MDCX during handover. */
5881 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5882
5883 var RSL_Message rsl;
5884 var PDU_ML3_NW_MS l3;
5885 var RslChannelNr new_chan_nr;
5886 var GsmArfcn arfcn;
5887 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
5888 l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
5889 if (not ischosen(l3.msgs.rrm.handoverCommand)) {
5890 setverdict(fail, "Expected handoverCommand");
5891 mtc.stop;
5892 }
5893 }
5894 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
5895 new_chan_nr, arfcn);
5896
5897 f_rslem_register(0, new_chan_nr, RSL1_PROC);
5898
5899 /* resume processing of RSL DChan messages, which was temporarily suspended
5900 * before performing a hand-over */
5901 f_rslem_resume(RSL1_PROC);
5902 RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
5903
5904 f_sleep(1.0);
5905
5906 /* Handover fails because no HANDO DET appears on the new lchan,
5907 * and the old lchan reports a Radio Link Failure. */
5908 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
5909
5910 var PDU_BSSAP rx_clear_request;
5911 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5912 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5913 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5914
5915 var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
5916
5917 var MgcpCommand mgcp;
5918 interleave {
5919 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
5920 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005921 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005922 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005923 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005924 }
5925 [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005926 [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005927 RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005928 f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005929 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005930 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5931 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5932 }
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005933 }
5934
5935 f_sleep(0.5);
5936 setverdict(pass);
5937}
5938testcase TC_ho_int_radio_link_failure() runs on test_CT {
5939 var MSC_ConnHdlr vc_conn;
5940 f_init(2, true);
5941 f_sleep(1.0);
5942
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005943 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005944
5945 vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
5946 vc_conn.done;
5947
5948 /* from f_establish_fully() */
5949 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5950 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5951 /* from handover */
5952 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5953 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
5954 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5955 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005956 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5957 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005958 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005959 f_shutdown_helper(ho := true);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005960}
5961
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005962/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005963private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005964 var MgcpCommand mgcp;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005965 var template MgcpResponse mgcp_resp;
5966 var MGCP_RecvFrom mrf;
5967 var template MgcpMessage msg_resp;
5968 var template MgcpMessage msg_dlcx := {
5969 command := tr_DLCX()
5970 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005971
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005972 if (g_pars.aoip) {
5973 MGCP.receive(tr_DLCX()) -> value mgcp {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005974 log("Got first DLCX: ", mgcp);
5975 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005976 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005977
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005978 MGCP.receive(tr_DLCX()) -> value mgcp {
5979 log("Got second DLCX: ", mgcp);
5980 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
5981 };
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005982 } else {
5983 /* For SCCPLite, BSC doesn't handle the MSC-side */
5984 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
5985 log("Got first DLCX: ", mrf.msg.command);
5986 msg_resp := {
5987 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
5988 }
5989 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
5990 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005991 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005992}
5993
Oliver Smithc9a5f532022-10-21 11:32:23 +02005994private function f_ho_out_of_this_bsc(template (omit) BSSMAP_oldToNewBSSIEs exp_oldToNewBSSIEs := omit,
5995 boolean skip_meas_rep := false) runs on MSC_ConnHdlr {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005996
Oliver Smithc9a5f532022-10-21 11:32:23 +02005997 if (not skip_meas_rep) {
5998 var NcellReports neighbor_rep := {
5999 { rxlev := 20, bcch_freq := 0, bsic := 11 }
6000 };
6001 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
6002 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
6003 l3_mr, 0));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006004
Oliver Smithc9a5f532022-10-21 11:32:23 +02006005 BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
6006 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006007
6008 f_sleep(0.5);
6009 /* The MSC negotiates Handover Request and Handover Request Ack with
6010 * the other BSS and comes back with a BSSMAP Handover Command
6011 * containing an RR Handover Command coming from the target BSS... */
6012
6013 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6014 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6015 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6016 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6017 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6018
6019 /* expect the Handover Command to go out on RR */
6020 var RSL_Message rsl_ho_cmd
6021 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6022 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6023 var RSL_IE_Body rsl_ho_cmd_l3;
6024 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6025 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6026 setverdict(fail);
6027 } else {
6028 log("Found L3 Info: ", rsl_ho_cmd_l3);
6029 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6030 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6031 setverdict(fail);
6032 } else {
6033 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6034 setverdict(pass);
6035 }
6036 }
6037
6038 /* When the other BSS has reported a completed handover, this side is
6039 * torn down. */
6040
6041 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_HANDOVER_SUCCESSFUL;
6042 var BssmapCause cause := enum2int(cause_val);
6043 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6044
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006045 f_expect_dlcx_conns();
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006046
6047 interleave {
6048 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
6049 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
6050 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006051 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
6052 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
6053 }
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006054 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006055 setverdict(pass);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006056}
6057
6058private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
6059 g_pars := f_gen_test_hdlr_pars();
6060 var PDU_BSSAP ass_req := f_gen_ass_req();
6061 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6062 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6063 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6064 f_establish_fully(ass_req, exp_compl);
6065
6066 f_ho_out_of_this_bsc();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006067}
6068testcase TC_ho_out_of_this_bsc() runs on test_CT {
6069 var MSC_ConnHdlr vc_conn;
6070
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006071 f_init_vty();
6072 f_bts_0_cfg(BSCVTY,
6073 {"neighbor-list mode automatic",
6074 "handover 1",
6075 "handover algorithm 2",
6076 "handover2 window rxlev averaging 1",
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006077 "no neighbors",
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006078 "neighbor lac 99 arfcn 123 bsic any"});
6079 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6080
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006081 f_init(1, true);
6082 f_sleep(1.0);
6083
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006084 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006085
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006086 vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
6087 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006088
6089 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6090 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6091 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6092 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6093 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6094 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
6095 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006096 f_shutdown_helper(ho := true);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006097}
6098
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006099private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6100 template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
Vadim Yanitskiy2ef6a2f2020-10-08 23:17:32 +07006101 template (present) OCT1 dlci := ?,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006102 octetstring l3 := '0123456789'O)
6103runs on MSC_ConnHdlr {
Neels Hofmeyr43654812020-09-25 01:35:35 +02006104 /* The old lchan and conn should still be active. See that arbitrary L3
6105 * is still going through. */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006106 rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
Neels Hofmeyr43654812020-09-25 01:35:35 +02006107 var template PDU_BSSAP exp_data := {
6108 discriminator := '1'B,
6109 spare := '0000000'B,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006110 dlci := dlci,
6111 lengthIndicator := lengthof(l3),
Neels Hofmeyr43654812020-09-25 01:35:35 +02006112 pdu := {
6113 dtap := l3
6114 }
6115 };
6116 BSSAP.receive(exp_data);
6117 setverdict(pass);
6118}
6119
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006120private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6121 template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006122 template (value) OCT1 dlci := '00'O,
6123 octetstring l3 := '0123456789'O)
6124runs on MSC_ConnHdlr {
6125 BSSAP.send(PDU_BSSAP:{
6126 discriminator := '1'B,
6127 spare := '0000000'B,
6128 dlci := dlci,
6129 lengthIndicator := lengthof(l3),
6130 pdu := {
6131 dtap := l3
6132 }
6133 });
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006134 rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006135 setverdict(pass);
6136}
6137
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006138/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
6139 * simply never sends a BSSMAP Handover Command. */
6140private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006141 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006142
6143 var PDU_BSSAP ass_req := f_gen_ass_req();
6144 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6145 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6146 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6147 f_establish_fully(ass_req, exp_compl);
6148
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006149 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006150 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6151
6152 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6153
6154 /* osmo-bsc should time out 10 seconds after the handover started.
6155 * Let's give it a bit extra. */
6156 f_sleep(15.0);
6157
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006158 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006159 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006160 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006161}
6162testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
6163 var MSC_ConnHdlr vc_conn;
6164
6165 f_init(1, true);
6166 f_sleep(1.0);
6167
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006168 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006169
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006170 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
6171 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006172
6173 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6174 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6175 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6176 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6177 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6178 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6179 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006180 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006181}
6182
6183/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
6184 * RR Handover Failure. */
6185private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006186 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006187
6188 var PDU_BSSAP ass_req := f_gen_ass_req();
6189 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6190 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6191 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6192 f_establish_fully(ass_req, exp_compl);
6193
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006194 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006195 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6196
6197 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6198
6199 f_sleep(0.5);
6200 /* The MSC negotiates Handover Request and Handover Request Ack with
6201 * the other BSS and comes back with a BSSMAP Handover Command
6202 * containing an RR Handover Command coming from the target BSS... */
6203
6204 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6205 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6206 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6207 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6208 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6209
6210 /* expect the Handover Command to go out on RR */
6211 var RSL_Message rsl_ho_cmd
6212 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6213 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6214 var RSL_IE_Body rsl_ho_cmd_l3;
6215 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6216 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6217 setverdict(fail);
6218 } else {
6219 log("Found L3 Info: ", rsl_ho_cmd_l3);
6220 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6221 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6222 setverdict(fail);
6223 } else {
6224 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6225 setverdict(pass);
6226 }
6227 }
6228
6229 f_sleep(0.2);
6230 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
6231
6232 /* Should tell the MSC about the failure */
6233 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6234
6235 f_sleep(1.0);
6236
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006237 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006238 f_sleep(1.0);
6239
6240 setverdict(pass);
6241 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006242 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006243}
6244testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
6245 var MSC_ConnHdlr vc_conn;
6246
6247 f_init(1, true);
6248 f_sleep(1.0);
6249
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006250 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006251
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006252 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
6253 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006254
6255 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6256 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6257 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6258 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6259 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6260 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
6261 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006262 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006263}
6264
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006265/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
6266 * (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 +02006267 * and the lchan is released. */
6268private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006269 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006270
6271 var PDU_BSSAP ass_req := f_gen_ass_req();
6272 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6273 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6274 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6275 f_establish_fully(ass_req, exp_compl);
6276
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006277 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006278 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6279
6280 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6281
6282 f_sleep(0.5);
6283 /* The MSC negotiates Handover Request and Handover Request Ack with
6284 * the other BSS and comes back with a BSSMAP Handover Command
6285 * containing an RR Handover Command coming from the target BSS... */
6286
6287 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6288 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6289 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6290 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6291 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6292
6293 /* expect the Handover Command to go out on RR */
6294 var RSL_Message rsl_ho_cmd
6295 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6296 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6297 var RSL_IE_Body rsl_ho_cmd_l3;
6298 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6299 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6300 setverdict(fail);
6301 } else {
6302 log("Found L3 Info: ", rsl_ho_cmd_l3);
6303 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6304 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6305 setverdict(fail);
6306 } else {
6307 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6308 setverdict(pass);
6309 }
6310 }
6311
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006312 /* We get neither success nor failure report from the remote BSS. Eventually T8 times out and we run into 3GPP
6313 * TS 48.008 3.1.5.3.3 "Abnormal Conditions": Clear Request should go to the MSC, and RR should be released
6314 * after Clear Command */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006315
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006316 var PDU_BSSAP rx_clear_request;
Neels Hofmeyre1797aa2019-07-09 19:34:04 +02006317 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
6318 log("Got BSSMAP Clear Request");
6319 /* Instruct BSC to clear channel */
6320 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6321 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6322
6323 var MgcpCommand mgcp;
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006324 interleave {
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01006325 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
6326 log("Got Deact SACCH");
6327 }
Harald Welte924b6ea2019-02-04 01:05:34 +01006328 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
Neels Hofmeyr211169d2018-11-07 00:37:29 +01006329 log("Got RR Release");
6330 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02006331 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006332 log("Got RF Chan Rel");
6333 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02006334 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006335 }
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006336 }
6337
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006338 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006339 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006340 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006341
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006342 setverdict(pass);
6343 f_sleep(1.0);
6344}
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006345testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006346 var MSC_ConnHdlr vc_conn;
6347
6348 f_init(1, true);
6349 f_sleep(1.0);
6350
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006351 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006352
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006353 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006354 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006355
6356 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6357 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6358 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6359 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6360 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6361 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6362 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006363 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006364}
6365
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006366private 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 +01006367 var PDU_BSSAP rx_bssap;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006368 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6369 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6370 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6371 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6372 * before we get started. */
6373 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6374 f_rslem_register(0, new_chan_nr);
6375 g_chan_nr := new_chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06006376 var uint3_t expect_target_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006377 f_sleep(1.0);
6378
6379 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6380 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006381 var default as_media := activate(as_Media());
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006382
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01006383 var PDU_BSSAP ho_req := f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
6384 cell_id_source := g_pars.cell_id_source,
6385 oldToNewBSSIEs := oldToNewBSSIEs,
6386 enc := g_pars.encr);
6387 if (g_pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr) {
6388 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, ho_req));
6389 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6390 } else {
6391 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, omit));
6392 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6393 BSSAP.send(ho_req);
6394 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006395
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006396 alt {
6397 [] BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap {
6398 if (g_pars.expect_ho_fail) {
6399 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6400 "Expected Handover Request to fail, but got Handover Request Ack")
6401 }
6402 }
6403 [] BSSAP.receive(tr_BSSMAP_HandoverFailure) -> value rx_bssap {
6404 if (not g_pars.expect_ho_fail) {
6405 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6406 "Expected Handover Request to succeed, but got Handover Failure")
6407 }
6408 // TODO: evaluate correct cause value. But osmo-bsc doesn't seem to send meaningful causes yet!
6409 // For now just accept any cause.
6410 BSSAP.receive(tr_BSSMAP_ClearRequest);
6411 setverdict(pass);
6412 return;
6413 }
6414 }
6415
Oliver Smith7a8594a2023-02-13 14:30:49 +01006416 if (g_pars.expect_ho_fail_lchan_est) {
6417 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6418 setverdict(pass);
Oliver Smitha1cbec52023-02-21 12:44:12 +01006419
6420 /* When we let MGCP MDCX run into a timeout, it's still in the
6421 * queue and additionally after BSSAP HandoverFailure, two DLCX
Oliver Smith30eb8822023-03-06 12:31:53 +01006422 * get sent (for AoIP, for SCCPlite one DLCX). */
Oliver Smitha1cbec52023-02-21 12:44:12 +01006423 if (g_pars.ignore_mgw_mdcx) {
Oliver Smith30eb8822023-03-06 12:31:53 +01006424 if (g_pars.aoip) {
6425 MGCP.receive(tr_MDCX);
6426 MGCP.receive(tr_DLCX);
6427 MGCP.receive(tr_DLCX);
6428 } else {
6429 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_MDCX}));
6430 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_DLCX}));
6431 }
Oliver Smitha1cbec52023-02-21 12:44:12 +01006432 }
Oliver Smith7a8594a2023-02-13 14:30:49 +01006433 return;
6434 }
6435
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006436 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6437
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006438 /* we're sure that the channel activation is done now, verify the parameters in it */
6439 var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
6440 f_verify_encr_info(chan_act);
6441 f_chan_act_verify_tsc(chan_act, expect_target_tsc);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006442
Neels Hofmeyr46e16e52022-02-23 17:04:00 +01006443 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.codecList)) {
6444 if (not g_pars.aoip) {
6445 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6446 "handoverRequestAck: Expected no Speech Codec List (BSS Supported), because this is not AoIP");
6447 }
6448 /* TODO: check actual codecs? */
6449 } else {
6450 if (g_pars.aoip) {
6451 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6452 "handoverRequestAck: Expected Speech Codec List (BSS Supported), but none found");
6453 }
6454 }
6455
6456 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.speechCodec)) {
6457 if (not g_pars.aoip) {
6458 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6459 "handoverRequestAck: Expected no Speech Codec (Chosen), because this is not AoIP");
6460 }
6461 /* TODO: check actual codec? */
6462 } else {
6463 if (g_pars.aoip) {
6464 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6465 "handoverRequestAck: Expected Speech Codec (Chosen), but none found");
6466 }
6467 }
6468
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006469 var octetstring ho_command_str;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006470 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6471 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6472 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6473 log("L3 Info in HO Request Ack is ", ho_command);
6474
6475 var GsmArfcn arfcn;
6476 var RslChannelNr actual_new_chan_nr;
6477 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6478 actual_new_chan_nr, arfcn);
6479
6480 if (actual_new_chan_nr != new_chan_nr) {
6481 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6482 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6483 setverdict(fail);
6484 return;
6485 }
6486 log("Handover Command chan_nr is", actual_new_chan_nr);
6487
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006488 var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
6489 if (not match(got_tsc, expect_target_tsc)) {
6490 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6491 expect_target_tsc, " got ", got_tsc);
6492 mtc.stop;
6493 } else {
6494 log("handoverCommand: verified TSC = ", got_tsc);
6495 }
6496
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006497 /* Check the Cipher Mode Setting IE (shall be present during inter-RAT handover) */
6498 if (ispresent(ho_command.msgs.rrm.handoverCommand.cipherModeSetting)) {
6499 var CipherModeSetting_TV cms := ho_command.msgs.rrm.handoverCommand.cipherModeSetting;
6500 var template (present) CipherModeSetting_TV tr_cms := {
6501 sC := '0'B, /* no ciphering by default */
6502 algorithmIdentifier := '000'B,
6503 elementIdentifier := ?
6504 };
6505 if (ispresent(g_pars.encr) and g_pars.encr.enc_alg_expect != '01'O) { /* A5/N */
6506 tr_cms.algorithmIdentifier := f_cipher_mode_bssmap_to_rr(g_pars.encr.enc_alg_expect);
6507 tr_cms.sC := '1'B;
6508 }
6509 if (not match(cms, tr_cms)) {
6510 setverdict(fail, "RR Handover Command: unexpected Cipher Mode Setting IE: ",
6511 cms, ", expected: ", tr_cms);
6512 }
6513 } else {
6514 setverdict(fail, "RR Handover Command: Cipher Mode Setting IE is not present");
6515 }
6516
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006517 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6518 * tells the MS to handover to the new lchan. Here comes the new MS on
6519 * the new lchan with a Handover RACH: */
6520
6521 /* send handover detect */
6522
6523 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6524
6525 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6526
6527 /* send handover complete over the new channel */
6528
6529 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_HandoverComplete('00'O));
6530 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
6531 enc_PDU_ML3_MS_NW(l3_tx)));
6532
6533 BSSAP.receive(tr_BSSMAP_HandoverComplete);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006534 deactivate(as_media);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006535 setverdict(pass);
6536}
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006537
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006538private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006539 var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006540 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
6541 if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
6542 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006543 }
6544 if (g_pars.exp_fast_return) {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006545 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006546 } else {
6547 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006548 }
6549 f_ho_into_this_bsc(id, oldToNewBSSIEs);
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006550 if (g_pars.expect_ho_fail) {
6551 f_perform_clear_no_lchan();
Oliver Smith7a8594a2023-02-13 14:30:49 +01006552 } else if (g_pars.expect_ho_fail_lchan_est) {
6553 BSSAP.receive(tr_BSSMAP_ClearRequest);
6554 f_perform_clear_no_lchan();
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006555 } else {
6556 f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
6557 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006558 setverdict(pass);
6559}
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006560function 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 +01006561 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006562
6563 f_init(1, true);
6564 f_sleep(1.0);
6565
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006566 f_vty_encryption_a5(vty_a5_cfg);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006567 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006568
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006569 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6570 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006571
6572 vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
6573 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006574
6575 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006576 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006577 if (pars.expect_ho_fail) {
6578 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6579 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:failed");
Oliver Smith7a8594a2023-02-13 14:30:49 +01006580 } else if (pars.expect_ho_fail_lchan_est) {
6581 f_ctrs_bsc_and_bts_add(0, "handover:error");
6582 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006583 } else {
6584 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6585 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
6586 }
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006587 f_ctrs_bsc_and_bts_verify();
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006588
6589 f_vty_encryption_a5_reset();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006590}
6591
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006592testcase TC_ho_into_this_bsc() runs on test_CT {
6593 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6594 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006595 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006596}
6597
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006598function f_tc_ho_into_this_bsc_a5(TestHdlrEncrParams encr, charstring vty_a5_cfg := VTY_A5_DEFAULT,
6599 boolean expect_fail := false) runs on test_CT {
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006600 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006601 pars.encr := encr;
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006602 pars.expect_ho_fail := expect_fail;
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006603 f_tc_ho_into_this_bsc_main(pars, vty_a5_cfg);
Oliver Smith39f53072022-10-27 14:44:04 +02006604 f_shutdown_helper(ho := true);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006605}
6606
6607testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006608 f_tc_ho_into_this_bsc_a5(f_encr_params('01'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006609}
6610
6611testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006612 f_tc_ho_into_this_bsc_a5(f_encr_params('02'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006613}
6614
6615testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006616 f_tc_ho_into_this_bsc_a5(f_encr_params('08'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006617}
6618
6619testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006620 f_tc_ho_into_this_bsc_a5(f_encr_params('10'O, kc128 := true), "3 4");
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006621}
6622
Neels Hofmeyr1951be22022-02-16 16:21:07 +01006623/* Report: in inter-BSC incoming handover, when the MSC omits the Chosen Encryption Algorithm IE in the Handover Request
6624 * message, then osmo-bsc starts an unencrypted lchan even if A5/0 is not permitted.
6625 *
6626 * This test verifies that the Encryption Information is present in the Channel Activation when the Chosen Enc Alg is
6627 * omitted.
6628 *
6629 * Related: SYS#5839
6630 */
6631testcase TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() runs on test_CT {
6632 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O, alg_chosen := omit));
6633}
6634
6635testcase TC_ho_into_this_bsc_a5_1_3() runs on test_CT {
6636 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O));
6637}
6638
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006639/* Send a permitted algo mask that does not intersect with osmo-bsc.cfg */
6640testcase TC_ho_into_this_bsc_a5_mismatch() runs on test_CT {
6641 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '18'O, alg_expect := '10'O), "0 1",
6642 expect_fail := true); // 0x18 = A5/3 and A5/4
6643}
6644
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006645testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
6646 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6647 pars.host_aoip_tla := "::6";
6648 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006649 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006650}
6651
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006652/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006653 to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006654 channel is later released (RR CHannel Release), should trigger inclusion of
6655 IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
6656 neighbors. */
6657testcase TC_srvcc_eutran_to_geran() runs on test_CT {
6658 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6659 pars.last_used_eutran_plmn := '323454'O;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006660 pars.exp_fast_return := true;
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006661 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006662
6663 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6664 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6665 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006666 f_shutdown_helper(ho := true);
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006667}
6668
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006669/* Same as TC_srvcc_eutran_to_geran, but enables ciphering on the target channel. */
6670testcase TC_srvcc_eutran_to_geran_a5_3() runs on test_CT {
6671 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6672 pars.encr := f_encr_params('08'O); /* only A5/3 */
6673 pars.last_used_eutran_plmn := '323454'O;
6674 pars.exp_fast_return := true;
6675 f_tc_ho_into_this_bsc_main(pars);
6676
6677 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6678 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6679 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006680 f_shutdown_helper(ho := true);
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006681}
6682
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006683/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
6684 on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
6685 list when the channel is released. */
6686testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
6687 f_init_vty();
6688 f_vty_allow_srvcc_fast_return(true, 0)
6689
6690 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6691 pars.last_used_eutran_plmn := '323454'O;
6692 pars.exp_fast_return := false;
6693 f_tc_ho_into_this_bsc_main(pars);
6694 f_vty_allow_srvcc_fast_return(false, 0);
6695 f_shutdown_helper();
6696}
6697
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01006698/* Same as TC_srvcc_eutran_to_geran, but using SAI as serving Cell Identifier. SYS#5838 */
6699testcase TC_srvcc_eutran_to_geran_src_sai() runs on test_CT {
6700 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6701 pars.last_used_eutran_plmn := '323454'O;
6702 pars.cell_id_source := valueof(ts_CellID_SAI('123456'O, 300, 444));
6703 f_tc_ho_into_this_bsc_main(pars);
6704
6705 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6706 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6707 f_ctrs_bsc_and_bts_verify();
6708 f_shutdown_helper();
6709}
6710
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006711private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
6712 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
6713 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
6714 f_ho_into_this_bsc(id, oldToNewBSSIEs);
6715 f_ho_out_of_this_bsc(oldToNewBSSIEs);
6716 setverdict(pass);
6717}
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006718
6719private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
6720 runs on test_CT {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006721 var MSC_ConnHdlr vc_conn;
6722 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6723
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006724 f_init_vty();
6725 f_bts_0_cfg(BSCVTY,
6726 {"neighbor-list mode automatic",
6727 "handover 1",
6728 "handover algorithm 2",
6729 "handover2 window rxlev averaging 1",
6730 "no neighbors",
6731 "neighbor lac 99 arfcn 123 bsic any"});
6732 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6733
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006734 f_init(1, true);
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006735 if (disable_fast_return) {
6736 f_vty_allow_srvcc_fast_return(true, 0);
6737 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006738 f_sleep(1.0);
6739
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006740 f_ctrs_bsc_and_bts_handover_init();
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006741
6742 pars.last_used_eutran_plmn := '323454'O;
6743 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6744 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
6745
6746 vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
6747 vc_conn.done;
6748
6749 f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
6750 f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
6751 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
6752 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
6753 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
6754 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006755
6756 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
6757 f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006758 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006759
6760 if (disable_fast_return) {
6761 f_vty_allow_srvcc_fast_return(false, 0);
6762 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006763 f_shutdown_helper();
6764}
6765
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006766/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
6767 BSS Information" IE with "Last Used E-UTRAN PLMN Id".
6768 Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
6769 IE with "Last Used E-UTRAN PLMN Id" from first step. */
6770testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
6771 f_tc_srvcc_eutran_to_geran_ho_out_main(false);
6772}
6773/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
6774 * independently of fast-reture allowed/forbidden in local BTS */
6775testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
6776 f_tc_srvcc_eutran_to_geran_ho_out_main(true);
6777}
6778
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006779private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
6780 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6781 f_rslem_register(0, new_chan_nr);
6782 g_chan_nr := new_chan_nr;
6783 f_sleep(1.0);
6784
6785 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6786 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6787 activate(as_Media());
6788
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006789 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006790 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006791 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006792
6793 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6794
6795 var PDU_BSSAP rx_bssap;
6796 var octetstring ho_command_str;
6797
6798 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6799
6800 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6801 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6802 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6803 log("L3 Info in HO Request Ack is ", ho_command);
6804
6805 var GsmArfcn arfcn;
6806 var RslChannelNr actual_new_chan_nr;
6807 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6808 actual_new_chan_nr, arfcn);
6809
6810 if (actual_new_chan_nr != new_chan_nr) {
6811 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6812 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6813 setverdict(fail);
6814 return;
6815 }
6816 log("Handover Command chan_nr is", actual_new_chan_nr);
6817
Neels Hofmeyr61ca08d2019-05-06 23:52:22 +02006818 /* For deterministic test results, give some time for the MGW endpoint to be configured */
6819 f_sleep(1.0);
6820
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006821 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6822 * tells the MS to handover to the new lchan. In this case, the MS
6823 * reports a Handover Failure to the old BSS, which forwards a BSSMAP
6824 * Handover Failure to the MSC. The procedure according to 3GPP TS
6825 * 48.008 3.1.5.3.2 "Handover Failure" is then that the MSC sends a
6826 * BSSMAP Clear Command: */
6827
6828 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6829 var BssmapCause cause := enum2int(cause_val);
6830 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6831
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006832 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006833 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006834 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006835
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006836 setverdict(pass);
6837 f_sleep(1.0);
6838
6839 setverdict(pass);
6840}
6841testcase TC_ho_in_fail_msc_clears() runs on test_CT {
6842 var MSC_ConnHdlr vc_conn;
6843 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6844
6845 f_init(1, true);
6846 f_sleep(1.0);
6847
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006848 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006849
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006850 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6851 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006852
6853 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
6854 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006855
6856 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6857 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6858 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6859 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6860 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006861 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006862}
6863
6864private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
6865 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6866 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6867 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6868 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6869 * before we get started. */
6870 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6871 f_rslem_register(0, new_chan_nr);
6872 g_chan_nr := new_chan_nr;
6873 f_sleep(1.0);
6874
6875 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6876 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6877 activate(as_Media());
6878
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006879 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006880 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006881 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006882
6883 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6884
6885 var PDU_BSSAP rx_bssap;
6886 var octetstring ho_command_str;
6887
6888 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6889
6890 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6891 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6892 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6893 log("L3 Info in HO Request Ack is ", ho_command);
6894
6895 var GsmArfcn arfcn;
6896 var RslChannelNr actual_new_chan_nr;
6897 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6898 actual_new_chan_nr, arfcn);
6899
6900 if (actual_new_chan_nr != new_chan_nr) {
6901 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6902 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6903 setverdict(fail);
6904 return;
6905 }
6906 log("Handover Command chan_nr is", actual_new_chan_nr);
6907
6908 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6909 * tells the MS to handover to the new lchan. Here comes the new MS on
6910 * the new lchan with a Handover RACH: */
6911
6912 /* send handover detect */
6913
6914 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6915
6916 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6917
6918 /* The MSC chooses to clear the connection now, maybe we got the
6919 * Handover RACH on the new cell but the MS still signaled Handover
6920 * Failure to the old BSS? */
6921
6922 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6923 var BssmapCause cause := enum2int(cause_val);
6924 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6925
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006926 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006927 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006928 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006929
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006930 f_sleep(1.0);
6931}
6932testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
6933 var MSC_ConnHdlr vc_conn;
6934 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6935
6936 f_init(1, true);
6937 f_sleep(1.0);
6938
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006939 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006940
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006941 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6942 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006943
6944 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
6945 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006946
6947 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6948 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6949 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6950 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6951 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006952 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006953}
6954
6955/* The new BSS's lchan times out before the MSC decides that handover failed. */
6956private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
6957 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6958 f_rslem_register(0, new_chan_nr);
6959 g_chan_nr := new_chan_nr;
6960 f_sleep(1.0);
6961
6962 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6963 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01006964 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006965
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006966 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006967 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006968 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006969
6970 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6971
6972 var PDU_BSSAP rx_bssap;
6973 var octetstring ho_command_str;
6974
6975 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6976
6977 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6978 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6979 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6980 log("L3 Info in HO Request Ack is ", ho_command);
6981
6982 var GsmArfcn arfcn;
6983 var RslChannelNr actual_new_chan_nr;
6984 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6985 actual_new_chan_nr, arfcn);
6986
6987 if (actual_new_chan_nr != new_chan_nr) {
6988 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6989 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6990 setverdict(fail);
6991 return;
6992 }
6993 log("Handover Command chan_nr is", actual_new_chan_nr);
6994
6995 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6996 * tells the MS to handover to the new lchan. But the MS never shows up
6997 * on the new lchan. */
6998
6999 BSSAP.receive(tr_BSSMAP_HandoverFailure);
7000
7001 /* Did osmo-bsc also send a Clear Request? */
7002 timer T := 0.5;
7003 T.start;
7004 alt {
7005 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
7006 [] T.timeout { }
7007 }
7008
7009 /* MSC plays along with a Clear Command (no matter whether osmo-bsc
7010 * asked for it, this is a Handover Failure after all). */
7011
7012 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
7013 var BssmapCause cause := enum2int(cause_val);
7014 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7015
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007016 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007017 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007018 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007019
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007020 f_sleep(1.0);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007021}
7022testcase TC_ho_in_fail_no_detect() runs on test_CT {
7023 var MSC_ConnHdlr vc_conn;
7024 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7025
Oliver Smithd49f46d2023-03-08 12:23:13 +01007026 pars.fail_on_dlcx := false;
7027
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007028 f_init(1, true);
7029 f_sleep(1.0);
7030
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007031 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007032
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007033 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7034 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007035
7036 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect), pars);
7037 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007038
7039 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7040 f_ctrs_bsc_and_bts_add(0, "handover:error");
7041 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7042 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7043 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007044 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007045}
7046
7047/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
7048private function f_tc_ho_in_fail_no_detect2(charstring id) runs on MSC_ConnHdlr {
7049 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
7050 f_rslem_register(0, new_chan_nr);
7051 g_chan_nr := new_chan_nr;
7052 f_sleep(1.0);
7053
7054 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
7055 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01007056 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007057
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007058 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007059 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02007060 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007061
7062 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
7063
7064 var PDU_BSSAP rx_bssap;
7065 var octetstring ho_command_str;
7066
7067 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
7068
7069 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
7070 log("Received L3 Info in HO Request Ack: ", ho_command_str);
7071 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
7072 log("L3 Info in HO Request Ack is ", ho_command);
7073
7074 var GsmArfcn arfcn;
7075 var RslChannelNr actual_new_chan_nr;
7076 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
7077 actual_new_chan_nr, arfcn);
7078
7079 if (actual_new_chan_nr != new_chan_nr) {
7080 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
7081 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
7082 setverdict(fail);
7083 return;
7084 }
7085 log("Handover Command chan_nr is", actual_new_chan_nr);
7086
7087 /* Now the MSC forwards the RR Handover Command to the other BSC, which
7088 * tells the MS to handover to the new lchan. But the MS never shows up
7089 * on the new lchan. */
7090
7091 BSSAP.receive(tr_BSSMAP_HandoverFailure);
7092
7093 /* MSC plays dumb and sends no Clear Command */
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007094 var PDU_BSSAP rx_clear_request;
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02007095
7096 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request {
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007097 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
7098 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7099 };
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007100 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007101 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007102 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007103
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007104 f_sleep(1.0);
7105}
7106testcase TC_ho_in_fail_no_detect2() runs on test_CT {
7107 var MSC_ConnHdlr vc_conn;
7108 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7109
Oliver Smith735b47c2023-02-15 16:03:54 +01007110 pars.fail_on_dlcx := false;
7111
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007112 f_init(1, true);
7113 f_sleep(1.0);
7114
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007115 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007116
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007117 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7118 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007119
7120 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
7121 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007122
7123 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7124 f_ctrs_bsc_and_bts_add(0, "handover:error");
7125 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7126 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7127 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007128 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007129}
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01007130
Oliver Smith7a8594a2023-02-13 14:30:49 +01007131testcase TC_ho_in_fail_mgw_mdcx_timeout() runs on test_CT {
7132 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7133
7134 pars.ignore_mgw_mdcx := true;
7135 pars.expect_ho_fail_lchan_est := true;
7136
7137 f_tc_ho_into_this_bsc_main(pars);
7138 f_shutdown_helper(ho := true);
7139}
7140
Oliver Smith4eed06f2023-02-15 15:43:19 +01007141testcase TC_ho_in_fail_ipa_crcx_timeout() runs on test_CT {
7142 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7143
7144 pars.ignore_ipa_media := true;
7145 pars.expect_ho_fail_lchan_est := true;
7146 pars.fail_on_dlcx := false;
7147
7148 f_tc_ho_into_this_bsc_main(pars);
7149 f_shutdown_helper(ho := true);
7150}
7151
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007152/* An incoming inter-BSC HO can either issue the Handover Request message attached to the initial SCCP N-Connect (as in
7153 * the other tests we have so far), or the first CR can be "empty" with the BSSAP request following later. Test the
7154 * empty N-Connect case. */
7155testcase TC_ho_into_this_bsc_sccp_cr_without_bssap() runs on test_CT {
7156 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7157 pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr := false;
7158 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02007159 f_shutdown_helper(ho := true);
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007160}
7161
Neels Hofmeyr91401012019-07-11 00:42:35 +02007162type record of charstring Commands;
7163
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007164private function f_bts_0_cfg(TELNETasp_PT pt, Commands cmds := {})
Neels Hofmeyr91401012019-07-11 00:42:35 +02007165{
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007166 f_vty_enter_cfg_bts(pt, 0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007167 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007168 f_vty_transceive(pt, cmds[i]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007169 }
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007170 f_vty_transceive(pt, "end");
Neels Hofmeyr91401012019-07-11 00:42:35 +02007171}
7172
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01007173private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
7174{
7175 f_vty_enter_cfg_cs7_inst(pt, 0);
7176 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
7177 f_vty_transceive(pt, cmds[i]);
7178 }
7179 f_vty_transceive(pt, "end");
7180}
7181
Neels Hofmeyr91401012019-07-11 00:42:35 +02007182private function f_probe_for_handover(charstring log_label,
7183 charstring log_descr,
7184 charstring handover_vty_cmd,
7185 boolean expect_handover,
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007186 boolean is_inter_bsc_handover := false,
7187 template uint3_t expect_target_tsc := ?)
Neels Hofmeyr91401012019-07-11 00:42:35 +02007188runs on MSC_ConnHdlr
7189{
Neels Hofmeyrb3fc8982020-05-11 00:16:42 +02007190 /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
7191 * lchans to be established on bts 1 or bts 2. */
7192 f_rslem_suspend(RSL1_PROC);
7193 f_rslem_suspend(RSL2_PROC);
7194
Neels Hofmeyr91401012019-07-11 00:42:35 +02007195 var RSL_Message rsl;
7196
7197 var charstring log_msg := " (expecting handover)"
7198 if (not expect_handover) {
7199 log_msg := " (expecting NO handover)";
7200 }
7201 log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg);
7202 f_vty_transceive(BSCVTY, handover_vty_cmd);
7203
Neels Hofmeyr91401012019-07-11 00:42:35 +02007204 timer T := 2.0;
7205 T.start;
7206
7207 alt {
7208 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
7209 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
7210 log("Rx L3 from net: ", l3);
7211 if (ischosen(l3.msgs.rrm.handoverCommand)) {
7212 var RslChannelNr new_chan_nr;
7213 var GsmArfcn arfcn;
7214 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
7215 new_chan_nr, arfcn);
7216 log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
7217 log(l3.msgs.rrm.handoverCommand);
7218
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007219 /* Verify correct TSC in handoverCommand */
7220 var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
7221 if (not match(got_tsc, expect_target_tsc)) {
7222 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
7223 expect_target_tsc, " got ", got_tsc);
7224 mtc.stop;
7225 } else {
7226 log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
7227 expect_target_tsc, ")");
7228 }
7229
Neels Hofmeyr91401012019-07-11 00:42:35 +02007230 /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
7231 * matter on which BTS it really is, we're not going to follow through an entire handover
7232 * anyway. */
7233 f_rslem_register(0, new_chan_nr, RSL1_PROC);
7234 f_rslem_resume(RSL1_PROC);
7235 f_rslem_register(0, new_chan_nr, RSL2_PROC);
7236 f_rslem_resume(RSL2_PROC);
7237
7238 if (expect_handover and not is_inter_bsc_handover) {
7239 setverdict(pass);
7240 log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected.");
7241 } else {
7242 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. "
7243 & log_label & ": " & log_descr);
7244 }
7245
7246 log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
7247 /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with
7248 * Handover Failure. */
7249 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
7250
7251 /* target BTS is told to release lchan again; don't care which BTS nor what messages. */
7252 f_sleep(0.5);
7253 RSL1.clear;
7254 RSL2.clear;
7255 log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)");
7256 break;
7257 } else {
7258 repeat;
7259 }
7260 }
7261 [] BSSAP.receive(tr_BSSMAP_HandoverRequired) {
7262 if (expect_handover and is_inter_bsc_handover) {
7263 setverdict(pass);
7264 log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected.");
7265 } else {
7266 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. "
7267 & log_label & ": " & log_descr);
7268 }
7269
7270 log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)");
7271
7272 /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to
7273 * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required,
7274 * setting a short timeout and waiting is the only way. */
7275 log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out...");
7276 f_sleep(1.5);
7277 log("f_probe_for_handover(" & log_label & "): ...done");
7278
7279 break;
7280 }
7281 [] T.timeout {
7282 if (expect_handover) {
7283 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. "
7284 & log_label & ": " & log_descr);
7285 } else {
7286 setverdict(pass);
7287 log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected.");
7288 }
7289 log("f_probe_for_handover(" & log_label & "): done (got no Handover)");
7290 break;
7291 }
7292 }
7293
7294 f_rslem_resume(RSL1_PROC);
7295 f_rslem_resume(RSL2_PROC);
7296 f_sleep(3.0);
7297 RSL.clear;
7298
7299 log("f_probe_for_handover(" & log_label & "): done clearing");
7300}
7301
7302/* Test the effect of various neighbor configuration scenarios:
7303 *
7304 * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0.
7305 * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO.
7306 */
7307private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
7308 g_pars := f_gen_test_hdlr_pars();
7309 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
7310 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007311
7312 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
7313 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
7314
7315 /* Establish lchan at bts 0 */
7316 f_establish_fully(ass_cmd, exp_compl);
7317
7318 /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */
7319 f_vty_enter_cfg_network(BSCVTY);
7320 f_vty_transceive(BSCVTY, "timer T7 1");
7321 f_vty_transceive(BSCVTY, "end");
7322}
7323
7324private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
7325 f_tc_ho_neighbor_config_start();
7326
7327 /*
7328 * bts 0 ARFCN 871 BSIC 10
7329 * bts 1 ARFCN 871 BSIC 11
7330 * bts 2 ARFCN 871 BSIC 12
7331 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7332 */
7333
7334 log("f_tc_ho_neighbor_config: 1. No 'neighbor' config");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007335 f_bts_0_cfg(BSCVTY, {"no neighbors"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007336 f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
7337 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007338 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007339
7340 f_probe_for_handover("1.b", "HO to unknown cell does not start",
7341 "handover any to arfcn 13 bsic 39",
7342 false);
7343
7344 f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error",
7345 "handover any to arfcn 871 bsic 12",
7346 false);
7347
7348 f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
7349 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007350 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007351
7352 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007353}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007354testcase TC_ho_neighbor_config_1() runs on test_CT {
7355 var MSC_ConnHdlr vc_conn;
7356 f_init(3, true, guard_timeout := 60.0);
7357 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007358 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007359 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
7360 vc_conn.done;
7361
7362 /* f_tc_ho_neighbor_config_start() */
7363 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7364 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7365
7366 /* 1.a */
7367 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7368 * handover quickly by sending a Handover Failure message. */
7369 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7370 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7371 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7372 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007373 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7374 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007375
7376 /* 1.b */
7377 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7378 f_ctrs_bsc_and_bts_add(0, "handover:error");
7379
7380 /* 1.c */
7381 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7382 f_ctrs_bsc_and_bts_add(0, "handover:error");
7383
7384 /* 1.d */
7385 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7386 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7387 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7388 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007389 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7390 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007391
7392 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007393 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007394}
7395
Neels Hofmeyr91401012019-07-11 00:42:35 +02007396private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
7397 f_tc_ho_neighbor_config_start();
7398
7399 /*
7400 * bts 0 ARFCN 871 BSIC 10
7401 * bts 1 ARFCN 871 BSIC 11
7402 * bts 2 ARFCN 871 BSIC 12
7403 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7404 */
7405
7406 log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007407 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007408 f_sleep(0.5);
7409
7410 f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
7411 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007412 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007413
7414 f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
7415 "handover any to arfcn 871 bsic 12",
7416 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007417 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007418}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007419testcase TC_ho_neighbor_config_2() runs on test_CT {
7420 var MSC_ConnHdlr vc_conn;
7421 f_init(3, true, guard_timeout := 50.0);
7422 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007423 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007424 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
7425 vc_conn.done;
7426
7427 /* f_tc_ho_neighbor_config_start() */
7428 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7429 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7430
7431 /* 2.a */
7432 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7433 * handover quickly by sending a Handover Failure message. */
7434 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7435 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7436 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7437 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007438 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7439 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007440
7441 /* 2.b */
7442 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7443 f_ctrs_bsc_and_bts_add(0, "handover:error");
7444
7445 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007446 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007447}
7448
Neels Hofmeyr91401012019-07-11 00:42:35 +02007449private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
7450 f_tc_ho_neighbor_config_start();
7451
7452 /*
7453 * bts 0 ARFCN 871 BSIC 10
7454 * bts 1 ARFCN 871 BSIC 11
7455 * bts 2 ARFCN 871 BSIC 12
7456 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7457 */
7458
7459 log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007460 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007461 f_sleep(0.5);
7462
7463 f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor",
7464 "handover any to arfcn 871 bsic 11",
7465 false);
7466 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",
7467 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007468 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007469 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007470}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007471testcase TC_ho_neighbor_config_3() runs on test_CT {
7472 var MSC_ConnHdlr vc_conn;
7473 f_init(3, true, guard_timeout := 50.0);
7474 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007475 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007476 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
7477 vc_conn.done;
7478
7479 /* f_tc_ho_neighbor_config_start() */
7480 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7481 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7482
7483 /* 3.a */
7484 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7485 f_ctrs_bsc_and_bts_add(0, "handover:error");
7486
7487 /* 3.b */
7488 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7489 * handover quickly by sending a Handover Failure message. */
7490 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7491 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7492 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7493 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007494 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7495 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007496
7497 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007498 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007499}
7500
Neels Hofmeyr91401012019-07-11 00:42:35 +02007501private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
7502 f_tc_ho_neighbor_config_start();
7503
7504 /*
7505 * bts 0 ARFCN 871 BSIC 10
7506 * bts 1 ARFCN 871 BSIC 11
7507 * bts 2 ARFCN 871 BSIC 12
7508 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7509 */
7510
7511 log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007512 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007513 f_sleep(0.5);
7514
7515 f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor",
7516 "handover any to arfcn 871 bsic 11",
7517 false);
7518 f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor",
7519 "handover any to arfcn 871 bsic 12",
7520 false);
7521 f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
7522 "handover any to arfcn 123 bsic 45",
7523 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007524 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007525}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007526testcase TC_ho_neighbor_config_4() runs on test_CT {
7527 var MSC_ConnHdlr vc_conn;
7528 f_init(3, true, guard_timeout := 50.0);
7529 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007530 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007531 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
7532 vc_conn.done;
7533
7534 /* f_tc_ho_neighbor_config_start() */
7535 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7536 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7537
7538 /* 4.a */
7539 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7540 f_ctrs_bsc_and_bts_add(0, "handover:error");
7541
7542 /* 4.b */
7543 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7544 f_ctrs_bsc_and_bts_add(0, "handover:error");
7545
7546 /* 4.c */
7547 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7548 * handover quickly by timing out after the Handover Required message */
7549 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7550 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7551 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7552 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7553
7554 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007555 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007556}
7557
Neels Hofmeyr91401012019-07-11 00:42:35 +02007558private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
7559 f_tc_ho_neighbor_config_start();
7560
7561 /*
7562 * bts 0 ARFCN 871 BSIC 10
7563 * bts 1 ARFCN 871 BSIC 11
7564 * bts 2 ARFCN 871 BSIC 12
7565 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7566 */
7567
7568 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 +02007569 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007570 f_sleep(0.5);
7571
7572 f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
7573 "handover any to arfcn 871 bsic 12",
7574 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007575 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007576}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007577testcase TC_ho_neighbor_config_5() runs on test_CT {
7578 var MSC_ConnHdlr vc_conn;
7579 f_init(3, true);
7580 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007581 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007582 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
7583 vc_conn.done;
7584
7585 /* f_tc_ho_neighbor_config_start() */
7586 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7587 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7588
7589 /* 5 */
7590 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7591 * handover quickly by timing out after the Handover Required message */
7592 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7593 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7594 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7595 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7596
7597 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007598 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007599}
7600
Neels Hofmeyr91401012019-07-11 00:42:35 +02007601private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
7602 f_tc_ho_neighbor_config_start();
7603
7604 /*
7605 * bts 0 ARFCN 871 BSIC 10
7606 * bts 1 ARFCN 871 BSIC 11
7607 * bts 2 ARFCN 871 BSIC 12
7608 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7609 */
7610
7611 log("f_tc_ho_neighbor_config: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:"
7612 & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007613 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "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("6.a", "HO to 871-12 is ambiguous = error",
7617 "handover any to arfcn 871 bsic 12",
7618 false);
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_6() 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_6));
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 /* 6.a */
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:error");
7638
7639 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007640 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007641}
7642
Neels Hofmeyr91401012019-07-11 00:42:35 +02007643private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
7644 f_tc_ho_neighbor_config_start();
7645
7646 /*
7647 * bts 0 ARFCN 871 BSIC 10
7648 * bts 1 ARFCN 871 BSIC 11
7649 * bts 2 ARFCN 871 BSIC 12
7650 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7651 */
7652
7653 log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:"
7654 & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007655 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007656 f_sleep(0.5);
7657
7658 f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
7659 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007660 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007661 f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
7662 "handover any to arfcn 123 bsic 45",
7663 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007664 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007665}
Neels Hofmeyr91401012019-07-11 00:42:35 +02007666testcase TC_ho_neighbor_config_7() runs on test_CT {
7667 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf2b88032020-06-16 00:35:04 +02007668 f_init(3, true, guard_timeout := 50.0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007669 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007670 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007671 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
7672 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007673
7674 /* f_tc_ho_neighbor_config_start() */
7675 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7676 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7677
7678 /* 7.a */
7679 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7680 * handover quickly by sending a Handover Failure message. */
7681 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7682 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7683 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7684 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007685 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7686 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007687
7688 /* 7.b */
7689 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7690 * handover quickly by timing out after the Handover Required message */
7691 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7692 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7693 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7694 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7695
7696 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007697 f_shutdown_helper(ho := true);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007698}
7699
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007700/* OS#3041: Open and close N connections in a normal fashion, and expect no
7701 * BSSMAP Reset just because of that. */
7702testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
7703 var default d;
7704 var integer i;
7705 var DchanTuple dt;
7706
7707 f_init();
7708
7709 /* Wait for initial BSSMAP Reset to pass */
7710 f_sleep(4.0);
7711
7712 d := activate(no_bssmap_reset());
7713
7714 /* Setup up a number of connections and RLSD them again from the MSC
7715 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7716 * Let's do it some more times for good measure. */
Harald Weltec3260d92018-06-11 17:48:16 +02007717 for (i := 0; i < 4; i := i+1) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007718 /* Since we're doing a lot of runs, give each one a fresh
7719 * T_guard from the top. */
7720 T_guard.start;
7721
7722 /* Setup a BSSAP connection and clear it right away. This is
7723 * the MSC telling the BSC about a planned release, it's not an
7724 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007725 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007726
7727 /* MSC disconnects (RLSD). */
7728 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
7729 }
7730
7731 /* In the buggy behavior, a timeout of 2 seconds happens between above
7732 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7733 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7734 f_sleep(4.0);
7735
7736 deactivate(d);
7737 f_shutdown_helper();
7738}
Harald Welte552620d2017-12-16 23:21:36 +01007739
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007740/* OS#3041: Open and close N connections in a normal fashion, and expect no
7741 * BSSMAP Reset just because of that. Invoke the release by a BSSMAP Clear from
7742 * the MSC. */
7743testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
7744 var default d;
7745 var integer i;
7746 var DchanTuple dt;
7747 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007748 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
7749 var BssmapCause cause := enum2int(cause_val);
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. */
7761 for (i := 0; i < 8; i := i+1) {
7762 /* 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 Hofmeyr4ff93282018-03-12 04:25:35 +01007770
7771 /* Instruct BSC to clear channel */
7772 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7773
7774 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007775 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007776 }
7777
7778 /* In the buggy behavior, a timeout of 2 seconds happens between above
7779 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7780 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7781 f_sleep(4.0);
7782
7783 deactivate(d);
7784 f_shutdown_helper();
7785}
7786
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007787/* OS#3041: Open and close N connections in a normal fashion, and expect no
7788 * BSSMAP Reset just because of that. Close connections from the MS side with a
7789 * Release Ind on RSL. */
7790testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
7791 var default d;
7792 var integer i;
7793 var DchanTuple dt;
7794 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007795 var integer j;
7796
7797 f_init();
7798
7799 /* Wait for initial BSSMAP Reset to pass */
7800 f_sleep(4.0);
7801
7802 d := activate(no_bssmap_reset());
7803
7804 /* Setup up a number of connections and RLSD them again from the MSC
7805 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7806 * Let's do it some more times for good measure. */
7807 for (i := 0; i < 8; i := i+1) {
7808 /* Since we're doing a lot of runs, give each one a fresh
7809 * T_guard from the top. */
7810 T_guard.start;
7811
7812 /* Setup a BSSAP connection and clear it right away. This is
7813 * the MSC telling the BSC about a planned release, it's not an
7814 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007815 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007816
7817 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007818 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007819
7820 /* expect Clear Request on MSC side */
7821 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
7822
7823 /* Instruct BSC to clear channel */
7824 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
7825 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7826
7827 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007828 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007829 }
7830
7831 /* In the buggy behavior, a timeout of 2 seconds happens between above
7832 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7833 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7834 f_sleep(4.0);
7835
7836 deactivate(d);
7837 f_shutdown_helper();
7838}
7839
Harald Welte94e0c342018-04-07 11:33:23 +02007840/***********************************************************************
7841 * IPA style dynamic PDCH
7842 ***********************************************************************/
7843
7844private function f_dyn_ipa_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7845 template (omit) RSL_Cause nack := omit)
7846runs on test_CT {
7847 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7848 var RSL_Message rsl_unused;
7849 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7850 f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
7851 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007852 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007853 if (istemplatekind(nack, "omit")) {
7854 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007855 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007856 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007857 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007858 }
7859}
7860
7861private function f_dyn_ipa_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7862 template (omit) RSL_Cause nack := omit)
7863runs on test_CT {
7864 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7865 var RSL_Message rsl_unused;
7866 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7867 f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
7868 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007869 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_DEACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007870 if (istemplatekind(nack, "omit")) {
7871 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007872 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007873 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007874 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007875 }
7876}
7877
7878private function f_ts_dyn_mode_get(integer bts_nr, integer trx_nr, integer ts_nr)
7879runs on test_CT return charstring {
7880 var charstring cmd, resp;
7881 cmd := "show timeslot "&int2str(bts_nr)&" "&int2str(trx_nr)&" "&int2str(ts_nr);
Stefan Sperlingcff13562018-11-13 15:24:06 +01007882 return f_vty_transceive_match_regexp_retry(BSCVTY, cmd, "*\((*)\)*", 0, 4, 1.0);
Harald Welte94e0c342018-04-07 11:33:23 +02007883}
7884
7885private function f_ts_dyn_mode_assert(integer bts_nr, integer trx_nr, integer ts_nr,
7886 template charstring exp)
7887runs on test_CT {
7888 var charstring mode := f_ts_dyn_mode_get(bts_nr, trx_nr, ts_nr);
7889 if (not match(mode, exp)) {
7890 setverdict(fail, "Unexpected TS Mode: ", mode);
Daniel Willmannafce8662018-07-06 23:11:32 +02007891 mtc.stop;
Harald Welte94e0c342018-04-07 11:33:23 +02007892 }
7893}
7894
7895private function f_ts_set_chcomb(integer bts_nr, integer trx_nr, integer ts_nr, charstring chcomb)
7896runs on test_CT {
7897 f_vty_enter_cfg_ts(BSCVTY, bts_nr, trx_nr, ts_nr);
7898 f_vty_transceive(BSCVTY, "phys_chan_config " & chcomb);
7899 f_vty_transceive(BSCVTY, "end");
7900}
7901
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007902
7903private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
7904 var integer i;
7905 for (i := 0; i < 8; i := i + 1) {
7906 f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
7907 }
7908}
7909
Harald Welte94e0c342018-04-07 11:33:23 +02007910private const charstring TCHF_MODE := "TCH/F mode";
7911private const charstring TCHH_MODE := "TCH/H mode";
7912private const charstring PDCH_MODE := "PDCH mode";
7913private const charstring NONE_MODE := "NONE mode";
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007914private const charstring SDCCH8_MODE := "SDCCH8 mode";
Harald Welte94e0c342018-04-07 11:33:23 +02007915
7916/* Test IPA PDCH activation / deactivation triggered by VTY */
7917testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
7918 var RSL_Message rsl_unused;
7919
7920 /* change Timeslot 6 before f_init() starts RSL */
7921 f_init_vty();
7922 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7923 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7924
7925 f_init(1, false);
7926 f_sleep(1.0);
7927
7928 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7929
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007930 log("TCH/F_PDCH pchan starts out in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007931 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7932 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007933 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7934 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007935 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007936 log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007937 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7938
7939 /* De-activate it via VTY */
7940 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7941 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007942 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007943 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7944
7945 /* re-activate it via VTY */
7946 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn);
7947 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007948 log("TCH/F_PDCH pchan, PDCH ACT via VTY, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007949 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7950
7951 /* and finally de-activate it again */
7952 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7953 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007954 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007955 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7956
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007957 /* clean up config */
7958 f_ts_set_chcomb(0, 0, 6, "PDCH");
7959
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007960 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007961}
7962
7963/* Test IPA PDCH activation NACK */
7964testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
7965 var RSL_Message rsl_unused;
7966
7967 /* change Timeslot 6 before f_init() starts RSL */
7968 f_init_vty();
7969 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7970 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7971
7972 f_init(1, false);
7973 f_sleep(1.0);
7974
7975 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7976
7977 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7978 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007979 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7980 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007981 f_sleep(1.0);
7982 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7983
7984 /* De-activate it via VTY */
7985 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7986 f_sleep(1.0);
7987 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7988
7989 /* re-activate it via VTY, but fail that; check BSC still assumes TCH/F mode */
7990 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn, RSL_ERR_EQUIPMENT_FAIL);
7991 f_sleep(1.0);
7992 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7993
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007994 /* clean up config */
7995 f_ts_set_chcomb(0, 0, 6, "PDCH");
7996
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007997 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007998}
7999
8000
8001/***********************************************************************
8002 * Osmocom style dynamic PDCH
8003 ***********************************************************************/
8004
8005private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
8006 template (omit) RSL_Cause nack := omit)
8007runs on test_CT {
8008 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
8009 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02008010 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02008011 /* FIXME: no VTY command to activate Osmocom PDCH !! */
8012 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008013 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT(chan_nr, ?));
Harald Welte94e0c342018-04-07 11:33:23 +02008014 if (istemplatekind(nack, "omit")) {
8015 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008016 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02008017 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008018 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02008019 }
8020}
8021
8022private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
8023 template (omit) RSL_Cause nack := omit)
8024runs on test_CT {
8025 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
8026 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02008027 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02008028 /* FIXME: no VTY command to activate Osmocom PDCH !! */
8029 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008030 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008031 if (istemplatekind(nack, "omit")) {
8032 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008033 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008034 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008035 //f_ipa_tx(ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02008036 }
8037}
8038
8039/* Test Osmocom dyn PDCH activation / deactivation triggered by VTY */
8040testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
8041 var RSL_Message rsl_unused;
8042
8043 /* change Timeslot 6 before f_init() starts RSL */
8044 f_init_vty();
8045 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8046 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8047
8048 f_init(1, false);
8049 f_sleep(1.0);
8050
8051 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8052
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008053 log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02008054 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8055 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008056 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008057
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008058 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02008059 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008060 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 +02008061 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
8062
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008063 /* clean up config */
8064 f_ts_set_chcomb(0, 0, 6, "PDCH");
8065
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008066 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008067}
8068
8069/* Test Osmocom dyn PDCH activation NACK behavior */
8070testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
8071 var RSL_Message rsl_unused;
8072
8073 /* change Timeslot 6 before f_init() starts RSL */
8074 f_init_vty();
8075 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8076 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8077
8078 f_init(1, false);
8079 f_sleep(1.0);
8080
8081 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8082
8083 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8084 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008085 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008086
8087 /* NACK this activation and expect the "show timeslot" mode still to be NONE */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008088 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte94e0c342018-04-07 11:33:23 +02008089 f_sleep(1.0);
8090 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8091
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008092 /* clean up config */
8093 f_ts_set_chcomb(0, 0, 6, "PDCH");
8094
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008095 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008096}
8097
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008098/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
8099testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
8100 var RSL_Message rsl_unused, rsl_msg;
8101 var DchanTuple dt;
8102 var BSSAP_N_CONNECT_ind rx_c_ind;
8103
8104 /* change Timeslot 6 before f_init() starts RSL */
8105 f_init_vty();
8106 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8107 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8108
8109 f_init(1, false);
8110 f_sleep(1.0);
8111
8112 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8113
8114 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8115 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8116 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008117 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008118
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008119 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008120 f_sleep(1.0);
8121 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8122 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8123
8124 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8125 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008126 var DchanTuples sdcch_cleanup := {};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008127 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008128 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008129 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008130 sdcch_cleanup := sdcch_cleanup & { dt };
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008131 }
8132
8133 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008134 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8135 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8136 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008137
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008138 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008139 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008140 dt.idx := {0, 0};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008141
8142 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008143 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8144 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008145 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
8146
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008147 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 +02008148 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8149 dt.sccp_conn_id := rx_c_ind.connectionId;
8150 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8151
8152 /* Instruct BSC to clear channel */
8153 var BssmapCause cause := 0;
8154 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008155 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008156
8157 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008158 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8159 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008160 f_sleep(1.0);
8161 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8162
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008163 /* Clean up SDCCH lchans */
8164 for (i := 0; i < lengthof(sdcch_cleanup); i := i + 1) {
8165 f_perform_clear_test_ct(sdcch_cleanup[i]);
8166 }
8167
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008168 /* clean up config */
8169 f_ts_set_chcomb(0, 0, 6, "PDCH");
8170
8171 f_shutdown_helper();
8172}
8173
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008174/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
8175testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
8176 var ASP_RSL_Unitdata rsl_ud;
8177 var integer i;
8178 var integer chreq_total, chreq_nochan;
8179
8180 f_init_vty();
8181 for (i := 1; i < 8; i := i + 1) {
8182 if (i == 2) {
8183 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8184 } else {
8185 f_ts_set_chcomb(0, 0, i, "PDCH");
8186 }
8187 }
8188 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8189
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008190 f_init(1, guard_timeout := 60.0);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008191
8192 /* The dyn TS want to activate PDCH mode, ACK that. */
8193 var RslChannelNr chan_nr;
8194 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008195 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
8196 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008197
8198 f_sleep(1.0);
8199
8200 /* Exhaust all dedicated SDCCH lchans.
8201 /* GSM 44.018 Table 9.1.8.2:
8202 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
8203 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008204 var DchanTuples chan_cleanup := {};
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008205 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008206 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 +02008207 }
8208
8209 /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008210 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 +02008211 /* Also occupy the seven other SDCCH of the dyn TS */
8212 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008213 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 +01008214 }
8215
8216 /* Clean up SDCCH lchans */
8217 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8218 f_perform_clear_test_ct(chan_cleanup[i]);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008219 }
8220
8221 /* clean up config */
8222 f_ts_reset_chcomb(0);
8223
8224 f_shutdown_helper();
8225}
8226
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008227/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
8228 SDCCH8 would end up in having no free TCH, then BSC should decide to activate
8229 it as TCH directly instead. SYS#5309. */
8230testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
8231 var RSL_Message rsl_unused, rsl_msg;
8232 var DchanTuple dt;
8233 var BSSAP_N_CONNECT_ind rx_c_ind;
8234 var integer i;
8235
8236 /* change Timeslot 6 before f_init() starts RSL */
8237 f_init_vty();
8238 for (i := 1; i < 8; i := i + 1) {
8239 if (i == 6) {
8240 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8241 } else {
8242 f_ts_set_chcomb(0, 0, i, "PDCH");
8243 }
8244 }
8245 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8246
8247 f_init(1, false);
8248 f_sleep(1.0);
8249
8250 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8251
8252 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8253 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8254 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008255 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008256
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008257 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008258 f_sleep(1.0);
8259 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8260 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8261
8262 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8263 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008264 var DchanTuples chan_cleanup := {};
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02008265 var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008266 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008267 dt := f_est_dchan(ra, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008268 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008269 }
8270
8271 /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008272 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
8273 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8274 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008275
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008276 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008277 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008278 dt.idx := {0, 0};
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008279
8280 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008281 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8282 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008283 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
8284
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008285 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 +02008286 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8287 dt.sccp_conn_id := rx_c_ind.connectionId;
8288 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8289
8290 /* Instruct BSC to clear channel */
8291 var BssmapCause cause := 0;
8292 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008293 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008294
8295 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008296 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8297 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008298 f_sleep(1.0);
8299 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8300
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008301 /* Clean up SDCCH lchans */
8302 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8303 f_perform_clear_test_ct(chan_cleanup[i]);
8304 }
8305
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008306 /* clean up config */
8307 f_ts_reset_chcomb(0);
8308 /* TODO: clean up other channels? */
8309
8310 f_shutdown_helper();
8311}
8312
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008313/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
8314testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
8315 var RSL_Message rsl_unused, rsl_msg;
8316 var DchanTuple dt;
8317 var BSSAP_N_CONNECT_ind rx_c_ind;
8318 var GsmRrMessage rr;
8319
8320 /* change Timeslot 6 before f_init() starts RSL */
8321 f_init_vty();
8322 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8323 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8324
8325 f_init(1, false);
8326 f_sleep(1.0);
8327
8328 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8329
8330 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8331 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8332 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008333 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008334
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008335 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008336 f_sleep(1.0);
8337 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8338 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8339
8340 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8341 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008342 var DchanTuples chan_cleanup := {};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008343 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008344 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008345 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008346 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008347 }
8348
8349 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008350 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8351 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8352 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008353
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008354 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008355 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008356 dt.idx := {0, 0};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008357
8358 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008359 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
8360 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008361 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
8362 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
8363 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
8364 }
8365
8366 /* FIXME? Currently the TS stays in state BORKEN: */
8367
8368 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008369 /* rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8370 * f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008371 * f_sleep(1.0);
8372 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
8373 */
8374
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008375 /* Clean up SDCCH lchans */
8376 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8377 f_perform_clear_test_ct(chan_cleanup[i]);
8378 }
8379
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008380 /* clean up config */
8381 f_ts_set_chcomb(0, 0, 6, "PDCH");
8382
8383 f_shutdown_helper();
8384}
8385
Stefan Sperling0796a822018-10-05 13:01:39 +02008386testcase TC_chopped_ipa_ping() runs on test_CT {
Stefan Sperling554123f2018-10-09 14:12:30 +02008387 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port, mp_bsc_ctrl_port};
Stefan Sperling0796a822018-10-05 13:01:39 +02008388 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8389 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8390 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008391 f_shutdown_helper();
Stefan Sperling0796a822018-10-05 13:01:39 +02008392}
8393
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008394testcase TC_chopped_ipa_payload() runs on test_CT {
8395 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port
8396 /* TODO: mp_bsc_ctrl_port does not work yet */};
8397 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8398 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8399 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008400 f_shutdown_helper();
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008401}
8402
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008403/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
8404 the BTS does autonomous MS power control loop */
8405testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
8406 var MSC_ConnHdlr vc_conn;
8407 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8408 //pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
8409 pars.exp_ms_power_params := true;
8410
8411 f_init(1, true);
8412 f_sleep(1.0);
8413 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
8414 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008415 f_shutdown_helper();
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008416}
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008417
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008418/* Verify activation and deactivation of the BCCH carrier power reduction mode */
8419testcase TC_c0_power_red_mode() runs on test_CT {
8420 f_init(1);
8421
8422 for (var integer red := 6; red >= 0; red := red - 2) {
8423 /* Configure BCCH carrier power reduction mode via the VTY */
8424 f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
8425
8426 /* Expect Osmocom specific BS Power Control message on the RSL */
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03008427 var template (present) RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008428 chan_nr := t_RslChanNr_BCCH(0),
8429 bs_power := tr_RSL_IE_BS_Power(red / 2));
8430 tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008431 var RSL_Message unused := f_exp_ipa_rx(tr_rsl_pdu);
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008432
8433 /* Additionally verify the applied value over the CTRL interface */
8434 var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
8435 if (cred != int2str(red)) {
8436 setverdict(fail, "Unexpected BCCH carrier power reduction value ",
8437 cred, " (expected ", red, ")");
8438 }
8439 }
8440
8441 f_shutdown_helper();
8442}
8443
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008444/***********************************************************************
8445 * MSC Pooling
8446 ***********************************************************************/
8447
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008448template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
Harald Weltebf397612021-01-14 20:39:46 +01008449 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 +02008450
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008451private 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 +02008452runs on MSC_ConnHdlr {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008453 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008454 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008455 f_logp(BSCVTY, "Got RSL RR Release");
8456 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008457 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008458 f_logp(BSCVTY, "Got RSL Deact SACCH");
8459 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008460 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008461 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008462 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8463 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008464 break;
8465 }
8466 }
8467}
8468
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008469private altstep as_mgcp_ack_all_dlcx() runs on MSC_ConnHdlr {
8470 var MgcpCommand mgcp_cmd;
Oliver Smithab7354b2023-05-08 11:34:30 +02008471 var template MgcpMessage msg_dlcx := {
8472 command := tr_DLCX
8473 }
8474 var MGCP_RecvFrom mrf;
8475
8476 [g_pars.aoip] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008477 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
8478 repeat;
8479 }
Oliver Smithab7354b2023-05-08 11:34:30 +02008480
8481 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
8482 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
8483 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
8484 }));
8485 repeat;
8486 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008487}
8488
8489private altstep as_rsl_ack_all_rel_req() runs on MSC_ConnHdlr {
8490 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
8491 [] RSL.receive(tr_RSL_REL_REQ(g_chan_nr, ?)) {
8492 RSL.send(ts_RSL_REL_CONF(g_chan_nr, main_dcch));
8493 repeat;
8494 }
8495}
8496
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008497friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
8498 template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02008499runs on MSC_ConnHdlr {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008500 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8501 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008502 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008503 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8504 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008505 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008506 f_logp(BSCVTY, "Got RSL RR Release");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008507 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008508 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008509 f_logp(BSCVTY, "Got RSL Deact SACCH");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008510 }
8511 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008512 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008513 /* Also drop the SCCP connection */
8514 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8515 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008516 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008517 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008518 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8519 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008520 }
8521 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008522 deactivate(ack_dlcx);
8523 deactivate(ack_rel_req);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008524}
8525
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01008526friend function f_perform_clear_no_rr_rel(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC)
8527runs on MSC_ConnHdlr {
8528 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8529 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
8530 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8531 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8532 interleave {
8533 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
8534 f_logp(BSCVTY, "Got RSL Deact SACCH");
8535 }
8536 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
8537 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8538 /* Also drop the SCCP connection */
8539 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8540 }
8541 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
8542 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
8543 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8544 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
8545 }
8546 }
8547 deactivate(ack_dlcx);
8548 deactivate(ack_rel_req);
8549}
8550
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01008551friend function f_perform_clear_no_lchan()
8552runs on MSC_ConnHdlr {
8553 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8554 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8555 BSSAP.receive(tr_BSSMAP_ClearComplete);
8556 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8557 /* Also drop the SCCP connection */
8558 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8559}
8560
Vadim Yanitskiy65d879d2022-06-23 18:15:39 +07008561friend function f_perform_clear_test_ct(DchanTuple dt)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008562 runs on test_CT
8563{
8564 /* Instruct BSC to clear channel */
8565 var BssmapCause cause := 0;
8566 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008567 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008568}
8569
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008570private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
8571 template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008572runs on MSC_ConnHdlr {
8573 timer T := 10.0;
8574 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
8575
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008576 f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008577 f_create_bssmap_exp(l3_enc);
8578
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008579 /* RSL_Emulation.f_chan_est() on rsl_pt:
8580 * This is basically code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008581 * RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
8582 */
8583 var RSL_Message rx_rsl;
8584 var GsmRrMessage rr;
8585
8586 /* request a channel to be established */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008587 rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008588 /* expect immediate assignment.
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008589 * Code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008590 * rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
8591 */
8592 timer Tt := 10.0;
8593
8594 /* request a channel to be established */
8595 Tt.start;
8596 alt {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008597 [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008598 Tt.stop;
8599 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008600 [] rsl_pt.receive {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008601 setverdict(fail, "Unexpected RSL message on DCHAN");
8602 mtc.stop;
8603 }
8604 [] Tt.timeout {
8605 setverdict(fail, "Timeout waiting for RSL on DCHAN");
8606 mtc.stop;
8607 }
8608 }
8609 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
8610 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008611 rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008612
8613
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008614 if (expect_bssmap_l3) {
8615 f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
8616 var template PDU_BSSAP exp_l3_compl;
8617 exp_l3_compl := tr_BSSMAP_ComplL3()
8618 if (g_pars.aoip == false) {
8619 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
8620 } else {
8621 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
8622 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008623
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008624 var PDU_BSSAP bssap;
8625 T.start;
8626 alt {
8627 [] BSSAP.receive(exp_l3_compl) -> value bssap {
8628 f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
8629 log("rx exp_l3_compl = ", bssap);
8630 }
8631 [] BSSAP.receive(tr_BSSMAP_ComplL3) {
8632 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
8633 }
8634 [] T.timeout {
8635 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
8636 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008637 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008638
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008639 /* start ciphering, if requested */
8640 if (ispresent(g_pars.encr)) {
8641 f_logp(BSCVTY, "start ciphering");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008642 f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008643 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008644 }
8645
8646 if (do_clear) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008647 f_perform_clear(rsl_pt, rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008648 }
8649 setverdict(pass);
8650 f_sleep(1.0);
8651}
8652
8653private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
8654 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8655 if (g_pars.mscpool.rsl_idx == 0) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008656 f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008657 } else if (g_pars.mscpool.rsl_idx == 1) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008658 f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008659 } else if (g_pars.mscpool.rsl_idx == 2) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008660 f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008661 }
8662}
8663
8664/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
8665private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
8666 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008667 f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
8668 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 +02008669 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)) );
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008670 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 +02008671}
8672testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
8673
8674 f_init(1, true);
8675 f_sleep(1.0);
8676 var MSC_ConnHdlr vc_conn;
8677 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008678
8679 f_ctrs_msc_init();
8680
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008681 vc_conn := f_start_handler(refers(f_tc_mscpool_L3Compl_on_1_msc), pars);
8682 vc_conn.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008683
8684 f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008685 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008686}
8687
8688/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
8689/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8690 * just as well using only RSL. */
8691testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
8692
8693 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8694 f_sleep(1.0);
8695
8696 /* Control which MSC gets chosen next by the round-robin, otherwise
8697 * would be randomly affected by which other tests ran before this. */
8698 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8699
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008700 f_ctrs_msc_init();
8701
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008702 var MSC_ConnHdlr vc_conn1;
8703 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8704 pars1.mscpool.rsl_idx := 0;
8705 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8706 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8707 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008708 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008709
8710 var MSC_ConnHdlr vc_conn2;
8711 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8712 pars2.mscpool.rsl_idx := 1;
8713 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8714 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8715 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008716 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008717
8718 /* Test round-robin wrap to the first MSC */
8719 var MSC_ConnHdlr vc_conn3;
8720 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8721 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008722 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008723 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8724 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008725 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008726 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008727}
8728
8729/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 0
8730 * (configured in osmo-bsc.cfg). */
8731/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8732 * just as well using only RSL. */
8733testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
8734
8735 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8736 f_sleep(1.0);
8737
8738 /* Control which MSC gets chosen next by the round-robin, otherwise
8739 * would be randomly affected by which other tests ran before this. */
8740 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8741
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008742 f_ctrs_msc_init();
8743
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008744 var MSC_ConnHdlr vc_conn1;
8745 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8746 pars1.mscpool.rsl_idx := 0;
8747 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8748 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8749 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008750 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008751
8752 var MSC_ConnHdlr vc_conn2;
8753 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8754 pars2.mscpool.rsl_idx := 1;
8755 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8756 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8757 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008758 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008759
8760 /* Test round-robin wrap to the first MSC */
8761 var MSC_ConnHdlr vc_conn3;
8762 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8763 pars3.mscpool.rsl_idx := 2;
8764 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8765 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8766 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008767 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008768 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008769}
8770
8771/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
8772 * (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
8773 * NULL-NRI setting is stronger than that. */
8774/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8775 * just as well using only RSL. */
8776testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
8777
8778 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8779 f_sleep(1.0);
8780
8781 /* Control which MSC gets chosen next by the round-robin, otherwise
8782 * would be randomly affected by which other tests ran before this. */
8783 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8784
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008785 f_ctrs_msc_init();
8786
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008787 var MSC_ConnHdlr vc_conn1;
8788 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8789 pars1.mscpool.rsl_idx := 0;
8790 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8791 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8792 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008793 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008794
8795 var MSC_ConnHdlr vc_conn2;
8796 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8797 pars2.mscpool.rsl_idx := 1;
8798 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8799 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8800 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008801 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008802
8803 /* Test round-robin wrap to the first MSC */
8804 var MSC_ConnHdlr vc_conn3;
8805 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8806 pars3.mscpool.rsl_idx := 2;
8807 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8808 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8809 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008810 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008811 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008812}
8813
8814/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
8815 * assigned to any MSC (configured in osmo-bsc.cfg). */
8816/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8817 * just as well using only RSL. */
8818testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test_CT {
8819
8820 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8821 f_sleep(1.0);
8822
8823 /* Control which MSC gets chosen next by the round-robin, otherwise
8824 * would be randomly affected by which other tests ran before this. */
8825 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8826
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008827 f_ctrs_msc_init();
8828
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008829 var MSC_ConnHdlr vc_conn1;
8830 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8831 pars1.mscpool.rsl_idx := 0;
8832 /* An NRI that is not assigned to any MSC */
8833 pars1.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(1023))));
8834 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8835 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008836 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008837
8838 var MSC_ConnHdlr vc_conn2;
8839 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8840 pars2.mscpool.rsl_idx := 1;
8841 /* An NRI that is not assigned to any MSC */
8842 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(768)), '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:new");
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 /* An NRI that is not assigned to any MSC */
8852 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, valueof(ts_MI_TMSI_NRI_LV(819))));
8853 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8854 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008855 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008856 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008857}
8858
8859/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
8860 * assigned to an MSC that is currently not connected (configured in osmo-bsc.cfg). */
8861/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8862 * just as well using only RSL. */
8863testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
8864
8865 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8866 f_sleep(1.0);
8867
8868 /* Control which MSC gets chosen next by the round-robin, otherwise
8869 * would be randomly affected by which other tests ran before this. */
8870 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8871
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008872 f_ctrs_msc_init();
8873
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008874 var MSC_ConnHdlr vc_conn1;
8875 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8876 pars1.mscpool.rsl_idx := 0;
8877 /* An NRI that is assigned to an unconnected MSC */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008878 pars1.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(512)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008879 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8880 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008881 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8882 f_ctrs_msc_add(0, "mscpool:subscr:new");
8883 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008884
8885 var MSC_ConnHdlr vc_conn2;
8886 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8887 pars2.mscpool.rsl_idx := 1;
8888 /* An NRI that is assigned to an unconnected MSC */
8889 pars2.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(767))));
8890 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8891 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008892 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8893 f_ctrs_msc_add(1, "mscpool:subscr:new");
8894 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008895
8896 /* Test round-robin wrap to the first MSC */
8897 var MSC_ConnHdlr vc_conn3;
8898 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8899 pars3.mscpool.rsl_idx := 2;
8900 /* An NRI that is assigned to an unconnected MSC */
8901 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(750)), '00F110'O));
8902 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8903 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008904 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8905 f_ctrs_msc_add(0, "mscpool:subscr:new");
8906 f_ctrs_msc_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008907 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008908}
8909
8910/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
8911 * osmo-bsc.cfg). */
8912/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8913 * just as well using only RSL. */
8914testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
8915
8916 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8917 f_sleep(1.0);
8918
8919 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
8920 * this is not using round-robin. */
8921 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8922
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008923 f_ctrs_msc_init();
8924
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008925 var MSC_ConnHdlr vc_conn1;
8926 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8927 pars1.mscpool.rsl_idx := 0;
8928 /* An NRI of the second MSC's range (256-511) */
8929 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(256))));
8930 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8931 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008932 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008933
8934 var MSC_ConnHdlr vc_conn2;
8935 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8936 pars2.mscpool.rsl_idx := 1;
8937 /* An NRI of the second MSC's range (256-511) */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008938 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(260)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008939 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8940 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008941 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008942
8943 var MSC_ConnHdlr vc_conn3;
8944 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8945 pars3.mscpool.rsl_idx := 2;
8946 /* An NRI of the second MSC's range (256-511) */
8947 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(511)), '00F110'O));
8948 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8949 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008950 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008951 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008952}
8953
8954/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
8955 * while a round-robin remains unaffected by that. */
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_2() runs on test_CT {
8959
8960 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8961 f_sleep(1.0);
8962
8963 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
8964 * this is not using round-robin. */
8965 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
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 := 2);
8971 pars1.mscpool.rsl_idx := 0;
8972 /* An NRI of the third MSC's range (512-767) */
8973 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(512))));
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(2, "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 := 2);
8980 pars2.mscpool.rsl_idx := 1;
8981 /* An NRI of the third MSC's range (512-767) */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008982 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(678)));
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(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008986
8987 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
8988 var MSC_ConnHdlr vc_conn3;
8989 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8990 pars3.mscpool.rsl_idx := 2;
8991 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000013'H)), '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:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008995 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008996}
8997
8998/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
8999/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
9000 * just as well using only RSL. */
9001testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
9002
9003 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9004 f_sleep(1.0);
9005
9006 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
9007 * instead, and hits msc 0. */
9008 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9009
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009010 f_ctrs_msc_init();
9011
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009012 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-bsc.cfg */
9013 var MSC_ConnHdlr vc_conn1;
9014 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9015 pars1.mscpool.rsl_idx := 0;
9016 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(260)), '99F999'O));
9017 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9018 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009019 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009020
9021 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
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 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(555)), '00F110'O));
9026 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9027 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009028 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009029 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009030}
9031
9032/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
9033 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9034private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
9035 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9036 //cid_list := { cIl_allInBSS := ''O };
9037 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9038 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9039 var BSSAP_N_UNITDATA_req paging;
9040 var hexstring imsi := '001010000000123'H;
9041
9042 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9043
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009044 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009045 valueof(ts_BSSMAP_Paging(imsi, cid_list, omit, bssmap_chneed))));
9046 BSSAP.send(paging);
9047
9048 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9049 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9050 * channel number is picked here. */
9051 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9052 f_rslem_register(0, new_chan_nr);
9053 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(imsi)));
9054 f_rslem_unregister(0, new_chan_nr);
9055
9056 /* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
9057 * causes this Paging Response to go to the first MSC (bssap_idx := 0). */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009058 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV(imsi)) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009059 f_sleep(1.0);
9060}
9061testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
9062 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9063 f_sleep(1.0);
9064
9065 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9066 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9067 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
9068
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009069 f_ctrs_msc_init();
9070
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009071 var MSC_ConnHdlr vc_conn1;
9072 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9073 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009074 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9075 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009076 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
9077 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009078 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009079 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009080}
9081
9082/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
9083 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9084private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
9085 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9086 //cid_list := { cIl_allInBSS := ''O };
9087 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9088 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9089 var integer nri_v := 300; /* <-- second MSC's NRI */
Harald Weltebf397612021-01-14 20:39:46 +01009090 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009091 var BSSAP_N_UNITDATA_req paging;
9092
9093 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9094
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009095 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009096 valueof(ts_BSSMAP_Paging('001010000000011'H, cid_list, tmsi, bssmap_chneed))));
9097 BSSAP.send(paging);
9098
9099 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9100 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9101 * channel number is picked here. */
9102 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9103 f_rslem_register(0, new_chan_nr);
9104 RSL.receive(tr_RSL_PAGING_CMD(t_MI_TMSI(tmsi)));
9105 f_rslem_unregister(0, new_chan_nr);
9106
9107 /* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
9108 * third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
9109 * the first MSC (bssap_idx := 0). */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009110 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_TMSI_NRI_LV(nri_v)) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009111 f_sleep(1.0);
9112}
9113testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
9114 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9115 f_sleep(1.0);
9116
9117 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9118 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9119 f_vty_transceive(BSCVTY, "mscpool roundrobin next 2");
9120
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009121 f_ctrs_msc_init();
9122
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009123 var MSC_ConnHdlr vc_conn1;
9124 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9125 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009126 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9127 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009128 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
9129 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009130 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009131 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009132}
9133
9134/* For round-robin, skip an MSC that has 'no allow-attach' set. */
9135/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
9136 * just as well using only RSL. */
9137testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
9138
9139 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9140 f_sleep(1.0);
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009141 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9142 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009143
9144 /* Control which MSC gets chosen next by the round-robin, otherwise
9145 * would be randomly affected by which other tests ran before this. */
9146 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9147
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009148 f_ctrs_msc_init();
9149
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009150 var MSC_ConnHdlr vc_conn1;
9151 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9152 pars1.mscpool.rsl_idx := 0;
9153 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9154 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9155 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009156 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009157
9158 var MSC_ConnHdlr vc_conn2;
9159 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9160 pars2.mscpool.rsl_idx := 1;
9161 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9162 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9163 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009164 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009165
9166 var MSC_ConnHdlr vc_conn3;
9167 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
9168 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009169 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009170 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9171 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009172 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009173 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009174}
9175
9176/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
9177 * TMSI NRI. */
9178testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
9179
9180 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9181 f_sleep(1.0);
9182
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009183 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9184 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
9185
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009186 /* Control which MSC gets chosen next by the round-robin, otherwise
9187 * would be randomly affected by which other tests ran before this. */
9188 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9189
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009190 f_ctrs_msc_init();
9191
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009192 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
9193 var MSC_ConnHdlr vc_conn1;
9194 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
9195 pars1.mscpool.rsl_idx := 0;
9196 /* An NRI of the second MSC's range (256-511) */
9197 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_TMSI_NRI_LV(260))));
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(1, "mscpool:subscr:known");
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 := 0);
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(0, "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 := 2);
9212 pars3.mscpool.rsl_idx := 2;
9213 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000003'H))));
9214 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(2, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009217 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009218}
9219
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009220/* When an MSC point-code gets an SCCP N-PCSTATE saying it is unreachable, immediately mark the MSC as unusable. */
9221testcase TC_mscpool_sccp_n_pcstate_detaches_msc() runs on test_CT {
9222
9223 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
9224 f_sleep(1.0);
9225
9226 /* Control which MSC gets chosen next by the round-robin, otherwise
9227 * would be randomly affected by which other tests ran before this. */
9228 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9229
9230 f_ctrs_msc_init();
9231
9232 var MSC_ConnHdlr vc_conn1;
9233 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9234 pars1.mscpool.rsl_idx := 0;
9235 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9236 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9237 vc_conn1.done;
9238 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9239
9240 var MSC_ConnHdlr vc_conn2;
9241 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
9242 pars2.mscpool.rsl_idx := 1;
9243 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9244 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9245 vc_conn2.done;
9246 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9247
9248 f_logp(BSCVTY, "disconnecting msc0");
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009249 f_bssap_idx_disconnect(0);
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009250
9251 /* Now round-robin would wrap to the first MSC, but since the first MSC is disconnected, it wraps around to msc
9252 * 2 again. */
9253 var MSC_ConnHdlr vc_conn3;
9254 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
9255 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009256 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009257 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9258 vc_conn3.done;
9259 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9260 f_shutdown_helper();
9261}
9262
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009263/* When an MSC point-code gets an SCCP N-PCSTATE saying it is now reachable, immediately trigger RESET and bring up the
9264 * MSC. */
9265testcase TC_mscpool_sccp_n_pcstate_attaches_msc() runs on test_CT {
9266
9267 f_init(nr_bts := 3, handler_mode := true, nr_msc := 1);
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 /* There is only one MSC, round robin stays on msc0 */
9277 var MSC_ConnHdlr vc_conn1;
9278 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9279 pars1.mscpool.rsl_idx := 0;
9280 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('0010100230000001'H)), '00F110'O));
9281 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9282 vc_conn1.done;
9283 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9284
9285 var MSC_ConnHdlr vc_conn2;
9286 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9287 pars2.mscpool.rsl_idx := 1;
9288 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010023000002'H))));
9289 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9290 vc_conn2.done;
9291 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9292
9293 f_logp(BSCVTY, "connecting msc1");
9294 f_vty_msc_allow_attach(BSCVTY, { true, true });
9295 f_bssap_idx_init(1);
9296 f_sleep(1.0);
9297
9298 /* This time round-robin wraps to the second MSC, because it is now online. */
9299 var MSC_ConnHdlr vc_conn4;
9300 var TestHdlrParams pars4 := f_gen_test_hdlr_pars(bssap_idx := 1);
9301 pars4.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009302 pars4.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010023000003'H)));
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009303 vc_conn4 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars4);
9304 vc_conn4.done;
9305 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9306
9307 f_shutdown_helper();
9308}
9309
Philipp Maier783681c2020-07-16 16:47:06 +02009310/* Allow/Deny emergency calls globally via VTY */
9311private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
9312 f_vty_enter_cfg_msc(BSCVTY, 0);
9313 if (allow) {
9314 f_vty_transceive(BSCVTY, "allow-emergency allow");
9315 } else {
9316 f_vty_transceive(BSCVTY, "allow-emergency deny");
9317 }
9318 f_vty_transceive(BSCVTY, "exit");
9319 f_vty_transceive(BSCVTY, "exit");
9320}
9321
9322/* Allow/Deny emergency calls per BTS via VTY */
9323private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
9324 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9325 if (allow) {
9326 f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
9327 } else {
9328 f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
9329 }
9330 f_vty_transceive(BSCVTY, "exit");
9331 f_vty_transceive(BSCVTY, "exit");
Neels Hofmeyrb6ed80c2020-10-12 22:52:39 +00009332 f_vty_transceive(BSCVTY, "exit");
Philipp Maier783681c2020-07-16 16:47:06 +02009333}
9334
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02009335/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
9336private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
9337 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9338 if (allow) {
9339 f_vty_transceive(BSCVTY, "srvcc fast-return allow");
9340 } else {
9341 f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
9342 }
9343 f_vty_transceive(BSCVTY, "exit");
9344 f_vty_transceive(BSCVTY, "exit");
9345 f_vty_transceive(BSCVTY, "exit");
9346}
9347
Pau Espin Pedrol14475352021-07-22 15:48:16 +02009348/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
9349private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
9350 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9351 if (allow) {
9352 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
9353 } else {
9354 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
9355 }
9356 f_vty_transceive(BSCVTY, "exit");
9357 f_vty_transceive(BSCVTY, "exit");
9358 f_vty_transceive(BSCVTY, "exit");
9359}
9360
Pau Espin Pedrol35609792023-01-03 16:56:59 +01009361/* Begin assignment procedure and send an EMERGENCY SETUP (RR) */
Philipp Maier783681c2020-07-16 16:47:06 +02009362private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
9363 var PDU_ML3_MS_NW emerg_setup;
9364 var octetstring emerg_setup_enc;
9365 var RSL_Message emerg_setup_data_ind;
9366
9367 f_establish_fully(omit, omit);
9368
9369 emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
9370 emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
9371 emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
9372
9373 RSL.send(emerg_setup_data_ind);
9374}
9375
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009376/* expect EmergencySetup on BSSAP after calling f_assignment_emerg_setup() */
9377private function f_assignment_emerg_setup_exp_bssap()
9378runs on MSC_ConnHdlr {
Philipp Maier783681c2020-07-16 16:47:06 +02009379 var PDU_BSSAP emerg_setup_data_ind_bssap;
9380 var PDU_ML3_MS_NW emerg_setup;
9381 timer T := 3.0;
9382
Philipp Maier783681c2020-07-16 16:47:06 +02009383 T.start;
9384 alt {
9385 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
9386 emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
9387 if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
9388 setverdict(fail, "no emergency setup");
9389 }
9390 }
9391 [] BSSAP.receive {
9392 setverdict(fail, "unexpected BSSAP message!");
9393 }
9394 [] T.timeout {
9395 setverdict(fail, "timout waiting for EMERGENCY SETUP!");
9396 }
9397 }
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009398}
9399
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009400private function f_assignment_emerg_setup_voice()
9401runs on MSC_ConnHdlr {
9402 /* Go on with voice call assignment */
9403 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
9404 var PDU_BSSAP ass_cmd := f_gen_ass_req();
9405
9406 /* Below speechOrDataIndicator and codecList are copied from an emergency call captured during tests.
9407 * They seem a bit weird (AMR-WB, and the order differ between speechId_DataIndicator and the codecList), but
9408 * seems a good idea to see how osmo-bsc reacts to this. */
9409 ass_cmd.pdu.bssmap.assignmentRequest.channelType := {
9410 elementIdentifier := '0B'O, /* overwritten */
9411 lengthIndicator := 0, /* overwritten */
9412 speechOrDataIndicator := '0001'B, /* speech */
9413 spare1_4 := '0000'B,
9414 channelRateAndType := ChRate_TCHForH_Fpref,
9415 speechId_DataIndicator := 'c2918105'O
9416 };
9417 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({
9418 ts_CodecHR, ts_CodecAMR_WB, ts_CodecEFR, ts_CodecFR}));
9419
9420 f_rslem_dchan_queue_enable();
9421
9422 var ExpectCriteria mgcpcrit := {
9423 connid := omit,
9424 endpoint := omit,
9425 transid := omit
9426 };
9427 f_create_mgcp_expect(mgcpcrit);
9428
9429 BSSAP.send(ass_cmd);
9430
9431 var AssignmentState st := valueof(ts_AssignmentStateInit);
Oliver Smithce2dd692023-04-17 10:25:50 +02009432 st.rtp_stream := true;
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009433 st.is_assignment := false;
9434 alt {
9435 [] as_modify(st);
9436 [] as_Media();
9437 [st.modify_done] BSSAP.receive(exp_compl) {
9438 setverdict(pass);
9439 }
9440 }
9441
9442 /* Voice call carries on ... */
9443 f_sleep(2.0);
9444}
9445
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009446/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
9447 * CALLS are permitted by the BSC config. */
9448private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
9449
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009450 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
9451 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
9452 * another lchan. */
9453 g_pars.ra := f_rnd_ra_emerg();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009454 f_assignment_emerg_setup();
9455 f_assignment_emerg_setup_exp_bssap();
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009456 f_assignment_emerg_setup_voice();
Philipp Maier783681c2020-07-16 16:47:06 +02009457
9458 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009459 f_perform_clear();
Philipp Maier783681c2020-07-16 16:47:06 +02009460}
9461
9462/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
9463 * forbidden by the BSC config. */
9464private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
9465 var PDU_BSSAP emerg_setup_data_ind_bssap;
9466 timer T := 3.0;
9467
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009468 f_assignment_emerg_setup();
Philipp Maier783681c2020-07-16 16:47:06 +02009469
9470 T.start;
9471 alt {
9472 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
9473 setverdict(pass);
9474 }
9475 [] RSL.receive {
9476 setverdict(fail, "unexpected RSL message!");
9477 }
9478 [] T.timeout {
9479 setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
9480 }
9481 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009482 BSSAP.receive(tr_BSSMAP_ClearRequest);
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01009483 f_perform_clear_no_rr_rel();
Philipp Maier783681c2020-07-16 16:47:06 +02009484}
9485
9486/* EMERGENCY CALL situation #1, allowed globally and by BTS */
9487testcase TC_assignment_emerg_setup_allow() runs on test_CT {
9488 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9489 var MSC_ConnHdlr vc_conn;
9490
9491 f_init(1, true);
9492 f_sleep(1.0);
9493
9494 f_vty_allow_emerg_msc(true);
9495 f_vty_allow_emerg_bts(true, 0);
9496 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9497 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009498 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009499}
9500
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +01009501/* Test MO emergency call using MobileIdentity=IMEI (possible for emergency
9502 * calls from phones without SIM card).
9503 * 3GPP TS 24.008 section 10.5.1.4, OS#5849 */
9504testcase TC_assignment_emerg_setup_allow_imei() runs on test_CT {
9505 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9506 var MSC_ConnHdlr vc_conn;
9507
9508 /* Remove IMSI set by f_gen_test_hdlr_pars(), then IMEI will be used to place the call */
9509 pars.imsi := omit;
9510
9511 f_init(1, true);
9512 f_sleep(1.0);
9513
9514 f_vty_allow_emerg_msc(true);
9515 f_vty_allow_emerg_bts(true, 0);
9516 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9517 vc_conn.done;
9518 f_shutdown_helper();
9519}
9520
Philipp Maier783681c2020-07-16 16:47:06 +02009521/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
9522testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
9523 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9524 var MSC_ConnHdlr vc_conn;
9525
9526 f_init(1, true);
9527 f_sleep(1.0);
9528
9529 f_vty_allow_emerg_msc(false);
9530 f_vty_allow_emerg_bts(true, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009531 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx): */
9532 pars.ra := f_rnd_ra_emerg();
Philipp Maier783681c2020-07-16 16:47:06 +02009533 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9534 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009535 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009536}
9537
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009538/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS.
9539 * The RACH req (and hence CHAN RQD) indicate other than emergency call.
9540 * Hence BSC only learns about it being an emergency call later during call setup.
9541 * If interested in the ra="emergency call" + deny bts policy case,
9542 * see TC_chan_rqd_emerg_deny.
9543 */
Philipp Maier783681c2020-07-16 16:47:06 +02009544testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
9545 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9546 var MSC_ConnHdlr vc_conn;
9547
9548 /* Note: This simulates a spec violation by the MS, correct MS
9549 * implementations would not try to establish an emergency call because
9550 * the system information tells in advance that emergency calls are
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009551 * not allowed */
Philipp Maier783681c2020-07-16 16:47:06 +02009552
9553 f_init(1, true);
9554 f_sleep(1.0);
9555
9556 f_vty_allow_emerg_msc(true);
9557 f_vty_allow_emerg_bts(false, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009558 /* Note: Here we implicitly leave default g_pars.ra which is different than "emergency call" */
Philipp Maier783681c2020-07-16 16:47:06 +02009559 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9560 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009561 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009562}
9563
Philipp Maier82812002020-08-13 18:48:27 +02009564/* Test what happens when an emergency call arrives while all TCH channels are
9565 * busy, the BSC is expected to terminate one call in favor of the incoming
9566 * emergency call */
9567testcase TC_emerg_premption() runs on test_CT {
9568 var ASP_RSL_Unitdata rsl_ud;
9569 var integer i;
9570 var integer chreq_total, chreq_nochan;
9571 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009572 var octetstring l3_payload := gen_l3_valid_payload();
Philipp Maier82812002020-08-13 18:48:27 +02009573
9574 f_init(1);
9575 f_sleep(1.0);
9576
9577 f_vty_allow_emerg_msc(true);
9578 f_vty_allow_emerg_bts(true, 0);
9579
9580 /* Fill up all channels on the BTS */
9581 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
9582 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
9583 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 +02009584 f_chreq_act_ack('33'O, i);
Philipp Maier82812002020-08-13 18:48:27 +02009585 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009586 IPA_RSL[0][0].clear;
Philipp Maier82812002020-08-13 18:48:27 +02009587 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
9588 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
9589
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009590 /* Send EST IND for the first TCH, so we get to test the RR release cause */
9591 var RslChannelNr first_tch := valueof(t_RslChanNr_Bm(1));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009592 f_ipa_tx(ts_RSL_EST_IND(first_tch, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009593
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009594 /* Accept BSSAP conn, so we get to test the Clear Request cause */
9595 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009596 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009597 var integer sccp_conn_id := rx_c_ind.connectionId;
9598 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
9599
Philipp Maier82812002020-08-13 18:48:27 +02009600 /* Send Channel request for emegergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009601 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier82812002020-08-13 18:48:27 +02009602
9603 /* Expect the BSC to release one (the first) TCH/F on the BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009604 f_expect_chan_rel(first_tch, expect_rr_chan_rel := true, expect_rll_rel_req := false,
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009605 expect_rr_cause := GSM48_RR_CAUSE_PREMPTIVE_REL);
Philipp Maier82812002020-08-13 18:48:27 +02009606
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009607 /* Also expect a BSSMAP Clear Request with PREEMPTION */
9608 var BSSAP_N_DATA_ind rx_clear_req;
9609 const myBSSMAP_Cause preemption := GSM0808_CAUSE_PREEMPTION;
9610 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_clear_req;
9611 log("XXX ", rx_clear_req);
9612 if (rx_clear_req.userData.pdu.bssmap.clearRequest.cause.causeValue != int2bit(enum2int(preemption), 7)) {
9613 setverdict(fail, "BSSMAP Clear Request: expected cause PREEMPTION");
9614 }
9615
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009616 /* Expect the BSC to send activate/assign the channel for the emergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009617 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009618 if (first_tch != rx_rsl.ies[0].body.chan_nr) {
9619 setverdict(fail, "different TCH lchan activated than expected");
9620 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009621 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(first_tch, 33));
9622 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Philipp Maier104f4c02020-09-11 18:12:18 +02009623
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009624 /* complete the BSSMAP Clear to satisfy the conn leak check */
9625 BSSAP.send(ts_BSSAP_DATA_req(sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(preemption))));
9626 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearComplete)) {
9627 BSSAP.send(ts_BSSAP_DISC_req(sccp_conn_id, 0));
9628 }
9629
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009630 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009631}
9632
9633/* Hopping parameters per a timeslot */
Vadim Yanitskiybc6654a2020-09-13 01:27:40 +07009634private type record length(0..64) of GsmArfcn ArfcnList;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009635private type record FHParamsTs {
9636 boolean enabled,
9637 uint6_t hsn,
9638 uint6_t maio,
9639 ArfcnList ma
9640};
9641
9642/* Hopping parameters per a transceiver */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009643private type record FHParamsTrx {
Philipp Maier798d8952021-10-19 14:43:19 +02009644 GsmBandArfcn arfcn,
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009645 FHParamsTs ts[8]
9646};
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009647
9648/* Randomly generate the hopping parameters for the given timeslot numbers */
9649private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
9650runs on test_CT return FHParamsTrx {
9651 var FHParamsTrx fhp;
9652
Philipp Maier798d8952021-10-19 14:43:19 +02009653 /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
9654 * fall in the GSM900 band. */
9655 fhp.arfcn.arfcn := f_rnd_int(3);
9656 fhp.arfcn.pcs := false;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009657
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009658 for (var integer tn := 0; tn < 8; tn := tn + 1) {
9659 if (not match(tn, tr_tn)) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009660 fhp.ts[tn].enabled := false;
9661 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009662 continue;
9663 }
9664
9665 /* Random HSN / MAIO values: 0..63 */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009666 fhp.ts[tn].hsn := f_rnd_int(64);
9667 fhp.ts[tn].maio := f_rnd_int(64);
9668 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009669
9670 /* Random Mobile Allocation (hopping channels) */
9671 var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
9672 var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
9673 for (var integer i := 1; i <= ma_len; i := i + 1) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009674 fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009675 }
9676
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009677 fhp.ts[tn].enabled := true;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009678 }
9679
9680 log("f_TC_fh_params_gen(): ", fhp);
9681 return fhp;
9682}
9683
9684/* Make sure that the given Channel Description IE matches the hopping configuration */
9685private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
9686{
9687 var template (present) ChannelDescription tr_cd;
9688 var template (present) MaioHsn tr_maio_hsn;
9689 var uint3_t tn := cd.chan_nr.tn;
9690
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009691 if (fhp.ts[tn].enabled) {
9692 tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009693 tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
9694 } else {
Philipp Maier798d8952021-10-19 14:43:19 +02009695 tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009696 }
9697
9698 if (not match(cd, tr_cd)) {
9699 setverdict(fail, "Channel Description IE does not match: ",
9700 cd, " vs expected ", tr_cd);
9701 }
9702}
9703
9704/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
9705private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
9706 in MobileAllocationLV ma)
9707{
9708 var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
9709
9710 if (not match(ma, tr_ma)) {
9711 setverdict(fail, "Mobile Allocation IE does not match (tn := ",
9712 tn, "): ", ma, " vs expected: ", tr_ma);
9713 } else {
9714 setverdict(pass);
9715 }
9716}
9717
9718private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
9719 in MobileAllocationLV ma)
9720return template MobileAllocationLV {
9721 /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009722 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009723 return { len := 0, ma := ''B };
9724 }
9725
9726 var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
9727 var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
9728 var bitstring ma_mask := ''B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009729
9730 /* Compose the full bit-mask (all channels, up to 1024 entries) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009731 for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
9732 for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
9733 if (full_mask[fhp.ts[i].ma[j]] == '1'B)
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009734 { continue; }
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009735 full_mask[fhp.ts[i].ma[j]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009736 }
9737 }
9738
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009739 /* Take ARFCN of the TRX itself into account */
Philipp Maier798d8952021-10-19 14:43:19 +02009740 full_mask[fhp.arfcn.arfcn] := '1'B;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009741
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009742 /* Compose a bit-mask for the given timeslot number */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009743 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9744 slot_mask[fhp.ts[tn].ma[i]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009745 }
9746
9747 /* Finally, compose the Mobile Allocation bit-mask */
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009748 for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009749 if (full_mask[i] != '1'B)
9750 { continue; }
9751
9752 /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
9753 if (slot_mask[i] == '1'B) {
9754 ma_mask := ma_mask & '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009755 } else {
9756 ma_mask := ma_mask & '0'B;
9757 }
9758 }
9759
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009760 /* ARFCN 0 (if present) goes to the last position of the bit-mask */
9761 if (full_mask[0] == '1'B) {
9762 /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
9763 if (slot_mask[0] == '1'B) {
9764 ma_mask := ma_mask & '1'B;
9765 } else {
9766 ma_mask := ma_mask & '0'B;
9767 }
9768 }
9769
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009770 /* Ensure that ma_mask is octet-aligned */
Vadim Yanitskiy2aa02522020-09-06 14:05:23 +07009771 var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009772 ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
9773
9774 return { len := ma_mask_len, ma := ma_mask };
9775}
9776
Philipp Maier798d8952021-10-19 14:43:19 +02009777/* Configure the appropriate band for a given arfcn, exc */
9778private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
9779{
9780 var charstring band;
9781 var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
9782
9783 select (arfcn_) {
9784 case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
9785 case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
9786 case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
9787 case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
9788 case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
9789 case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
9790 case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
9791 case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
9792 case else { return; }
9793 }
9794
9795 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9796 f_vty_transceive(BSCVTY, "band " & band);
9797 f_vty_transceive(BSCVTY, "end");
9798}
9799
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009800/* Configure the hopping parameters in accordance with the given record */
9801private function f_TC_fh_params_set(in FHParamsTrx fhp,
9802 uint8_t bts_nr := 0,
9803 uint8_t trx_nr := 0)
9804runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009805
9806 f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
9807
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009808 /* Enter the configuration node for the given BTS/TRX numbers */
9809 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9810
Philipp Maier798d8952021-10-19 14:43:19 +02009811 f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009812
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009813 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009814 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9815
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009816 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009817 f_vty_transceive(BSCVTY, "hopping enabled 0");
9818 f_vty_transceive(BSCVTY, "exit"); /* go back */
9819 continue;
9820 }
9821
9822 /* Configure HSN / MAIO values */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009823 f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
9824 f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009825
9826 /* Configure the Mobile Allocation (hopping channels) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009827 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9828 f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009829 }
9830
9831 f_vty_transceive(BSCVTY, "hopping enabled 1");
9832 f_vty_transceive(BSCVTY, "exit"); /* go back */
9833 }
9834
9835 f_vty_transceive(BSCVTY, "end");
9836}
9837
9838/* Disable frequency hopping on all timeslots */
9839private function f_TC_fh_params_unset(in FHParamsTrx fhp,
9840 uint8_t bts_nr := 0,
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009841 uint8_t trx_nr := 0,
Philipp Maier798d8952021-10-19 14:43:19 +02009842 GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009843runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009844
9845 f_TC_set_band_by_arfcn(bts_nr, arfcn);
9846
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009847 /* Enter the configuration node for the given BTS/TRX numbers */
9848 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9849
Philipp Maier798d8952021-10-19 14:43:19 +02009850 f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009851
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009852 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009853 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9854
9855 /* Delete all ARFCNs from the Mobile Allocation (if any) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009856 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9857 f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009858 }
9859
9860 f_vty_transceive(BSCVTY, "hopping enabled 0");
9861 f_vty_transceive(BSCVTY, "exit"); /* go back */
9862 }
9863
9864 f_vty_transceive(BSCVTY, "end");
9865 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9866}
9867
9868/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
9869 * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
9870testcase TC_fh_params_chan_activ() runs on test_CT {
9871 var FHParamsTrx fhp := f_TC_fh_params_gen();
9872 var RSL_Message rsl_msg;
9873 var RSL_IE_Body ie;
9874
9875 f_init_vty();
9876
9877 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9878 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9879
9880 f_init(1);
9881
9882 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9883 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009884 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9885 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009886
9887 /* Make sure that Channel Identification IE is present */
9888 if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
9889 setverdict(fail, "RSL Channel Identification IE is absent");
9890 continue;
9891 }
9892
9893 /* Make sure that hopping parameters (HSN/MAIO) match */
9894 f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
9895
9896 /* "Mobile Allocation shall be included but empty" - let's check this */
9897 if (ie.chan_ident.ma.v.len != 0) {
9898 setverdict(fail, "Mobile Allocation IE is not empty: ",
9899 ie.chan_ident.ma, ", despite it shall be");
9900 continue;
9901 }
9902 }
9903
9904 /* Disable frequency hopping */
9905 f_TC_fh_params_unset(fhp);
9906
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009907 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009908}
9909
9910/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
9911testcase TC_fh_params_imm_ass() runs on test_CT {
9912 var FHParamsTrx fhp := f_TC_fh_params_gen();
9913 var RSL_Message rsl_msg;
9914 var RSL_IE_Body ie;
9915
9916 f_init_vty();
9917
9918 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9919 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9920
9921 f_init(1);
9922
9923 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9924 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009925 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9926 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009927
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009928 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9929 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009930
9931 /* Make sure that Full Immediate Assign Info IE is present */
9932 if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
9933 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
9934 continue;
9935 }
9936
9937 /* Decode the actual Immediate Assignment message */
9938 var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
9939 if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
9940 setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
9941 continue;
9942 }
9943
9944 /* Make sure that hopping parameters (HSN/MAIO) match */
9945 f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
9946
9947 /* Make sure that the Mobile Allocation IE matches */
9948 f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
9949 rr_msg.payload.imm_ass.mobile_allocation);
9950 }
9951
9952 /* Disable frequency hopping */
9953 f_TC_fh_params_unset(fhp);
Philipp Maier82812002020-08-13 18:48:27 +02009954
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009955 f_shutdown_helper();
Philipp Maier82812002020-08-13 18:48:27 +02009956}
9957
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009958/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
9959testcase TC_fh_params_assignment_cmd() runs on test_CT {
9960 var FHParamsTrx fhp := f_TC_fh_params_gen();
9961 var RSL_Message rsl_msg;
9962 var RSL_IE_Body ie;
9963
9964 f_init_vty();
9965
9966 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9967 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9968
9969 f_init(1);
9970
9971 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02009972 vc_MGCP[0].stop;
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009973
9974 var template PDU_BSSAP ass_cmd := f_gen_ass_req();
9975 ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
9976
9977 /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
9978 * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
9979 for (var integer i := 0; i < 3; i := i + 1) {
9980 /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009981 var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009982
9983 /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
9984 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009985 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009986
9987 /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009988 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9989 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009990
9991 /* Make sure that L3 Information IE is present */
9992 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9993 setverdict(fail, "RSL L3 Information IE is absent");
9994 continue;
9995 }
9996
9997 /* Decode the L3 message and make sure it is (RR) Assignment Command */
9998 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9999 if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
10000 setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
10001 continue;
10002 }
10003
10004 /* Make sure that hopping parameters (HSN/MAIO) match */
10005 var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
10006 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10007
10008 /* Make sure that Cell Channel Description IE is present if FH is enabled */
10009 if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
Vadim Yanitskiy38d069d2020-09-02 17:18:57 +070010010 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010011 continue;
10012 }
10013
10014 /* Make sure that the Mobile Allocation IE matches (if present) */
10015 var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
10016 if (chan_desc.h and ma_present) {
10017 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10018 l3_msg.payload.ass_cmd.mobile_allocation.v);
10019 } else if (chan_desc.h and not ma_present) {
10020 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10021 continue;
10022 } else if (not chan_desc.h and ma_present) {
10023 setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
10024 continue;
10025 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010026
10027 f_perform_clear_test_ct(dt);
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010028 }
10029
10030 /* Give the IUT some time to release all channels */
10031 f_sleep(3.0);
10032
10033 /* Disable frequency hopping */
10034 f_TC_fh_params_unset(fhp);
10035
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010036 f_shutdown_helper();
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010037}
10038
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010039/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
10040private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
10041runs on test_CT {
10042 var RSL_Message rsl_msg;
10043 var RSL_IE_Body ie;
10044 var DchanTuple dt;
10045
10046 /* Establish a dedicated channel, so we can trigger handover */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010010047 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyc18ff472021-11-18 20:15:37 +030010048 f_sleep(0.5);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010049
10050 /* Trigger handover from BTS0 to BTS1 */
10051 f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
10052 f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
10053
10054 /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010055 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx := {1, 0});
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010056
10057 /* ACKnowledge channel activation and expect (RR) Handover Command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010058 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33), idx := {1, 0});
10059 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010060
10061 /* Make sure that L3 Information IE is present */
10062 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
10063 setverdict(fail, "RSL L3 Information IE is absent");
10064 return;
10065 }
10066
10067 /* Decode the L3 message and make sure it is (RR) Handover Command */
10068 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
10069 if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
10070 setverdict(fail, "Failed to match Handover Command: ", l3_msg);
10071 return;
10072 }
10073
10074 /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
10075 var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
10076 if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
10077 setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
10078 return;
10079 }
10080
10081 /* Make sure that hopping parameters (HSN/MAIO) match */
10082 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10083
10084 /* Make sure that Cell Channel Description IE is present */
10085 if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
10086 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
10087 return;
10088 }
10089
10090 /* Make sure that the Mobile Allocation (after time) IE is present and matches */
10091 var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
10092 if (ma_present) {
10093 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10094 l3_msg.payload.ho_cmd.mobile_allocation.v);
10095 } else {
10096 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10097 return;
10098 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010099
10100 f_perform_clear_test_ct(dt);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010101}
10102testcase TC_fh_params_handover_cmd() runs on test_CT {
10103 var FHParamsTrx fhp := f_TC_fh_params_gen();
10104
10105 f_init_vty();
10106
10107 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
10108 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
10109
10110 f_vty_transceive(BSCVTY, "timeslot 0");
10111 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10112 f_vty_transceive(BSCVTY, "exit"); /* go back */
10113
10114 f_vty_transceive(BSCVTY, "timeslot 1");
10115 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
10116 f_vty_transceive(BSCVTY, "end"); /* we're done */
10117
10118 f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
10119 f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
10120
10121 f_init(2);
10122
10123 f_TC_fh_params_handover_cmd(fhp);
10124
10125 /* Disable frequency hopping on BTS1 */
10126 f_TC_fh_params_unset(fhp, 1);
10127
10128 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
10129 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
10130
10131 f_vty_transceive(BSCVTY, "timeslot 0");
10132 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
10133 f_vty_transceive(BSCVTY, "exit"); /* go back */
10134
10135 f_vty_transceive(BSCVTY, "timeslot 1");
10136 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10137 f_vty_transceive(BSCVTY, "end"); /* we're done */
10138
10139 f_shutdown_helper();
10140}
10141
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010142/* Verify the hopping parameters in System Information Type 4 */
10143testcase TC_fh_params_si4_cbch() runs on test_CT {
10144 var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
10145 var ASP_RSL_Unitdata rx_rsl_ud;
10146 timer T := 5.0;
10147
10148 f_init_vty();
10149
10150 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
10151 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10152
10153 f_vty_transceive(BSCVTY, "timeslot 0");
10154 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10155 f_vty_transceive(BSCVTY, "exit"); /* go back */
10156
10157 f_vty_transceive(BSCVTY, "timeslot 1");
10158 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
10159 f_vty_transceive(BSCVTY, "end"); /* we're done */
10160
10161 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
10162 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10163
10164 f_init(1);
10165
10166 T.start;
10167 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010168 [] 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 +070010169 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
10170 var SystemInformation si := dec_SystemInformation(ie.other.payload);
10171
10172 /* Make sure that what we decoded is System Information Type 4 */
10173 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
10174 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
10175 repeat;
10176 }
10177
10178 /* Make sure that CBCH Channel Description IE is present */
10179 if (not ispresent(si.payload.si4.cbch_chan_desc)) {
10180 setverdict(fail, "CBCH Channel Description IE is absent");
10181 break;
10182 }
10183
10184 /* Finally, check the hopping parameters (HSN, MAIO) */
10185 var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
10186 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10187
10188 /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
10189 * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
10190 if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
10191 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10192 break;
10193 } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
10194 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10195 si.payload.si4.cbch_mobile_alloc.v);
10196 }
10197 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010198 [] IPA_RSL[0][0].receive { repeat; }
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010199 [] T.timeout {
10200 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
10201 }
10202 }
10203
10204 /* Disable frequency hopping */
10205 f_TC_fh_params_unset(fhp);
10206
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010207 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010208 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10209
10210 f_vty_transceive(BSCVTY, "timeslot 0");
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010211 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010212 f_vty_transceive(BSCVTY, "exit"); /* go back */
10213
10214 f_vty_transceive(BSCVTY, "timeslot 1");
10215 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10216 f_vty_transceive(BSCVTY, "end"); /* we're done */
10217
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010218 f_shutdown_helper();
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010219}
10220
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010221template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
10222 := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
10223
10224private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
10225 template (present) BSSLAP_PDU expect_bsslap)
10226{
10227 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
10228 if (not match(bsslap, expect_bsslap)) {
10229 log("EXPECTING BSSLAP: ", expect_bsslap);
10230 log("GOT BSSLAP: ", bsslap);
10231 setverdict(fail, "BSSLAP is not as expected");
10232 mtc.stop;
10233 }
10234 setverdict(pass);
10235}
10236
10237/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
10238const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
10239
10240private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
10241 var PDU_BSSAP_LE rx_bsslap;
10242 BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
10243 f_match_bsslap(rx_bsslap, expect_rx_bsslap);
10244}
10245
10246/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10247 * Request on Lb interface. Either with or without the SMLC doing a BSSLAP TA Request. */
10248private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
10249 f_sleep(1.0);
10250
10251 f_establish_fully(omit, omit);
10252 f_bssap_le_register_imsi(g_pars.imsi, omit);
10253
10254 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10255 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10256
10257 var PDU_BSSAP_LE plr;
10258 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10259
10260 if (not do_ta_request) {
10261 /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
10262 var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
10263 if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
10264 log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
10265 log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
10266 setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
10267 mtc.stop;
10268 }
10269 var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
10270 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
10271 if (not match(bsslap, expect_ta_layer3)) {
10272 log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
10273 log("GOT BSSLAP: ", bsslap);
10274 setverdict(fail, "BSSLAP is not as expected");
10275 mtc.stop;
10276 }
10277 /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
10278 * has no need to request the TA from the BSC and directly responds. */
10279 } else {
10280 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10281 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10282 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10283 }
10284
10285 /* SMLC got the TA from the BSC, now responds with geo information data. */
10286 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10287 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10288 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10289
10290 /* The LCS was using an active A-interface conn. It should still remain active after this. */
10291 f_mo_l3_transceive();
10292
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010293 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010294
10295 f_sleep(2.0);
10296 setverdict(pass);
10297}
10298
10299/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10300 * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
10301private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
10302 f_lcs_loc_req_for_active_ms(false);
10303}
10304testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
10305 var MSC_ConnHdlr vc_conn;
10306 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10307
10308 f_init(1, true);
10309 f_sleep(1.0);
10310 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
10311 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010312 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010313}
10314
10315/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10316 * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
10317private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
10318 f_lcs_loc_req_for_active_ms(true);
10319}
10320testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
10321 var MSC_ConnHdlr vc_conn;
10322 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10323
10324 f_init(1, true);
10325 f_sleep(1.0);
10326 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
10327 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010328 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010329}
10330
10331/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
10332 * conn without an active lchan. */
10333private function f_clear_A_conn() runs on MSC_ConnHdlr
10334{
10335 var BssmapCause cause := 0;
10336 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10337 BSSAP.receive(tr_BSSMAP_ClearComplete);
10338 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10339
10340 timer no_more_bssap := 5.0;
10341 no_more_bssap.start;
10342 alt {
10343 [] no_more_bssap.timeout { break; }
10344 [] BSSAP.receive(tr_BSSAP_BSSMAP) {
10345 setverdict(fail, "Expected no more BSSAP after Clear Complete");
10346 mtc.stop;
10347 }
10348 }
10349 setverdict(pass);
10350}
10351
10352/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
10353 * for LCS, for cases where there is only an A conn without an active lchan. */
10354private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
10355{
10356 f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
10357
10358 /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
10359 * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
10360 * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
10361 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10362 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10363 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10364
10365 /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
10366 f_clear_A_conn();
10367 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10368 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10369}
10370
10371/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10372 * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
10373 */
10374private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
10375 f_sleep(1.0);
10376
10377 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10378 f_bssap_le_register_imsi(g_pars.imsi, omit);
10379
10380 /* Register to receive the Paging Command */
10381 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10382 g_chan_nr := new_chan_nr;
10383 f_rslem_register(0, g_chan_nr);
10384
10385 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10386 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10387 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10388 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10389
10390 var PDU_BSSAP_LE plr;
10391 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10392
10393 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10394 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10395
10396 /* OsmoBSC needs to Page */
10397 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
10398 f_logp(BSCVTY, "got Paging Command");
10399
10400 /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
10401 * the MSC, and releases the lchan directly. */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +020010402 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 +020010403 f_expect_lchan_rel(RSL, RSL_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010404
10405 /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
10406
10407 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10408
10409 /* SMLC got the TA from the BSC, now responds with geo information data. */
10410 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10411 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10412
10413 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10414
10415 /* The lchan is gone, the A-interface conn was created for the LCS only.
10416 * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
10417 f_verify_active_A_conn_and_clear();
10418
10419 f_sleep(2.0);
10420 setverdict(pass);
10421}
10422testcase TC_lcs_loc_req_for_idle_ms() runs on test_CT {
10423 var MSC_ConnHdlr vc_conn;
10424 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10425
10426 f_init(1, true);
10427 f_sleep(1.0);
10428
10429 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10430 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10431
10432 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
10433 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010434 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010435}
10436
10437/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
10438 */
10439private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
10440 f_sleep(1.0);
10441
10442 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10443 f_bssap_le_register_imsi(g_pars.imsi, omit);
10444
10445 /* provoke an abort by omitting both IMSI and IMEI */
10446 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10447 valueof(ts_BSSMAP_Perform_Location_Request(omit,
10448 ts_CellId_CGI('262'H, '42'H, 23, 42)))));
10449 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10450
10451 /* BSC tells MSC about failure */
10452 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10453 locationEstimate := omit, positioningData := omit,
10454 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
10455
10456 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10457 f_verify_active_A_conn_and_clear();
10458
10459 f_sleep(2.0);
10460 setverdict(pass);
10461}
10462testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
10463 var MSC_ConnHdlr vc_conn;
10464 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10465
10466 f_init(1, true);
10467 f_sleep(1.0);
10468
10469 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10470 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10471
10472 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
10473 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010474 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010475}
10476
10477/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10478 * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
10479private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
10480 f_sleep(1.0);
10481
10482 f_establish_fully(omit, omit);
10483 f_bssap_le_register_imsi(g_pars.imsi, omit);
10484
10485 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10486 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10487
10488 var PDU_BSSAP_LE plr;
10489 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10490
10491 if (do_ta) {
10492 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10493 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10494 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10495 }
10496
10497 /* SMLC fails to respond, BSC runs into timeout */
10498 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
10499 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10500
10501 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10502 locationEstimate := omit, positioningData := omit,
10503 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
10504
10505 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10506 f_verify_active_A_conn_and_clear();
10507
10508 f_sleep(2.0);
10509 setverdict(pass);
10510}
10511
10512/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10513 * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
10514private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
10515 f_lcs_loc_req_for_active_ms_le_timeout(false);
10516}
10517
10518testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
10519 var MSC_ConnHdlr vc_conn;
10520 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10521
10522 f_init(1, true);
10523 f_sleep(1.0);
10524 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
10525 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010526 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010527}
10528
10529/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10530 * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
10531private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
10532 f_lcs_loc_req_for_active_ms_le_timeout(true);
10533}
10534
10535testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
10536 var MSC_ConnHdlr vc_conn;
10537 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10538
10539 f_init(1, true);
10540 f_sleep(1.0);
10541 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
10542 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010543 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010544}
10545
10546/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
10547private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
10548 f_sleep(1.0);
10549
10550 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10551 f_bssap_le_register_imsi(g_pars.imsi, omit);
10552
10553 /* Register to receive the Paging Command */
10554 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10555 g_chan_nr := new_chan_nr;
10556 f_rslem_register(0, g_chan_nr);
10557
10558 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10559 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10560 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10561 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10562
10563 var PDU_BSSAP_LE plr;
10564 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10565
10566 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10567 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10568
10569 /* OsmoBSC needs to Page */
10570 var PDU_BSSAP_LE rx_bsslap;
10571 alt {
10572 [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
10573 f_logp(BSCVTY, "got Paging Command");
10574 repeat;
10575 }
10576 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10577 /* MS does not respond to Paging, TA Req runs into timeout. */
10578 f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
10579 }
10580 }
10581
10582 /* SMLC responds with failure */
10583 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10584 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10585
10586 /* BSC tells MSC about failure */
10587 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10588 locationEstimate := omit, positioningData := omit,
10589 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
10590
10591 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10592 f_verify_active_A_conn_and_clear();
10593
10594 f_sleep(2.0);
10595 setverdict(pass);
10596}
10597testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
10598 var MSC_ConnHdlr vc_conn;
10599 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10600
10601 f_init(1, true);
10602 f_sleep(1.0);
10603
10604 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10605 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10606
10607 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
10608 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010609 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010610}
10611
10612/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
10613 * over. */
10614private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10615 f_sleep(1.0);
10616
10617 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10618 f_bssap_le_register_imsi(g_pars.imsi, omit);
10619
10620 /* Register to receive the Paging Command */
10621 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10622 g_chan_nr := new_chan_nr;
10623 f_rslem_register(0, g_chan_nr);
10624
10625 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10626 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10627 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10628 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10629
10630 var PDU_BSSAP_LE plr;
10631 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10632
10633 /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
10634 * and establish Layer 3. It should use the existing A-interface conn. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010635 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 +020010636 do_clear := false, expect_bssmap_l3 := true);
10637
10638 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10639 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10640
10641 /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
10642 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10643
10644 /* SMLC got the TA from the BSC, now responds with geo information data. */
10645 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10646 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10647 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10648
10649 /* The lchan should still exist, it was from a CM Service Request. */
10650 f_mo_l3_transceive();
10651
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010652 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010653
10654 f_sleep(2.0);
10655 setverdict(pass);
10656}
10657testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
10658 var MSC_ConnHdlr vc_conn;
10659 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10660
10661 f_init(1, true);
10662 f_sleep(1.0);
10663
10664 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10665 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10666
10667 vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
10668 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010669 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010670}
10671
10672/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
10673 * the new lchan after handover. */
10674private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10675 f_sleep(1.0);
10676
10677 f_establish_fully(omit, omit);
10678 f_bssap_le_register_imsi(g_pars.imsi, omit);
10679
10680 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10681 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10682
10683 var PDU_BSSAP_LE plr;
10684 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10685
10686 /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
10687 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
10688
10689 var HandoverState hs := {
10690 rr_ho_cmpl_seen := false,
10691 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +020010692 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010693 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010694 };
10695 /* issue hand-over command on VTY */
10696 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
10697 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
10698 f_rslem_suspend(RSL1_PROC);
10699
10700 /* From the MGW perspective, a handover is is characterized by
10701 * performing one MDCX operation with the MGW. So we expect to see
10702 * one more MDCX during handover. */
10703 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
10704
10705 alt {
10706 [] as_handover(hs);
10707 }
10708
10709 var PDU_BSSAP_LE rx_bsslap;
10710
10711 interleave {
10712 /* Expect the BSC to inform the MSC about the handover */
10713 [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
10714
10715 /* Expect the BSC to inform the SMLC about the handover */
10716 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10717 f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
10718 }
10719 }
10720
10721 /* SMLC now responds with geo information data. */
10722 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10723 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10724 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10725
10726 /* lchan still active */
10727 f_mo_l3_transceive(RSL1);
10728
10729 /* MSC decides it is done now. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010730 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010731
10732 f_sleep(2.0);
10733 setverdict(pass);
10734}
10735testcase TC_ho_during_lcs_loc_req() runs on test_CT {
10736 var MSC_ConnHdlr vc_conn;
10737 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10738
10739 f_init(2, true);
10740 f_sleep(1.0);
10741 vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
10742 vc_conn.done;
Oliver Smith39f53072022-10-27 14:44:04 +020010743 f_shutdown_helper(ho := true);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010744}
10745
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010746private function f_tc_emerg_call_and_lcs_loc_req(charstring id) runs on MSC_ConnHdlr
10747{
10748 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
10749 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
10750 * another lchan. */
Pau Espin Pedrol1809bce2023-01-03 16:54:41 +010010751 g_pars.ra := f_rnd_ra_emerg();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010752 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010753 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010754
10755 /* Here would usually be a CC Call Proceeding from the MSC, but what does the BSC care about DTAP. */
10756
10757 /* Do a Location Request in-between the CC call setup */
10758 f_bssap_le_register_imsi(g_pars.imsi, omit);
10759 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10760 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10761 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10762 /* SMLC got the TA from the BSC, now responds with geo information data. */
10763 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10764 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10765 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10766
Pau Espin Pedrol14076d32023-01-03 17:07:59 +010010767 f_assignment_emerg_setup_voice();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010768
10769 setverdict(pass);
10770 f_perform_clear();
10771}
10772
10773testcase TC_emerg_call_and_lcs_loc_req() runs on test_CT {
10774 var MSC_ConnHdlr vc_conn;
10775 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10776
10777 f_init(1, true);
10778 f_sleep(1.0);
10779 f_vty_allow_emerg_msc(true);
10780 f_vty_allow_emerg_bts(true, 0);
10781 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req), pars);
10782 vc_conn.done;
10783 f_shutdown_helper();
10784}
10785
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010786private altstep no_bssmap_clear_req() runs on MSC_ConnHdlr {
10787 [] BSSAP.receive(tr_BSSMAP_ClearRequest) {
10788 setverdict(fail, "unexpected BSSMAP Clear Request");
10789 mtc.stop;
10790 }
10791}
10792
10793private type enumerated RslRel {
10794 RSLREL_REL_IND,
10795 RSLREL_CONN_FAIL
10796};
10797
10798private function f_emerg_call_and_lcs_loc_req_early_lchan_release(RslRel rsl_rel) runs on MSC_ConnHdlr
10799{
10800 g_pars.ra := f_rnd_ra_emerg();
10801 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010802 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010803
10804 /* Start a Location Request to locate the emergency */
10805 f_bssap_le_register_imsi(g_pars.imsi, omit);
10806 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10807 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10808 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10809
10810 /* 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
10811 * do a Clear Command when the Location Response arrives. */
10812 activate(no_bssmap_clear_req());
10813
10814 /* the lchan gets interrupted while the Location Request has no response */
10815 select (rsl_rel) {
10816 case (RSLREL_REL_IND) {
10817 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
10818 f_expect_lchan_rel(RSL, RSL_PROC);
10819 }
10820 case (RSLREL_CONN_FAIL) {
10821 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
10822 }
10823 case else {
10824 setverdict(fail, "Unknown RslRel type");
10825 mtc.stop;
10826 }
10827 }
10828
10829 /* Still expect the Location Response to find its way to the MSC. */
10830 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10831 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10832 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10833
10834 setverdict(pass);
10835
10836 select (rsl_rel) {
10837 case (RSLREL_REL_IND) {
10838 f_perform_clear_no_lchan();
10839 }
10840 case (RSLREL_CONN_FAIL) {
10841 f_perform_clear();
10842 }
10843 }
10844}
10845
10846private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind(charstring id) runs on MSC_ConnHdlr
10847{
10848 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_REL_IND);
10849}
10850
10851testcase TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() runs on test_CT {
10852 var MSC_ConnHdlr vc_conn;
10853 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10854
10855 f_init(1, true);
10856 f_sleep(1.0);
10857 f_vty_allow_emerg_msc(true);
10858 f_vty_allow_emerg_bts(true, 0);
10859 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind), pars);
10860 vc_conn.done;
10861 f_shutdown_helper();
10862}
10863
10864private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail(charstring id) runs on MSC_ConnHdlr
10865{
10866 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_CONN_FAIL);
10867}
10868
10869testcase TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() runs on test_CT {
10870 var MSC_ConnHdlr vc_conn;
10871 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10872
10873 f_init(1, true);
10874 f_sleep(1.0);
10875 f_vty_allow_emerg_msc(true);
10876 f_vty_allow_emerg_bts(true, 0);
10877 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail), pars);
10878 vc_conn.done;
10879 f_shutdown_helper();
10880}
10881
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010882/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
10883private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
10884 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10885
10886 /* Also disable attach for the single connected MSC */
10887 f_vty_msc_allow_attach(BSCVTY, { false });
10888
10889 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) ));
10890 f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
10891
10892 /* No MSC is found, expecting a proper release on RSL */
10893 interleave {
10894 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
10895 f_logp(BSCVTY, "Got RSL RR Release");
10896 }
10897 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10898 f_logp(BSCVTY, "Got RSL Deact SACCH");
10899 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010900 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010901 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
10902 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010903 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010904 }
10905 }
10906 setverdict(pass);
10907}
10908testcase TC_no_msc() runs on test_CT {
10909
10910 f_init(1, true);
10911 f_sleep(1.0);
10912 var MSC_ConnHdlr vc_conn;
10913 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10914
10915 f_ctrs_bsc_init(counternames_bsc_mscpool);
10916
10917 vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
10918 vc_conn.done;
10919
10920 f_ctrs_bsc_add("mscpool:subscr:no_msc");
10921 f_ctrs_bsc_verify();
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010922 f_shutdown_helper();
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010923}
10924
Harald Welte0ea2d5e2018-04-07 21:40:29 +020010925/* Dyn PDCH todo:
10926 * activate OSMO as TCH/F
10927 * activate OSMO as TCH/H
10928 * does the BSC-located PCU socket get the updated INFO?
10929 * what if no PCU is connected at the time?
10930 * is the info correct on delayed PCU (re)connect?
10931 */
Harald Welte94e0c342018-04-07 11:33:23 +020010932
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010933private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +020010934 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020010935 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010936
10937 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
10938 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10939 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
10940 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
10941 g_pars.ass_codec_list.codecElements[0];
10942 if (isvalue(g_pars.expect_mr_s0_s7)) {
10943 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
10944 g_pars.expect_mr_s0_s7;
10945 }
10946 }
10947 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
10948 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
10949 log("expecting ASS COMPL like this: ", exp_compl);
10950
10951 f_establish_fully(ass_cmd, exp_compl);
10952
Neels Hofmeyr8746b0d2021-06-01 17:25:39 +020010953 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 +000010954
10955 var RSL_Message rsl;
10956
10957 timer T := 5.0;
10958 T.start;
10959 alt {
10960 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
10961 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
10962 log("Rx L3 from net: ", l3);
10963 if (ischosen(l3.msgs.rrm.channelModeModify)) {
10964 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10965 mtc.stop;
10966 }
10967 }
10968 [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
10969 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10970 mtc.stop;
10971 }
10972 [] T.timeout {
10973 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
10974 setverdict(pass);
10975 }
10976 }
10977 T.stop;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010978
10979 f_perform_clear();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010980}
10981
10982/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
10983 * osmo-bsc. */
10984testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
10985 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10986 var MSC_ConnHdlr vc_conn;
10987
10988 f_init(1, true);
10989 f_sleep(1.0);
10990
10991 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10992 vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
10993 vc_conn.done;
10994 f_shutdown_helper();
10995}
10996
10997/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
10998 */
10999testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
11000 f_init_vty();
11001
11002 f_init(1, false);
11003 f_sleep(1.0);
11004
11005 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
11006
11007 var ASP_RSL_Unitdata rx_rsl_ud;
11008 timer T := 5.0;
11009
11010 T.start;
11011 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011012 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011013 if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
11014 T.stop;
11015 setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
11016 mtc.stop;
11017 }
11018 repeat;
11019 }
11020 [] T.timeout {
11021 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
11022 setverdict(pass);
11023 }
11024 }
11025}
11026
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011027private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
11028 /* First fully set up a speech lchan */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011029 f_assignment_codec(id, do_perform_clear := false);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011030
11031 /* Trigger re-assignment to another lchan */
11032 var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
11033
11034 /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
11035 * one MDCX on MGCP. */
11036 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
11037
11038 /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
11039 * as the old lchan used. */
11040 g_media.bts.ipa_crcx_seen := false;
11041 g_media.bts.ipa_mdcx_seen := false;
11042
11043 /* Send different BTS side RTP port number for the new lchan */
11044 g_media.bts.bts.port_nr := 4223;
11045
11046 f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
11047
11048 /* Trigger re-assignment. */
11049 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
11050
11051 timer T := 5.0;
11052 T.start;
11053 alt {
11054 [] as_assignment(assignment_st);
11055 [] as_Media();
11056 [] T.timeout {
11057 break;
11058 }
11059 }
11060
11061 if (not assignment_st.assignment_done) {
11062 setverdict(fail, "Assignment did not complete");
11063 mtc.stop;
11064 }
11065
11066 f_check_mgcp_expectations()
11067 setverdict(pass);
11068
11069 f_sleep(2.0);
11070 log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
11071
11072 /* Instruct BSC to clear channel */
11073 var BssmapCause cause := 0;
11074 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
11075 interleave {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011076 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
11077 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020011078 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011079 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020011080 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011081 }
11082 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
11083 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11084 }
11085 }
Neels Hofmeyr40a45d12021-09-23 22:57:12 +020011086 f_expect_dlcx_conns();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011087
11088 f_sleep(0.5);
11089}
11090
11091testcase TC_reassignment_fr() runs on test_CT {
11092 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11093 var MSC_ConnHdlr vc_conn;
11094
11095 f_init(1, true);
11096 f_sleep(1.0);
11097
Neels Hofmeyrac432fa2021-11-02 16:45:56 +010011098 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011099
11100 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11101 vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
11102 vc_conn.done;
11103
11104 /* from f_establish_fully() */
11105 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
11106 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
11107 /* from re-assignment */
11108 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
11109 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
11110 f_ctrs_bsc_and_bts_verify();
11111 f_shutdown_helper();
11112}
11113
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011114const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
11115const charstring REEST_CLEAR := "REEST_CLEAR";
11116const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
11117
11118/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
11119 * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
11120 * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
11121 * the MSC as the CM Re-Establishment is handled.
11122 *
11123 * MS bts0 bts1 bsc msc test-component
11124 * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
11125 * | | _1 wait a bit, to settle down
11126 * |<-x x--| | _1 "lose connection"
11127 * | | REEST_LOST_CONNECTION
11128 * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
11129 * | | REEST_CLEAR
11130 * | |<-0---| _1 Clear Command on first A-conn
11131 * | |--0-->| _1 Clear Complete
11132 * | |<----------------->| | _1 Release first channel
11133 * | | REEST_CLEAR_DONE
11134 * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
11135 * |<-----------------|<-------|<-1---| _2 Clear Command, Release
11136 *
11137 */
11138private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
11139 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
11140 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11141
11142 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11143 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11144
11145 f_establish_fully(ass_cmd, exp_compl);
11146
11147 /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
11148 * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
11149 * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
11150 f_sleep(2.0);
11151 COORD.send(REEST_LOST_CONNECTION);
11152
11153 alt {
11154 [] COORD.receive(REEST_CLEAR);
11155 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
11156 setverdict(fail, "Unexpected channel release");
11157 mtc.stop;
11158 }
11159 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
11160 setverdict(fail, "Unexpected channel release");
11161 mtc.stop;
11162 }
11163 }
11164 f_perform_clear()
Neels Hofmeyr969abd02021-09-23 22:24:08 +020011165 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011166 COORD.send(REEST_CLEAR_DONE);
11167}
11168
11169private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
11170 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
11171
11172 /* The MS lost the connection on the first channel, now establishes another one */
11173 COORD.receive(REEST_LOST_CONNECTION);
11174
11175 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
11176 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
11177 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
11178
11179 f_create_bssmap_exp(l3_enc);
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011180 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 +020011181 BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
11182
11183 /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
11184 COORD.send(REEST_CLEAR);
11185 COORD.receive(REEST_CLEAR_DONE);
11186
11187 f_sleep(2.0);
11188
11189 /* Answer the CM Re-Establishment with an Assignment Command. */
11190 var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
11191 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11192 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11193 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11194
11195 var AssignmentState st := valueof(ts_AssignmentStateInit);
Oliver Smithce2dd692023-04-17 10:25:50 +020011196 st.rtp_stream := true;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011197 st.is_assignment := true;
11198
11199 var ExpectCriteria mgcpcrit := {
11200 connid := omit,
11201 endpoint := omit,
11202 transid := omit
11203 };
11204 f_create_mgcp_expect(mgcpcrit);
11205
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011206 f_rslem_dchan_queue_enable(RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011207
11208 BSSAP.send(ass_cmd);
11209
11210 var PDU_BSSAP bssap;
11211
11212 alt {
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011213 [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
11214 [] as_Media_ipacc(RSL1, RSL2);
11215 [] as_Media_mgw();
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011216 [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
11217 break;
11218 }
11219 }
11220
11221 f_sleep(3.0);
11222
11223 f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011224 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011225}
11226
11227testcase TC_cm_reestablishment() runs on test_CT {
11228 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
11229 var MSC_ConnHdlr vc_conn1;
11230
11231 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
11232 var MSC_ConnHdlr vc_conn2;
11233 pars2.imsi := pars1.imsi;
11234 pars2.media_nr := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011235 pars2.expect_tsc := c_BtsParams[1].tsc;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011236
11237 f_init(2, true, guard_timeout := 40.0);
11238 f_sleep(1.0);
11239
11240 vc_conn1 := f_start_handler_create(pars1);
11241 vc_conn2 := f_start_handler_create(pars2);
11242 connect(vc_conn1:COORD, vc_conn2:COORD);
11243 f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
11244 f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
11245 vc_conn1.done;
11246 vc_conn2.done;
11247
11248 f_shutdown_helper();
11249}
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011250
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011251function f_exp_ipa_rx_nonfatal(template (present) RSL_Message t_rx,
11252 boolean ignore_other_rx := true,
11253 BtsTrxIdx idx := {0, 0},
11254 float Tval := 2.0)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011255runs on test_CT return template (omit) RSL_Message {
11256 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011257 timer T := Tval;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011258
11259 T.start;
11260 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011261 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011262 T.stop;
11263 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011264 [ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
11265 [not ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011266 log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
11267 T.stop;
11268 return omit;
11269 }
11270 [] T.timeout {
11271 return omit;
11272 }
11273 }
11274 return rx_rsl_ud.rsl;
11275}
11276
11277private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
11278 f_vty_enter_cfg_bts(pt, bts_nr);
11279 f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
11280 f_vty_transceive(pt, "exit");
11281 f_vty_transceive(pt, "exit");
11282 f_vty_transceive(pt, "exit");
11283}
11284
11285private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +030011286 template (present) RslChannelNr chan_nr := ?,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011287 template (present) uint12_t arfcn := ?,
11288 template (present) uint3_t tsc := ?)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011289{
11290 var RSL_IE_Body full_imm_ass_info;
11291 if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
11292 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
11293 mtc.stop;
11294 }
11295
11296 var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
11297 var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
11298 fn := fn,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011299 ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011300 page_mode := ?);
11301 if (not match(rr_imm_ass, expect_imm_ass)) {
11302 log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
11303 setverdict(fail, "Failed to match Immediate Assignment");
11304 mtc.stop;
11305 }
11306}
11307
11308testcase TC_imm_ass_post_chan_ack() runs on test_CT {
11309 var RSL_Message chan_act;
11310 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011311 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011312
11313 f_init(1, false);
11314 f_sleep(1.0);
11315
11316 /* (should be the default anyway, just to make things clear) */
11317 f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
11318
11319 /* RA containing reason=LU */
11320 var GsmFrameNumber fn := 2342;
11321 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011322 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011323
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011324 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011325
11326 /* First send the Chan Act ACK */
11327 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011328 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011329 var RSL_IE_Body chan_ident_ie;
11330 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11331 setverdict(fail, "RSL Channel Identification IE is absent");
11332 mtc.stop;
11333 }
11334
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011335 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011336
11337 /* Then expect the Immediate Assignment, after we ACKed the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011338 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011339
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011340 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11341 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011342
11343 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011344 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011345
11346 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011347 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011348 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011349 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11350
11351 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011352 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011353 f_shutdown_helper();
11354}
11355
11356testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
11357 var RSL_Message chan_act;
11358 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011359 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011360
11361 f_init(1, false);
11362 f_sleep(1.0);
11363
11364 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11365
11366 /* RA containing reason=LU */
11367 var GsmFrameNumber fn := 2342;
11368 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011369 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011370
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011371 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011372 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011373 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011374 var RSL_IE_Body chan_ident_ie;
11375 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11376 setverdict(fail, "RSL Channel Identification IE is absent");
11377 mtc.stop;
11378 }
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011379
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011380 /* (set bts 0 cfg back to default) */
11381 f_vty_set_imm_ass(BSCVTY);
11382
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011383 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011384 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011385 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11386 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011387
11388 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011389 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011390
11391 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011392 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011393
11394 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011395 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011396 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011397 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11398
11399 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011400 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011401 f_shutdown_helper();
11402}
11403
Neels Hofmeyr23158742021-09-07 19:08:07 +020011404testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
11405 var RSL_Message chan_act;
11406 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011407 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr23158742021-09-07 19:08:07 +020011408
11409 f_init(1, false);
11410 f_sleep(1.0);
11411
11412 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11413
11414 /* RA containing reason=LU */
11415 var GsmFrameNumber fn := 2342;
11416 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011417 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011418
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011419 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011420 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011421 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr23158742021-09-07 19:08:07 +020011422 var RSL_IE_Body chan_ident_ie;
11423 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11424 setverdict(fail, "RSL Channel Identification IE is absent");
11425 mtc.stop;
11426 }
11427
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011428 /* (set bts 0 cfg back to default) */
11429 f_vty_set_imm_ass(BSCVTY);
11430
Neels Hofmeyr23158742021-09-07 19:08:07 +020011431 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011432 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011433 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11434 chan_ident_ie.chan_ident.ch_desc.v.tsc);
11435
11436 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011437 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011438
11439 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011440 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011441
11442 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011443 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011444 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr23158742021-09-07 19:08:07 +020011445 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11446
11447 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011448 f_perform_clear_test_ct(dt);
Neels Hofmeyr23158742021-09-07 19:08:07 +020011449 f_shutdown_helper();
11450}
11451
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011452testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
11453 /* change Timeslot 6 before f_init() starts RSL */
11454 f_init_vty();
11455 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11456 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11457
11458 f_init(1, false);
11459 f_sleep(1.0);
11460
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011461 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011462 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11463 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011464 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11465 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011466
11467 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11468 f_ts_set_chcomb(0, 0, 6, "PDCH");
11469
11470 /* block all static timeslots so that the dyn TS will be used */
11471 f_disable_all_tch_f();
11472 f_disable_all_tch_h();
11473 f_disable_all_sdcch();
11474
11475 var RSL_Message chan_act;
11476 var RSL_Message imm_ass;
11477
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011478 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11479
11480 /* RA containing reason=LU */
11481 var GsmFrameNumber fn := 2342;
11482 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011483 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011484
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011485 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011486 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
11487 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011488
11489 /* Now activation as SDCCH8 */
11490 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011491 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011492
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011493 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011494 var RSL_IE_Body chan_ident_ie;
11495 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11496 setverdict(fail, "RSL Channel Identification IE is absent");
11497 mtc.stop;
11498 }
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011499
11500 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011501 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011502 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11503 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011504
11505 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011506 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011507
11508 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011509 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011510
11511 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011512 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011513 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011514 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11515
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011516 /* (set bts 0 cfg back to default) */
11517 f_vty_set_imm_ass(BSCVTY);
11518
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011519 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011520 f_perform_clear_test_ct(dt);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011521 f_shutdown_helper();
11522}
11523
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011524testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
11525 /* change Timeslot 6 before f_init() starts RSL */
11526 f_init_vty();
11527 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11528 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11529
11530 f_init(1, false);
11531 f_sleep(1.0);
11532
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011533 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011534 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11535 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011536 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11537 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011538
11539 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11540 f_ts_set_chcomb(0, 0, 6, "PDCH");
11541
11542 /* block all static timeslots so that the dyn TS will be used */
11543 f_disable_all_tch_f();
11544 f_disable_all_tch_h();
11545 f_disable_all_sdcch();
11546
11547 var RSL_Message chan_act;
11548 var RSL_Message imm_ass;
11549
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011550 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11551
11552 /* RA containing reason=LU */
11553 var GsmFrameNumber fn := 2342;
11554 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011555 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011556
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011557 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011558 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011559
11560 /* And already the Immediate Assignment even before the PDCH Deact ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011561 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011562
11563 /* continue the Osmo style PDCH Deact (usual chan rel) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011564 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011565
11566 /* Now activation as SDCCH8 */
11567 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011568 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011569
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011570 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011571 var RSL_IE_Body chan_ident_ie;
11572 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11573 setverdict(fail, "RSL Channel Identification IE is absent");
11574 mtc.stop;
11575 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011576 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011577
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011578 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11579 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011580
11581 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011582 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011583
11584 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011585 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011586 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011587 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11588
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011589 /* (set bts 0 cfg back to default) */
11590 f_vty_set_imm_ass(BSCVTY);
11591
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011592 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011593 f_perform_clear_test_ct(dt);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011594 f_shutdown_helper();
11595}
11596
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011597/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
11598testcase TC_ctrl_trx_rf_locked() runs on test_CT {
11599 var MSC_ConnHdlr vc_conn;
11600
11601 f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
11602 f_sleep(1.0);
11603
11604 /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
11605 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11606 "0,0,operational,unlocked,on,rsl-up;" &
11607 "1,0,operational,unlocked,on,rsl-up;" &
11608 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011609 "2,1,operational,unlocked,on,rsl-down;" &
11610 "2,2,operational,unlocked,on,rsl-down;" &
11611 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011612 "3,0,inoperational,locked,on,rsl-down;");
11613
11614 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock BTS 1 TRX 0");
11615 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11616 /* give it a moment to settle the FSM status */
11617 f_sleep(1.0);
11618
11619 /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
11620 * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
11621 * of "off"? But that's for a future patch if at all. */
11622 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11623 "0,0,operational,unlocked,on,rsl-up;" &
11624 "1,0,operational,locked,on,rsl-up;" &
11625 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011626 "2,1,operational,unlocked,on,rsl-down;" &
11627 "2,2,operational,unlocked,on,rsl-down;" &
11628 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011629 "3,0,inoperational,locked,on,rsl-down;");
11630
11631 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
11632 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11633 f_sleep(1.0);
11634 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11635 "0,0,operational,unlocked,on,rsl-up;" &
11636 "1,0,operational,locked,on,rsl-up;" &
11637 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011638 "2,1,operational,unlocked,on,rsl-down;" &
11639 "2,2,operational,unlocked,on,rsl-down;" &
11640 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011641 "3,0,inoperational,locked,on,rsl-down;");
11642
11643 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
11644 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
11645 f_sleep(1.0);
11646 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11647 "0,0,operational,unlocked,on,rsl-up;" &
11648 "1,0,operational,unlocked,on,rsl-up;" &
11649 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011650 "2,1,operational,unlocked,on,rsl-down;" &
11651 "2,2,operational,unlocked,on,rsl-down;" &
11652 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011653 "3,0,inoperational,locked,on,rsl-down;");
11654
11655 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
11656 f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
11657 f_sleep(1.0);
11658 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11659 "0,0,operational,unlocked,on,rsl-up;" &
11660 "1,0,operational,unlocked,on,rsl-up;" &
11661 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011662 "2,1,operational,unlocked,on,rsl-down;" &
11663 "2,2,operational,unlocked,on,rsl-down;" &
11664 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011665 "3,0,inoperational,locked,on,rsl-down;");
11666
11667 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
11668 f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
11669 f_sleep(1.0);
11670 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11671 "0,0,operational,unlocked,on,rsl-up;" &
11672 "1,0,operational,unlocked,on,rsl-up;" &
11673 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011674 "2,1,operational,unlocked,on,rsl-down;" &
11675 "2,2,operational,unlocked,on,rsl-down;" &
11676 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011677 "3,0,inoperational,locked,on,rsl-down;");
11678
11679 f_shutdown_helper();
11680}
11681
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011682const CounterNameVals counternames_cm_serv_rej := {
11683 { "cm_serv_rej", 0 },
11684 { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
11685 { "cm_serv_rej:illegal_ms", 0 },
11686 { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
11687 { "cm_serv_rej:imei_not_accepted", 0 },
11688 { "cm_serv_rej:illegal_me", 0 },
11689 { "cm_serv_rej:plmn_not_allowed", 0 },
11690 { "cm_serv_rej:loc_not_allowed", 0 },
11691 { "cm_serv_rej:roaming_not_allowed", 0 },
11692 { "cm_serv_rej:network_failure", 0 },
11693 { "cm_serv_rej:synch_failure", 0 },
11694 { "cm_serv_rej:congestion", 0 },
11695 { "cm_serv_rej:srv_opt_not_supported", 0 },
11696 { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
11697 { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
11698 { "cm_serv_rej:call_can_not_be_identified", 0 },
11699 { "cm_serv_rej:incorrect_message", 0 },
11700 { "cm_serv_rej:invalid_mandantory_inf", 0 },
11701 { "cm_serv_rej:msg_type_not_implemented", 0 },
11702 { "cm_serv_rej:msg_type_not_compatible", 0 },
11703 { "cm_serv_rej:inf_eleme_not_implemented", 0 },
11704 { "cm_serv_rej:condtional_ie_error", 0 },
11705 { "cm_serv_rej:msg_not_compatible", 0 },
11706 { "cm_serv_rej:protocol_error", 0 },
11707 { "cm_serv_rej:retry_in_new_cell", 0 }
11708};
11709
11710private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
11711{
11712 f_create_chan_and_exp();
Vadim Yanitskiya7fc5a62021-12-04 20:10:08 +030011713 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011714 BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011715 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_CM_SERV_REJ));
11716 f_perform_clear();
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011717 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011718}
11719testcase TC_cm_serv_rej() runs on test_CT {
11720 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11721 var MSC_ConnHdlr vc_conn;
11722
11723 f_init(1, true);
11724 f_sleep(1.0);
11725
11726 f_ctrs_bts_init(1, counternames_cm_serv_rej);
11727
11728 vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
11729 vc_conn.done;
11730
11731 f_ctrs_bts_add(0, "cm_serv_rej", 1);
11732 f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
11733 f_ctrs_bts_verify();
11734
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011735 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011736 f_shutdown_helper();
11737}
11738
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011739/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
11740 * Activ Ack (SYS#5627). */
11741private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
11742 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Vadim Yanitskiyf0310e32021-10-26 00:30:59 +030011743
11744 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11745 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011746
11747 var BSSMAP_FIELD_CodecType codecType;
11748 codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
11749
11750 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
11751
11752 /* First establish a signalling lchan */
11753 f_create_chan_and_exp();
11754 f_rslem_dchan_queue_enable();
11755
11756 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011757
11758 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
Oliver Smith735b47c2023-02-15 16:03:54 +010011759 activate(as_Media_mgw());
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011760
11761 var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
11762 f_rslem_register(0, chan_nr);
11763
11764 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
11765 BSSAP.send(ass_cmd);
11766
11767
11768 /* Wait for the Channel Activ for the TCH channel */
11769 var ASP_RSL_Unitdata rx_rsl_ud;
11770 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
11771
11772 /* make the original SDCCH disappear */
11773 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
11774
11775 /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
11776 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
11777
11778 interleave {
11779 [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
11780 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
11781 }
11782
11783 BSSAP.send(ts_BSSMAP_ClearCommand(0));
11784 BSSAP.receive(tr_BSSMAP_ClearComplete);
11785 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11786
11787 var MgcpCommand mgcp;
Vadim Yanitskiy6be4cf42022-06-04 21:25:47 +060011788 var MGCP_RecvFrom mrf;
11789 var template MgcpMessage msg_dlcx := { command := tr_DLCX };
11790 alt {
11791 [g_pars.aoip] MGCP.receive(tr_DLCX) -> value mgcp {
11792 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
11793 }
11794 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
11795 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
11796 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
11797 }));
11798 }
11799 }
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011800
11801 f_sleep(0.5);
11802}
11803testcase TC_lost_sdcch_during_assignment() runs on test_CT {
11804 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11805 var MSC_ConnHdlr vc_conn;
11806
Oliver Smith735b47c2023-02-15 16:03:54 +010011807 pars.fail_on_dlcx := false;
11808
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011809 f_init(1, true);
11810 f_sleep(1.0);
11811
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011812 vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
11813 vc_conn.done;
11814
11815 f_shutdown_helper();
11816}
11817
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011818const CounterNameVals counternames_bsc_bts_all_available_allocated := {
11819 { "all_allocated:sdcch", 0 },
11820 { "all_allocated:static_sdcch", 0 },
11821 { "all_allocated:tch", 0 },
11822 { "all_allocated:static_tch", 0 }
11823}
11824
11825private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
11826{
11827 /* Make sure counters settle first */
11828 f_sleep(1.0);
11829
11830 /* Take a baseline of counters */
11831 f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
11832
11833 /* Elapse some time so that we see changes in counters, hopefully where expected */
11834 f_sleep(2.0);
11835
11836 /* Get new counters */
11837 var charstring_list all_changed := {};
11838 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
11839 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
11840
11841 /* Compare with expectations */
11842 var charstring_list all_expect_changed := {};
11843 for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
11844 all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
11845 }
11846 f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
11847}
11848
11849testcase TC_ratectr_all_available_allocated() runs on test_CT {
11850 var ASP_RSL_Unitdata rsl_ud;
11851 var integer i;
11852 var integer chreq_total, chreq_nochan;
11853
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011854 f_init(1, guard_timeout := 60.0);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011855 f_sleep(1.0);
11856
11857 /* Exhaust all dedicated SDCCH lchans.
11858 /* GSM 44.018 Table 9.1.8.2:
11859 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11860 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011861 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011862 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011863 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 +020011864 }
11865
11866 /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
11867 * level.
11868 * All SDCCH are now occupied. */
11869 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11870
11871 /* Also fill up all remaining (TCH) channels */
11872 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011873 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 +020011874 }
11875
11876 /* All TCH are now also occupied */
11877 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11878 "all_allocated:tch", "all_allocated:static_tch"});
11879
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011880 /* Clean up SDCCH lchans */
11881 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11882 f_perform_clear_test_ct(chan_cleanup[i]);
11883 }
11884
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011885 f_shutdown_helper();
11886}
11887
11888testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
11889 var ASP_RSL_Unitdata rsl_ud;
11890 var integer i;
11891 var integer chreq_total, chreq_nochan;
11892
11893 f_init_vty();
11894 f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
11895 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11896 /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
11897
11898 f_init(1, guard_timeout := 60.0);
11899 f_sleep(1.0);
11900
11901 /* The dyn TS wants to activate PDCH mode, ACK that. */
11902 var RslChannelNr chan_nr;
11903 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011904 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11905 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011906
11907 /* Exhaust all dedicated SDCCH lchans.
11908 /* GSM 44.018 Table 9.1.8.2:
11909 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11910 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011911 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011912 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011913 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 +020011914 }
11915
11916 /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
11917 * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
11918 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
11919
11920 /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
11921 * Will release them later, so remember all the DchanTuples. */
11922 var DchanTuples dyn_sddch := {};
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011923 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 +020011924
11925 /* Also occupy the seven other SDCCH of the dyn TS */
11926 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011927 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 +020011928 }
11929
11930 /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
11931 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11932
11933 /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
11934 for (i := 0; i < 5; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011935 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 +020011936 }
11937
11938 /* All TCH lchans are now also occupied, both static and dynamic */
11939 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11940 "all_allocated:tch", "all_allocated:static_tch"});
11941
11942 /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
11943 * incrementing. */
11944 var BssmapCause cause := 0;
11945 var DchanTuple dt := dyn_sddch[0];
11946 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011947 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011948
11949 /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
11950 * count as occupied, so those still both increment. */
11951 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
11952 "all_allocated:tch", "all_allocated:static_tch"});
11953
11954 /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
11955 for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
11956 dt := dyn_sddch[i];
11957 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011958 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011959 }
11960
11961 /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
11962 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011963 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11964 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011965
11966 /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
11967 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
11968
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011969 /* Clean up SDCCH lchans */
11970 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11971 f_perform_clear_test_ct(chan_cleanup[i]);
11972 }
11973
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011974 /* clean up config */
11975 f_ts_reset_chcomb(0);
11976
11977 f_shutdown_helper();
11978}
11979
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011980private function f_TC_chan_alloc_algo(DchanTuple dt, BtsTrxIdx idx)
11981runs on test_CT {
11982 /* MSC sends an Assignment Request */
11983 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11984 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11985 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11986 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
11987
11988 /* Expect the BSC to allocate a TCH channel on the given BTS/TRX */
11989 var RSL_Message rsl_chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
11990 /* Send CHAN ACT NACK, so that the requested TCH channel becomes BORKEN */
11991 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(rsl_chan_act.ies[0].body.chan_nr, RSL_ERR_EQUIPMENT_FAIL), idx);
11992 /* Expect to receive an Assignment Failure */
11993 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail));
11994}
11995
11996testcase TC_chan_alloc_algo_ascending() runs on test_CT {
11997 /* We need to access BTS2, which has 4 TRXs */
11998 f_init(nr_bts := 3);
11999
12000 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012001 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012002
12003 f_vty_enter_cfg_bts(BSCVTY, 2);
12004 f_vty_transceive(BSCVTY, "channel allocator ascending");
12005 f_vty_transceive(BSCVTY, "end");
12006
12007 /* Expect the BSC to allocate 4 x TCH/F channels on BTS2/TRX0 */
12008 for (var integer i := 0; i < 4; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012009 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012010 f_TC_chan_alloc_algo(dt, {2, 0});
12011 f_perform_clear_test_ct(dt);
12012 }
12013
12014 /* At this point all 4 x TCH/F channels are BORKEN, but they will be
12015 * resurrected upon the A-bis/OML link re-establishment. */
12016 f_shutdown_helper();
12017}
12018
12019testcase TC_chan_alloc_algo_descending() runs on test_CT {
12020 /* We need to access BTS2, which has 4 TRXs */
12021 f_init(nr_bts := 3);
12022
12023 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012024 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012025
12026 f_vty_enter_cfg_bts(BSCVTY, 2);
12027 f_vty_transceive(BSCVTY, "channel allocator descending");
12028 f_vty_transceive(BSCVTY, "end");
12029
12030 /* Expect the BSC to allocate 5 x TCH/F channels on BTS2/TRX3 */
12031 for (var integer i := 0; i < 5; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012032 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012033 f_TC_chan_alloc_algo(dt, {2, 3});
12034 f_perform_clear_test_ct(dt);
12035 }
12036
12037 /* At this point all 5 x TCH/F channels are BORKEN, but they will be
12038 * resurrected upon the A-bis/OML link re-establishment. */
12039 f_shutdown_helper();
12040}
12041
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012042testcase TC_chan_alloc_algo_ass_dynamic() runs on test_CT {
12043 const BtsTrxIdx TRX0 := {2, 0};
12044 const BtsTrxIdx TRX3 := {2, 3};
12045
12046 /* We need to access BTS2, which has 4 TRXs */
12047 f_init(nr_bts := 3);
12048
12049 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012050 vc_MGCP[0].stop;
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012051
12052 f_vty_enter_cfg_bts(BSCVTY, 2);
12053 f_vty_transceive(BSCVTY, "channel allocator mode assignment dynamic");
12054 f_vty_transceive(BSCVTY, "channel allocator dynamic-param ul-rxlev thresh 50 avg-num 2");
12055 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 0");
12056 f_vty_transceive(BSCVTY, "end");
12057
12058 var DchanTuple dt;
12059
12060 f_logp(BSCVTY, "Case a) Unknown Uplink RxLev, fall-back to ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012061 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012062 f_TC_chan_alloc_algo(dt, TRX0);
12063 f_perform_clear_test_ct(dt);
12064
12065 f_logp(BSCVTY, "Case b) Not enough RxLev samples, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012066 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012067 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12068 ts_RSL_IE_UplinkMeas(30, 0),
12069 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012070 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012071 f_TC_chan_alloc_algo(dt, TRX0);
12072 f_perform_clear_test_ct(dt);
12073
12074 f_logp(BSCVTY, "Case c) Uplink RxLev below the threshold, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012075 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012076 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12077 ts_RSL_IE_UplinkMeas(45, 0),
12078 ts_RSL_IE_BS_Power(0)), TRX0);
12079 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12080 ts_RSL_IE_UplinkMeas(48, 0),
12081 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012082 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012083 f_TC_chan_alloc_algo(dt, TRX0);
12084 f_perform_clear_test_ct(dt);
12085
12086 f_logp(BSCVTY, "Case d) Uplink RxLev above the threshold, use descending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012087 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012088 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12089 ts_RSL_IE_UplinkMeas(50, 0),
12090 ts_RSL_IE_BS_Power(0)), TRX0);
12091 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12092 ts_RSL_IE_UplinkMeas(58, 0),
12093 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012094 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012095 f_TC_chan_alloc_algo(dt, TRX3);
12096 f_perform_clear_test_ct(dt);
12097
12098 f_vty_enter_cfg_bts(BSCVTY, 2);
12099 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 90");
12100 f_vty_transceive(BSCVTY, "end");
12101
12102 f_logp(BSCVTY, "Case e) Uplink RxLev above the threshold, but C0 load is not");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012103 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012104 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12105 ts_RSL_IE_UplinkMeas(50, 0),
12106 ts_RSL_IE_BS_Power(0)), TRX0);
12107 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12108 ts_RSL_IE_UplinkMeas(58, 0),
12109 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012110 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012111 f_TC_chan_alloc_algo(dt, TRX0);
12112 f_perform_clear_test_ct(dt);
12113
12114 f_vty_enter_cfg_bts(BSCVTY, 2);
12115 f_vty_transceive(BSCVTY, "channel allocator ascending");
12116 f_vty_transceive(BSCVTY, "end");
12117
12118 /* At this point some TCH/F channels are BORKEN, but they will be
12119 * resurrected upon the A-bis/OML link re-establishment. */
12120 f_shutdown_helper();
12121}
12122
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012123private function f_vty_mgw_enable(integer mgw_nr := 1) runs on test_CT {
12124 var rof_charstring cmds := {
12125 "remote-ip " & mp_test_ip,
12126 "remote-port " & int2str(2427 + mgw_nr)
12127 };
12128 f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
12129 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " reconnect")
12130}
12131private function f_vty_mgw_disable(integer mgw_nr := 1) runs on test_CT {
12132 f_vty_config3(BSCVTY, {"network"}, { "no mgw " &int2str(mgw_nr) });
12133}
12134private function f_vty_mgw_block(integer mgw_nr := 1, boolean blocked := true) runs on test_CT {
12135 var charstring arg;
12136 if (blocked) {
12137 arg := "block";
12138 } else {
12139 arg := "unblock";
12140 }
12141 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " " & arg);
12142}
Pau Espin Pedrolbd598422023-06-15 17:29:09 +020012143private 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 {
12144 var charstring arg;
12145 var rof_charstring cmds := {
12146 "keepalive request-interval " & int2str(req_intval),
12147 "keepalive request-endpoint " & req_endp,
12148 "keepalive timeout " & int2str(rx_timeout)
12149 };
12150 f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
12151}
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012152private const charstring COORD_CMD_ESTABLISHED := "COORD_CMD_ESTABLISHED";
12153private function f_TC_mgwpool_call_seq_1(charstring id) runs on MSC_ConnHdlr {
12154 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12155 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12156 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12157 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12158
12159 f_establish_fully(ass_cmd, exp_compl);
12160 COORD.send(COORD_CMD_ESTABLISHED);
12161
12162 COORD.receive(COORD_CMD_ESTABLISHED);
12163 f_perform_clear()
12164 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12165}
12166private function f_TC_mgwpool_call_seq_2(charstring id) runs on MSC_ConnHdlr {
12167 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12168 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12169 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12170 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12171
12172
12173 COORD.receive(COORD_CMD_ESTABLISHED);
12174 f_establish_fully(ass_cmd, exp_compl);
12175 COORD.send(COORD_CMD_ESTABLISHED);
12176
12177 f_perform_clear()
12178 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12179}
12180/* Test load is spread around 2 available MGWs */
12181testcase TC_mgwpool_all_used() runs on test_CT {
12182 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12183 var MSC_ConnHdlr vc_conn1;
12184 pars1.mgwpool_idx := 0;
12185
12186 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12187 var MSC_ConnHdlr vc_conn2;
12188 pars2.mgwpool_idx := 1;
12189
12190 f_init(1, true, nr_mgw := 2);
12191 f_sleep(1.0);
12192
12193 f_vty_mgw_enable(1);
12194
12195 vc_conn1 := f_start_handler_create(pars1);
12196 vc_conn2 := f_start_handler_create(pars2);
12197 connect(vc_conn1:COORD, vc_conn2:COORD);
12198 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12199 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12200 vc_conn1.done;
12201 vc_conn2.done;
12202
12203 f_vty_mgw_disable(1);
12204
12205 f_shutdown_helper();
12206}
12207
12208/* Test blocked MGW in the pool are not selected */
12209testcase TC_mgwpool_blocked_not_used() runs on test_CT {
12210 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12211 var MSC_ConnHdlr vc_conn1;
12212 pars1.mgwpool_idx := 0;
12213
12214 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12215 var MSC_ConnHdlr vc_conn2;
12216 pars2.mgwpool_idx := 0; /* expect it in the first one, since the second will be blocked */
12217 pars2.media_nr := 2;
12218
12219 f_init(1, true, nr_mgw := 2);
12220 f_sleep(1.0);
12221
12222 f_vty_mgw_enable(1);
12223 f_vty_mgw_block(1, true);
12224
12225 vc_conn1 := f_start_handler_create(pars1);
12226 vc_conn2 := f_start_handler_create(pars2);
12227 connect(vc_conn1:COORD, vc_conn2:COORD);
12228 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12229 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12230 vc_conn1.done;
12231 vc_conn2.done;
12232
12233 f_vty_mgw_disable(1);
12234
12235 f_shutdown_helper();
12236}
12237
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012238/* Test BTS pinning to an MGW is applied */
12239testcase TC_mgwpool_pin_bts() runs on test_CT {
12240 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12241 var MSC_ConnHdlr vc_conn1;
12242 pars1.mgwpool_idx := 0;
12243
12244 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12245 var MSC_ConnHdlr vc_conn2;
12246 pars2.mgwpool_idx := 0; /* expect it in the first one, since the BTS is pinned to the first MGW */
12247 pars2.media_nr := 2;
12248
12249 f_init(1, true, nr_mgw := 2);
12250 f_sleep(1.0);
12251
12252 f_vty_mgw_enable(1);
12253 f_vty_cfg_bts(BSCVTY, 0, { "mgw pool-target 0" });
12254
12255 vc_conn1 := f_start_handler_create(pars1);
12256 vc_conn2 := f_start_handler_create(pars2);
12257 connect(vc_conn1:COORD, vc_conn2:COORD);
12258 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12259 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12260 vc_conn1.done;
12261 vc_conn2.done;
12262
12263 f_vty_cfg_bts(BSCVTY, 0, { "no mgw pool-target" } );
Vadim Yanitskiy389d7e02022-10-25 17:44:05 +070012264 f_vty_mgw_disable(1);
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012265
12266 f_shutdown_helper();
12267}
12268
Pau Espin Pedrolbd598422023-06-15 17:29:09 +020012269/* Test keepalive procedure on the MGW */
12270private function f_TC_mgwpool_keepalive_mgw0(charstring id) runs on MSC_ConnHdlr {
12271 /* Make sure the MGW is considered DOWN by the keepalive. See "timeout"
12272 * param in TC_mgwpool_keepalive. */
12273 f_sleep(3.0);
12274
12275 COORD.send(COORD_CMD_ESTABLISHED);
12276
12277 /* Wait for signal that call was established successfully over the other MSC/MGW: */
12278 COORD.receive(COORD_CMD_ESTABLISHED);
12279}
12280private function f_TC_mgwpool_keepalive_mgw1(charstring id) runs on MSC_ConnHdlr {
12281 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12282 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12283 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12284 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12285
12286 /* Wait for other MSC/MGW component to tell us the timeout is done and
12287 * we can start the call, which will be assigned to use because the other
12288 * MGW will be seen as DOWN. */
12289 COORD.receive(COORD_CMD_ESTABLISHED);
12290 f_establish_fully(ass_cmd, exp_compl);
12291 /* signal that call was established successfully over the other MSC/MGW: */
12292 COORD.send(COORD_CMD_ESTABLISHED);
12293
12294 f_perform_clear()
12295 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12296}
12297testcase TC_mgwpool_keepalive_down_not_used() runs on test_CT {
12298 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12299 var MSC_ConnHdlr vc_conn1;
12300 pars1.mgwpool_idx := 0;
12301
12302 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12303 var MSC_ConnHdlr vc_conn2;
12304 pars2.mgwpool_idx := 1; /* expect it in the second one, since the first will be considered DOWN */
12305 pars2.media_nr := 2;
12306
12307 f_init(1, true, nr_mgw := 2);
12308 f_sleep(1.0);
12309
12310 f_vty_mgw_enable(1);
12311 f_vty_mgw_block(1, false);
12312 f_vty_mgw_cfg_keepalive(0, req_intval := 1, req_endp := "null", rx_timeout := 3);
12313
12314 vc_conn1 := f_start_handler_create(pars1);
12315 vc_conn2 := f_start_handler_create(pars2);
12316 connect(vc_conn1:COORD, vc_conn2:COORD);
12317 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_keepalive_mgw0), pars1);
12318 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_keepalive_mgw1), pars2);
12319 vc_conn1.done;
12320 vc_conn2.done;
12321
12322 f_vty_mgw_disable(1);
12323 /* disable keepalive (default status): */
12324 f_vty_mgw_cfg_keepalive(0, req_intval := 0, req_endp := "null", rx_timeout := 0);
12325
12326 f_shutdown_helper();
12327}
12328
Oliver Smithc9a5f532022-10-21 11:32:23 +020012329private function f_tc_ho_meas_rep_multi_band(charstring id) runs on MSC_ConnHdlr {
12330 g_pars := f_gen_test_hdlr_pars();
12331 var PDU_BSSAP ass_req := f_gen_ass_req();
12332 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12333 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12334 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12335 f_establish_fully(ass_req, exp_compl);
12336
12337 /* Send a measurement report with bad rxlev except on 3rd entry. The
12338 * measurement report is divided into two sub lists, as described in
12339 * 3GPP TS 04.08 § 10.5.2.20. */
12340 var NcellReports neighbor_rep := {
12341 /* Sub list 1: same band */
Oliver Smitha6773042022-10-24 12:56:30 +020012342 { rxlev := 0, bcch_freq := 0, bsic := 12 }, /* ARFCN 800, band 1800, LAC 98 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012343 /* Sub list 2: different band */
Oliver Smitha6773042022-10-24 12:56:30 +020012344 { rxlev := 0, bcch_freq := 1, bsic := 13 }, /* ARFCN 200, band 850, LAC 97 */
12345 { rxlev := 40, bcch_freq := 2, bsic := 14 }, /* ARFCN 1000, band 900, LAC 99 */
12346 { rxlev := 0, bcch_freq := 3, bsic := 11 } /* ARFCN 0, band 900, LAC 96 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012347 };
12348 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
12349 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
12350 l3_mr, 0));
12351
12352 /* Expect a handover to the third entry. If the BSC parsed the report
Oliver Smitha6773042022-10-24 12:56:30 +020012353 * correctly, the third entry has LAC 99. */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012354 var template BSSMAP_FIELD_CellIdentificationList cid_list := {
Oliver Smitha6773042022-10-24 12:56:30 +020012355 cIl_LAC := { ts_BSSMAP_CI_LAC(99) }
Oliver Smithc9a5f532022-10-21 11:32:23 +020012356 };
12357 alt {
12358 [] BSSAP.receive(tr_BSSMAP_HandoverRequired(cid_list := cid_list)) {
12359 setverdict(pass);
12360 }
12361 [] BSSAP.receive(tr_BSSMAP_HandoverRequired()) {
12362 setverdict(fail, "Handover has unexpected LAC in Cell Identification List. The BSC probably"
12363 & " didn't parse the multi-band measurement report correctly.");
12364 }
12365 }
12366
12367 f_ho_out_of_this_bsc(skip_meas_rep := true);
12368}
12369testcase TC_ho_meas_rep_multi_band() runs on test_CT {
12370 /* Verify that the BSC parses the measurement report correctly when
12371 * neighbors in multiple bands are configured (OS#5717). See
12372 * gsm_arfcn2band_rc() in libosmocore src/gsm/gsm_utils.c for the
12373 * ARFCN -> band mapping. The MS is connected to band 1800. */
12374 var MSC_ConnHdlr vc_conn;
12375
12376 f_init_vty();
12377 f_bts_0_cfg(BSCVTY,
12378 {"neighbor-list mode automatic",
12379 "handover 1",
12380 "handover algorithm 2",
12381 "handover2 window rxlev averaging 1",
12382 "no neighbors",
12383 "neighbor lac 99 arfcn 1000 bsic any", /* band 900 */
12384 "neighbor lac 98 arfcn 800 bsic any", /* band 1800 */
12385 "neighbor lac 97 arfcn 200 bsic any", /* band 850 */
Oliver Smitha6773042022-10-24 12:56:30 +020012386 "neighbor lac 96 arfcn 0 bsic any"}); /* band 900 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012387 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
12388
12389 f_init(1, true);
12390 f_sleep(1.0);
12391
12392 f_ctrs_bsc_and_bts_handover_init();
12393
12394 vc_conn := f_start_handler(refers(f_tc_ho_meas_rep_multi_band));
12395 vc_conn.done;
12396
12397 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
12398 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
12399 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
12400 f_ctrs_bsc_and_bts_add(0, "handover:completed");
12401 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
12402 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
12403 f_ctrs_bsc_and_bts_verify();
12404 f_shutdown_helper(ho := true);
12405}
12406
Harald Welte28d943e2017-11-25 15:00:50 +010012407control {
Harald Welte898113b2018-01-31 18:32:21 +010012408 /* CTRL interface testing */
Harald Welte4003d112017-12-09 22:35:39 +010012409 execute( TC_ctrl_msc_connection_status() );
Stefan Sperlingb041b3d2018-01-03 17:14:55 +010012410 execute( TC_ctrl_msc0_connection_status() );
Neels Hofmeyrf65ce872021-09-23 18:40:10 +020012411 /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
12412 * these in the AoIP test suite. */
12413 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12414 execute( TC_stat_num_msc_connected_1() );
12415 execute( TC_stat_num_msc_connected_2() );
12416 execute( TC_stat_num_msc_connected_3() );
12417 }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020012418 execute( TC_stat_num_bts_connected_1() );
12419 execute( TC_stat_num_bts_connected_2() );
12420 execute( TC_stat_num_bts_connected_3() );
Harald Welte96c94412017-12-09 03:12:45 +010012421 execute( TC_ctrl() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012422 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +020012423 execute( TC_ctrl_location() );
12424 }
Harald Welte898113b2018-01-31 18:32:21 +010012425
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012426 execute( TC_si_default() );
Neels Hofmeyr66aeba42020-07-06 02:21:21 +020012427 execute( TC_si2quater_2_earfcns() );
12428 execute( TC_si2quater_3_earfcns() );
12429 execute( TC_si2quater_4_earfcns() );
12430 execute( TC_si2quater_5_earfcns() );
12431 execute( TC_si2quater_6_earfcns() );
Neels Hofmeyrad132f22020-07-08 02:20:16 +020012432 execute( TC_si2quater_12_earfcns() );
12433 execute( TC_si2quater_23_earfcns() );
12434 execute( TC_si2quater_32_earfcns() );
12435 execute( TC_si2quater_33_earfcns() );
12436 execute( TC_si2quater_42_earfcns() );
12437 execute( TC_si2quater_48_earfcns() );
12438 execute( TC_si2quater_49_earfcns() );
Pau Espin Pedrol85a84432020-07-20 18:45:03 +020012439 execute( TC_si_acc_rotate() );
Alexander Couzens4ad3a352020-09-10 22:29:12 +020012440 execute( TC_si_acc_ramp_rotate() );
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012441
Harald Welte898113b2018-01-31 18:32:21 +010012442 /* RSL DCHAN Channel ACtivation / Deactivation */
Harald Welteae026692017-12-09 01:03:01 +010012443 execute( TC_chan_act_noreply() );
Harald Welte4003d112017-12-09 22:35:39 +010012444 execute( TC_chan_act_counter() );
Harald Welteae026692017-12-09 01:03:01 +010012445 execute( TC_chan_act_ack_noest() );
Philipp Maier9c60a622020-07-09 15:08:46 +020012446 execute( TC_chan_act_ack_noest_emerg() );
Philipp Maier606f07d2020-08-12 17:21:58 +020012447 execute( TC_chan_rqd_emerg_deny() );
Harald Welteae026692017-12-09 01:03:01 +010012448 execute( TC_chan_act_ack_est_ind_noreply() );
12449 execute( TC_chan_act_ack_est_ind_refused() );
Harald Welte618ef642017-12-14 14:58:20 +010012450 execute( TC_chan_act_nack() );
Harald Welte799c97b2017-12-14 17:50:30 +010012451 execute( TC_chan_exhaustion() );
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +070012452 execute( TC_chan_deact_silence() );
Harald Welte4003d112017-12-09 22:35:39 +010012453 execute( TC_chan_rel_rll_rel_ind() );
12454 execute( TC_chan_rel_conn_fail() );
12455 execute( TC_chan_rel_hard_clear() );
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +020012456 execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
12457 execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
Harald Welte99787102019-02-04 10:41:36 +010012458 execute( TC_chan_rel_hard_clear_csfb() );
Harald Welted8c36cd2017-12-09 23:05:31 +010012459 execute( TC_chan_rel_hard_rlsd() );
Harald Welte550daf92018-06-11 19:22:13 +020012460 execute( TC_chan_rel_hard_rlsd_ms_dead() );
Harald Welte85804d42017-12-10 14:11:58 +010012461 execute( TC_chan_rel_a_reset() );
Pau Espin Pedrolc675b612020-01-09 19:55:40 +010012462 execute( TC_chan_rel_sccp_tiar_timeout() );
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +020012463 execute( TC_chan_rel_rr_cause() );
Harald Welte6f521d82017-12-11 19:52:02 +010012464
Harald Weltecfe2c962017-12-15 12:09:32 +010012465 execute( TC_outbound_connect() );
Harald Welte898113b2018-01-31 18:32:21 +010012466
12467 /* Assignment related */
Harald Welte16a4adf2017-12-14 18:54:01 +010012468 execute( TC_assignment_cic_only() );
Harald Welte235ebf12017-12-15 14:18:16 +010012469 execute( TC_assignment_csd() );
12470 execute( TC_assignment_ctm() );
12471 execute( TC_assignment_sign() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012472 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12473 execute( TC_assignment_aoip_tla_v6() );
12474 }
Harald Welte235ebf12017-12-15 14:18:16 +010012475 execute( TC_assignment_fr_a5_0() );
12476 execute( TC_assignment_fr_a5_1() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012477 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte8f67d1d2018-05-25 20:38:42 +020012478 execute( TC_assignment_fr_a5_1_codec_missing() );
12479 }
Harald Welte235ebf12017-12-15 14:18:16 +010012480 execute( TC_assignment_fr_a5_3() );
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +020012481 execute( TC_assignment_fr_a5_4() );
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +020012482 execute( TC_assignment_fr_a5_4_fail() );
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +020012483 execute( TC_assignment_fr_a5_not_sup() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012484 execute( TC_ciph_mode_a5_0() );
12485 execute( TC_ciph_mode_a5_1() );
Oliver Smith50b98122021-07-09 15:00:28 +020012486 execute( TC_ciph_mode_a5_2_0() );
Oliver Smith1dff88d2021-07-09 08:45:51 +020012487 execute( TC_ciph_mode_a5_2_1() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012488 execute( TC_ciph_mode_a5_3() );
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +020012489 execute( TC_ciph_mode_a5_4() );
Harald Welte16a4adf2017-12-14 18:54:01 +010012490
Harald Welte60aa5762018-03-21 19:33:13 +010012491 execute( TC_assignment_codec_fr() );
Neels Hofmeyr559d5d02021-04-16 16:50:49 +020012492 execute( TC_assignment_codec_fr_by_mode_modify() );
Harald Welte60aa5762018-03-21 19:33:13 +010012493 execute( TC_assignment_codec_hr() );
12494 execute( TC_assignment_codec_efr() );
12495 execute( TC_assignment_codec_amr_f() );
12496 execute( TC_assignment_codec_amr_h() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012497
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012498 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier8a581d22019-03-26 18:32:48 +010012499 execute( TC_assignment_codec_amr_f_S1() );
12500 execute( TC_assignment_codec_amr_h_S1() );
12501 execute( TC_assignment_codec_amr_f_S124() );
12502 execute( TC_assignment_codec_amr_h_S124() );
12503 execute( TC_assignment_codec_amr_f_S0() );
12504 execute( TC_assignment_codec_amr_f_S02() );
12505 execute( TC_assignment_codec_amr_f_S024() );
12506 execute( TC_assignment_codec_amr_f_S0247() );
12507 execute( TC_assignment_codec_amr_h_S0() );
12508 execute( TC_assignment_codec_amr_h_S02() );
12509 execute( TC_assignment_codec_amr_h_S024() );
12510 execute( TC_assignment_codec_amr_h_S0247() );
12511 execute( TC_assignment_codec_amr_f_S01234567() );
12512 execute( TC_assignment_codec_amr_f_S0234567() );
12513 execute( TC_assignment_codec_amr_f_zero() );
12514 execute( TC_assignment_codec_amr_f_unsupp() );
12515 execute( TC_assignment_codec_amr_h_S7() );
Neels Hofmeyr21863562020-11-26 00:34:33 +000012516 execute( TC_assignment_codec_amr_f_start_mode_auto() );
12517 execute( TC_assignment_codec_amr_h_start_mode_auto() );
Neels Hofmeyr3eb94562020-11-26 02:40:26 +000012518 execute( TC_assignment_codec_amr_f_start_mode_4() );
12519 execute( TC_assignment_codec_amr_h_start_mode_4() );
Neels Hofmeyr454d7922020-11-26 02:24:57 +000012520 execute( TC_assignment_codec_amr_startmode_cruft() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012521 }
Harald Welte60aa5762018-03-21 19:33:13 +010012522
Philipp Maierac09bfc2019-01-08 13:41:39 +010012523 execute( TC_assignment_codec_fr_exhausted_req_hr() );
12524 execute( TC_assignment_codec_fr_exhausted_req_fr() );
12525 execute( TC_assignment_codec_fr_exhausted_req_fr_hr() );
12526 execute( TC_assignment_codec_fr_exhausted_req_hr_fr() );
12527 execute( TC_assignment_codec_hr_exhausted_req_fr() );
12528 execute( TC_assignment_codec_hr_exhausted_req_hr() );
12529 execute( TC_assignment_codec_hr_exhausted_req_hr_fr() );
12530 execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
12531 execute( TC_assignment_codec_req_hr_fr() );
12532 execute( TC_assignment_codec_req_fr_hr() );
Pau Espin Pedrol14475352021-07-22 15:48:16 +020012533 execute( TC_assignment_sdcch_exhausted_req_signalling() );
12534 execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
12535 execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
Philipp Maierac09bfc2019-01-08 13:41:39 +010012536
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +020012537 execute( TC_assignment_codec_hr_osmux_on() );
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +020012538 execute( TC_assignment_osmux() );
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020012539 execute( TC_assignment_osmux_cn() );
12540 execute( TC_assignment_osmux_bts() );
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +020012541
Harald Welte898113b2018-01-31 18:32:21 +010012542 /* RLL Establish Indication on inactive DCHAN / SAPI */
Harald Welte5cd20ed2017-12-13 21:03:20 +010012543 execute( TC_rll_est_ind_inact_lchan() );
12544 execute( TC_rll_est_ind_inval_sapi1() );
12545 execute( TC_rll_est_ind_inval_sapi3() );
12546 execute( TC_rll_est_ind_inval_sacch() );
12547
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +070012548 /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
12549 execute( TC_tch_dlci_link_id_sapi() );
12550
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012551 /* SAPI N Reject triggered by RLL establishment failures */
12552 execute( TC_rll_rel_ind_sapi_n_reject() );
12553 execute( TC_rll_err_ind_sapi_n_reject() );
12554 execute( TC_rll_timeout_sapi_n_reject() );
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +070012555 execute( TC_rll_sapi_n_reject_dlci_cc() );
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012556
Harald Welte898113b2018-01-31 18:32:21 +010012557 /* Paging related tests */
Harald Welte6f521d82017-12-11 19:52:02 +010012558 execute( TC_paging_imsi_nochan() );
12559 execute( TC_paging_tmsi_nochan() );
12560 execute( TC_paging_tmsi_any() );
12561 execute( TC_paging_tmsi_sdcch() );
12562 execute( TC_paging_tmsi_tch_f() );
12563 execute( TC_paging_tmsi_tch_hf() );
12564 execute( TC_paging_imsi_nochan_cgi() );
12565 execute( TC_paging_imsi_nochan_lac_ci() );
12566 execute( TC_paging_imsi_nochan_ci() );
12567 execute( TC_paging_imsi_nochan_lai() );
12568 execute( TC_paging_imsi_nochan_lac() );
12569 execute( TC_paging_imsi_nochan_all() );
Harald Welte751d3eb2018-01-31 15:51:06 +010012570 execute( TC_paging_imsi_nochan_plmn_lac_rnc() );
12571 execute( TC_paging_imsi_nochan_rnc() );
12572 execute( TC_paging_imsi_nochan_lac_rnc() );
12573 execute( TC_paging_imsi_nochan_lacs() );
12574 execute( TC_paging_imsi_nochan_lacs_empty() );
Stefan Sperling049a86e2018-03-20 15:51:00 +010012575 execute( TC_paging_imsi_nochan_cgi_unknown_cid() );
Harald Welte10985002017-12-12 09:29:15 +010012576 execute( TC_paging_imsi_a_reset() );
Harald Weltee65d40e2017-12-13 00:09:06 +010012577 execute( TC_paging_imsi_load() );
Philipp Maier779a7922018-02-16 11:00:37 +010012578 execute( TC_paging_counter() );
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +010012579 execute( TC_paging_resp_unsol() );
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +020012580 execute( TC_paging_500req() );
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +020012581 execute( TC_paging_450req_no_paging_load_ind() );
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +010012582 execute( TC_paging_imsi_nochan_ci_resp_invalid_mi() );
Harald Welte4e9b9cc2017-12-14 18:31:02 +010012583
12584 execute( TC_rsl_drop_counter() );
Stefan Sperling830dc9d2018-02-12 21:08:28 +010012585 execute( TC_rsl_unknown_unit_id() );
12586
12587 execute( TC_oml_unknown_unit_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012588
12589 execute( TC_classmark() );
Harald Welteeddf0e92020-06-21 19:42:15 +020012590 execute( TC_common_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012591 execute( TC_unsol_ass_fail() );
Harald Welteea99a002018-01-31 20:46:43 +010012592 execute( TC_unsol_ass_compl() );
Harald Weltefbf9b5e2018-01-31 20:41:23 +010012593 execute( TC_unsol_ho_fail() );
Harald Weltee3bd6582018-01-31 22:51:25 +010012594 execute( TC_err_82_short_msg() );
Harald Weltee9e02e42018-01-31 23:36:25 +010012595 execute( TC_err_84_unknown_msg() );
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012596
Harald Welte261af4b2018-02-12 21:20:39 +010012597 execute( TC_ho_int() );
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +020012598 execute( TC_ho_int_a5_0() );
12599 execute( TC_ho_int_a5_1() );
12600 execute( TC_ho_int_a5_3() );
12601 execute( TC_ho_int_a5_4() );
Neels Hofmeyr5f144212020-11-03 15:41:58 +000012602 execute( TC_ho_int_radio_link_failure() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012603
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012604 /* TC_ho_out_of_this_bsc is run last, see comment below */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +020012605 execute( TC_ho_out_fail_no_msc_response() );
12606 execute( TC_ho_out_fail_rr_ho_failure() );
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +020012607 execute( TC_ho_out_fail_no_result_after_ho_cmd() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012608
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012609 execute( TC_ho_into_this_bsc() );
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +020012610 execute( TC_ho_into_this_bsc_a5_0() );
12611 execute( TC_ho_into_this_bsc_a5_1() );
12612 execute( TC_ho_into_this_bsc_a5_3() );
12613 execute( TC_ho_into_this_bsc_a5_4() );
Neels Hofmeyr93182e02022-02-17 21:59:07 +010012614 execute( TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() );
12615 execute( TC_ho_into_this_bsc_a5_1_3() );
Neels Hofmeyr907b23b2022-02-17 21:58:47 +010012616 execute( TC_ho_into_this_bsc_a5_mismatch() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012617 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12618 execute( TC_ho_into_this_bsc_tla_v6() );
12619 }
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +020012620 execute( TC_srvcc_eutran_to_geran() );
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +030012621 execute( TC_srvcc_eutran_to_geran_a5_3() );
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +010012622 execute( TC_srvcc_eutran_to_geran_src_sai() );
Pau Espin Pedrol35801c32021-04-19 13:03:20 +020012623 execute( TC_srvcc_eutran_to_geran_ho_out() );
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +020012624 execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
12625 execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012626 execute( TC_ho_in_fail_msc_clears() );
12627 execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
12628 execute( TC_ho_in_fail_no_detect() );
12629 execute( TC_ho_in_fail_no_detect2() );
Oliver Smith7a8594a2023-02-13 14:30:49 +010012630 execute( TC_ho_in_fail_mgw_mdcx_timeout() );
Oliver Smith4eed06f2023-02-15 15:43:19 +010012631 execute( TC_ho_in_fail_ipa_crcx_timeout() );
Neels Hofmeyra23f3b12022-03-02 19:57:12 +010012632 execute( TC_ho_into_this_bsc_sccp_cr_without_bssap() );
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012633
Neels Hofmeyr91401012019-07-11 00:42:35 +020012634 execute( TC_ho_neighbor_config_1() );
12635 execute( TC_ho_neighbor_config_2() );
12636 execute( TC_ho_neighbor_config_3() );
12637 execute( TC_ho_neighbor_config_4() );
12638 execute( TC_ho_neighbor_config_5() );
12639 execute( TC_ho_neighbor_config_6() );
12640 execute( TC_ho_neighbor_config_7() );
12641
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012642 execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() );
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010012643 execute( TC_bssmap_clear_does_not_cause_bssmap_reset() );
Neels Hofmeyrfd445c32018-03-09 15:39:31 +010012644 execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() );
Harald Welte94e0c342018-04-07 11:33:23 +020012645
12646 execute( TC_dyn_pdch_ipa_act_deact() );
12647 execute( TC_dyn_pdch_ipa_act_nack() );
12648 execute( TC_dyn_pdch_osmo_act_deact() );
12649 execute( TC_dyn_pdch_osmo_act_nack() );
Pau Espin Pedrol37a4c152021-11-16 19:02:23 +010012650 execute( TC_dyn_ts_sdcch8_act_deact() );
12651 execute( TC_dyn_ts_sdcch8_all_subslots_used() );
12652 execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
12653 execute( TC_dyn_ts_sdcch8_act_nack() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012654
Stefan Sperling0796a822018-10-05 13:01:39 +020012655 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +020012656 execute( TC_chopped_ipa_payload() );
Stefan Sperling0796a822018-10-05 13:01:39 +020012657
Pau Espin Pedrol8f773632019-11-05 11:46:53 +010012658 /* Power control related */
12659 execute( TC_assignment_verify_ms_power_params_ie() );
Vadim Yanitskiy4b233042021-06-30 00:58:43 +020012660 execute( TC_c0_power_red_mode() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012661
12662 /* MSC pooling */
12663 /* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
12664 * RESET->RESET-ACK is unconditionally negotiated for all configured MSCs, they always all appear as connected
12665 * to osmo-bsc. The MSC pooling tests however require disconnecting selected MSCs, and hence don't work out as
12666 * intended on SCCPlite. So for now, run these only for SCCP/M3UA. */
12667 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12668 execute( TC_mscpool_L3Compl_on_1_msc() );
12669 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
12670 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
12671 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
12672 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
12673 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
12674 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
12675 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
12676 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
12677 execute( TC_mscpool_paging_and_response_imsi() );
12678 execute( TC_mscpool_paging_and_response_tmsi() );
12679 execute( TC_mscpool_no_allow_attach_round_robin() );
12680 execute( TC_mscpool_no_allow_attach_valid_nri() );
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +020012681
12682 execute( TC_mscpool_sccp_n_pcstate_detaches_msc() );
Neels Hofmeyr38632aa2023-04-05 03:50:51 +020012683 execute( TC_mscpool_sccp_n_pcstate_attaches_msc() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012684 }
12685
Harald Welte99f3ca02018-06-14 13:40:29 +020012686 execute( TC_early_conn_fail() );
12687 execute( TC_late_conn_fail() );
Oliver Smithaf03bef2021-08-24 15:34:51 +020012688 execute( TC_stats_conn_fail() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012689
Philipp Maier783681c2020-07-16 16:47:06 +020012690 /* Emergency call handling (deny / allow) */
12691 execute( TC_assignment_emerg_setup_allow() );
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +010012692 execute( TC_assignment_emerg_setup_allow_imei() );
Philipp Maier783681c2020-07-16 16:47:06 +020012693 execute( TC_assignment_emerg_setup_deny_msc() );
12694 execute( TC_assignment_emerg_setup_deny_bts() );
Philipp Maier82812002020-08-13 18:48:27 +020012695 execute( TC_emerg_premption() );
12696
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +070012697 /* Frequency hopping parameters handling */
12698 execute( TC_fh_params_chan_activ() );
12699 execute( TC_fh_params_imm_ass() );
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070012700 execute( TC_fh_params_assignment_cmd() );
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070012701 execute( TC_fh_params_handover_cmd() );
Vadim Yanitskiyca974032020-09-01 07:20:39 +070012702 execute( TC_fh_params_si4_cbch() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012703
12704 if (mp_enable_lcs_tests) {
12705 execute( TC_lcs_loc_req_for_active_ms() );
12706 execute( TC_lcs_loc_req_for_active_ms_ta_req() );
12707 execute( TC_lcs_loc_req_for_idle_ms() );
12708 execute( TC_lcs_loc_req_no_subscriber() );
12709 execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
12710 execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
12711 execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
12712 execute( TC_cm_service_during_lcs_loc_req() );
12713 execute( TC_ho_during_lcs_loc_req() );
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020012714 execute( TC_emerg_call_and_lcs_loc_req() );
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020012715 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() );
12716 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012717 }
Neels Hofmeyrbf037052020-10-28 22:52:02 +000012718
12719 execute( TC_no_msc() );
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000012720
12721 execute( TC_refuse_chan_act_to_vamos() );
12722 execute( TC_refuse_mode_modif_to_vamos() );
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000012723
12724 execute( TC_reassignment_fr() );
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020012725
12726 execute( TC_cm_reestablishment() );
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020012727
12728 execute( TC_imm_ass_post_chan_ack() );
12729 execute( TC_imm_ass_pre_chan_ack() );
Neels Hofmeyr23158742021-09-07 19:08:07 +020012730 execute( TC_imm_ass_pre_ts_ack() );
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020012731 execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020012732 execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020012733
12734 execute( TC_ctrl_trx_rf_locked() );
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012735
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012736 execute( TC_ratectr_all_available_allocated() );
12737 execute( TC_ratectr_all_available_allocated_dyn() );
12738
Neels Hofmeyrb7581872021-11-07 14:02:49 +010012739 execute( TC_cm_serv_rej() );
12740
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012741 execute( TC_lost_sdcch_during_assignment() );
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012742
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012743 /* Channel allocator */
12744 execute( TC_chan_alloc_algo_ascending() );
12745 execute( TC_chan_alloc_algo_descending() );
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012746 execute( TC_chan_alloc_algo_ass_dynamic() );
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012747
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012748 /* MGW pool */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +010012749 execute( TC_mgwpool_all_used() );
12750 execute( TC_mgwpool_blocked_not_used() );
12751 execute( TC_mgwpool_pin_bts() );
Pau Espin Pedrolbd598422023-06-15 17:29:09 +020012752 execute( TC_mgwpool_keepalive_down_not_used() );
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012753
Oliver Smithc9a5f532022-10-21 11:32:23 +020012754 execute( TC_ho_meas_rep_multi_band() );
12755
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012756 /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
12757 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
12758 execute( TC_ho_out_of_this_bsc() );
Harald Welte28d943e2017-11-25 15:00:50 +010012759}
12760
12761}