blob: f2844e1dfb5d3a0d7d232753ca0e6c622204fdc2 [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 {
Vadim Yanitskiy02c086f2023-09-22 15:32:41 +07001898 var MSC_ConnHdlr vc_conn;
1899 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Oliver Smithdd002752023-02-21 13:35:00 +01001900
Vadim Yanitskiy02c086f2023-09-22 15:32:41 +07001901 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
1902
1903 f_init(1, true, guard_timeout := 120.0);
1904 f_sleep(1.0);
1905 vc_conn := f_start_handler(refers(f_tc_assignment_csd_all), pars);
1906 vc_conn.done;
1907
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001908 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001909}
1910
1911testcase TC_assignment_ctm() runs on test_CT {
1912 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001913 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001914 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
1915 //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 +01001916 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
1917 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001918 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001919}
1920
Harald Welte4003d112017-12-09 22:35:39 +01001921type record DchanTuple {
1922 integer sccp_conn_id,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001923 RslChannelNr rsl_chan_nr,
1924 BtsTrxIdx idx
Harald Weltea5d2ab22017-12-09 14:21:42 +01001925}
1926
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +02001927type record of DchanTuple DchanTuples;
1928
Harald Welted6939652017-12-13 21:02:46 +01001929/* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001930private function f_chreq_act_ack(OCT1 ra := '23'O,
1931 GsmFrameNumber fn := 23,
1932 BtsTrxIdx idx := {0, 0})
Harald Welted6939652017-12-13 21:02:46 +01001933runs on test_CT return RslChannelNr {
1934 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001935 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
1936 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Harald Welted6939652017-12-13 21:02:46 +01001937 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001938 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10), idx);
1939 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Harald Welted6939652017-12-13 21:02:46 +01001940 return chan_nr;
1941}
1942
Harald Welte4003d112017-12-09 22:35:39 +01001943/* helper function to establish a dedicated channel via BTS and MSC */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001944function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1945 BtsTrxIdx idx := {0, 0})
Harald Welte4003d112017-12-09 22:35:39 +01001946runs on test_CT return DchanTuple {
1947 var BSSAP_N_CONNECT_ind rx_c_ind;
Harald Welte4003d112017-12-09 22:35:39 +01001948 var DchanTuple dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001949
Harald Welte4003d112017-12-09 22:35:39 +01001950 /* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001951 dt.rsl_chan_nr := f_chreq_act_ack(ra, fn, idx);
Harald Welte4003d112017-12-09 22:35:39 +01001952
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001953 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 +01001954
1955 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1956 dt.sccp_conn_id := rx_c_ind.connectionId;
1957 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1958
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001959 dt.idx := idx;
Harald Welte4003d112017-12-09 22:35:39 +01001960 return dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001961}
1962
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001963/* 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 +06001964function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1965 BtsTrxIdx idx := {0, 0})
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001966runs on test_CT return DchanTuple {
1967 var BSSAP_N_CONNECT_ind rx_c_ind;
1968 var DchanTuple dt;
1969
1970 /* Send CHAN RQD */
1971 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001972 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001973
1974 /* The dyn TS first deactivates PDCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001975 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 +02001976 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001977 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001978
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001979 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001980 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1981
1982 /* Now activates the signalling channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001983 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10), idx);
1984 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001985
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001986 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 +02001987
1988 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1989 dt.sccp_conn_id := rx_c_ind.connectionId;
1990 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1991
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001992 dt.idx := idx;
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001993 return dt;
1994}
1995
Harald Welte641fcbe2018-06-14 10:58:35 +02001996/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001997private function f_exp_chan_rel_and_clear(DchanTuple dt)
1998runs on test_CT {
Harald Welte641fcbe2018-06-14 10:58:35 +02001999 var RSL_Message rx_rsl;
2000 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002001 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 +02002002 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002003 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), dt.idx);
Harald Welte641fcbe2018-06-14 10:58:35 +02002004
2005 /* expect Clear Complete from BSC */
2006 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2007
2008 /* MSC disconnects as instructed. */
2009 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2010}
2011
Harald Welte4003d112017-12-09 22:35:39 +01002012/* Test behavior of channel release after unilateral RLL REL IND (DISC from MS) */
2013testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002014 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002015 var DchanTuple dt;
Harald Welte96c94412017-12-09 03:12:45 +01002016
Harald Welte89d42e82017-12-17 16:42:41 +01002017 f_init(1);
Harald Welte96c94412017-12-09 03:12:45 +01002018
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002019 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002020
2021 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002022 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Harald Welte4003d112017-12-09 22:35:39 +01002023
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002024 /* expect Clear Request on MSC side */
2025 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2026
2027 /* Instruct BSC to clear channel */
2028 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2029 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2030
Harald Welte4003d112017-12-09 22:35:39 +01002031 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002032 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002033
2034 /* wait for SCCP emulation to do its job */
2035 f_sleep(1.0);
Harald Welte4003d112017-12-09 22:35:39 +01002036
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002037 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002038}
2039
2040/* Test behavior of channel release after CONN FAIL IND from BTS */
2041testcase TC_chan_rel_conn_fail() runs on test_CT {
2042 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002043 var DchanTuple dt;
2044
Harald Welte89d42e82017-12-17 16:42:41 +01002045 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002046
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002047 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002048
Vadim Yanitskiy01d0a902022-12-14 22:41:42 +07002049 /* Sending CONN FAIL IND immediately may trigger a race condition.
2050 * Give the BSC some time to process a new SCCP connection (OS#5823). */
2051 f_sleep(0.2);
2052
Harald Welte4003d112017-12-09 22:35:39 +01002053 /* simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002054 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte4003d112017-12-09 22:35:39 +01002055 /* TODO: different cause values? */
2056
Harald Welte4003d112017-12-09 22:35:39 +01002057 /* expect Clear Request from BSC */
2058 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2059
2060 /* Instruct BSC to clear channel */
2061 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2062 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2063
Harald Welte6ff76ea2018-01-28 13:08:01 +01002064 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002065 f_exp_chan_rel_and_clear(dt);
Harald Welte4003d112017-12-09 22:35:39 +01002066
2067 /* wait for SCCP emulation to do its job */
2068 f_sleep(1.0);
2069
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002070 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002071}
2072
Harald Welte99f3ca02018-06-14 13:40:29 +02002073/* Test behavior of early CONN FAIL IND from BTS (before EST IND!) */
2074/* See also https://www.osmocom.org/issues/3182 */
2075testcase TC_early_conn_fail() runs on test_CT {
2076 var RSL_Message rx_rsl;
2077 var DchanTuple dt;
2078
2079 f_init(1);
2080
2081 /* BTS->BSC: Send CHAN RQD and wait for allocation; acknowledge it */
Harald Weltec46ea3c2020-10-10 18:46:12 +02002082 dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_ra_cs(), 23);
Harald Welte99f3ca02018-06-14 13:40:29 +02002083
2084 /* BTS->BSC: simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002085 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002086
2087 /* BTS->BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002088 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002089
2090 /* BTS<-BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002091 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002092
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002093 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002094}
2095
2096/* Test behavior of late CONN FAIL IND from BTS (ater REL IND!) */
2097/* See also https://www.osmocom.org/issues/3182 */
2098testcase TC_late_conn_fail() runs on test_CT {
2099 var RSL_Message rx_rsl;
2100 var DchanTuple dt;
2101
2102 f_init(1);
2103
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002104 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99f3ca02018-06-14 13:40:29 +02002105
2106 /* BSC<-MSC: Instruct BSC to clear connection */
2107 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(0)));
2108
2109 /* BTS->BSC: expect BSC to deactivate SACCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002110 rx_rsl := f_exp_ipa_rx(tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002111
2112 /* BTS->BSC: simulate a late CONN FAIL IND from BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002113 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002114
2115 /* BTS<-BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002116 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002117 /* BTS->BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002118 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002119
2120 /* BSC->MSC: expect Clear Complete from BSC */
2121 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2122
2123 /* BSC<-MSC: MSC disconnects as requested. */
2124 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2125
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002126 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002127}
2128
Oliver Smithaf03bef2021-08-24 15:34:51 +02002129private function f_TC_stats_conn_fail(charstring id) runs on MSC_ConnHdlr {
2130 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
2131 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2132
2133 f_statsd_reset();
2134
Oliver Smith15890b42023-03-08 14:12:28 +01002135 /* Establish SDCCH (invalid DataIndicator for exp_fail) */
Oliver Smithaf03bef2021-08-24 15:34:51 +02002136 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smith15890b42023-03-08 14:12:28 +01002137 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := 'ff'O;
Oliver Smithaf03bef2021-08-24 15:34:51 +02002138 f_establish_fully(ass_cmd, exp_fail);
2139
2140 /* Expect stats to be 0 */
2141 var StatsDExpects expect := {
2142 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
2143 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
2144 };
2145 f_statsd_expect(expect);
2146
2147 /* Simulate CONN FAIL IND on SDCCH */
2148 RSL.send(ts_ASP_RSL_UD(
2149 ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
2150 IPAC_PROTO_RSL_TRX0));
2151
Neels Hofmeyr58be48a2021-09-07 18:39:21 +02002152 f_sleep(1.0);
2153
Oliver Smithaf03bef2021-08-24 15:34:51 +02002154 /* Expect stats to be 1 */
2155 expect := {
2156 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
2157 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
2158 };
2159 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002160 BSSAP.receive(tr_BSSMAP_ClearRequest);
2161 f_perform_clear();
Oliver Smithaf03bef2021-08-24 15:34:51 +02002162}
2163testcase TC_stats_conn_fail() runs on test_CT {
2164 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2165 var MSC_ConnHdlr vc_conn;
2166
2167 f_init(1, true);
2168 f_sleep(1.0);
2169
2170 vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
2171 vc_conn.done;
2172
2173 f_shutdown_helper();
2174}
2175
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002176function f_expect_chan_rel(RslChannelNr rsl_chan_nr,
2177 BtsTrxIdx idx := {0, 0},
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002178 boolean expect_deact_sacch := true,
2179 boolean expect_rr_chan_rel := true,
2180 boolean expect_rll_rel_req := true,
Harald Welte99787102019-02-04 10:41:36 +01002181 boolean handle_rll_rel := true,
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002182 template CellSelIndValue expect_cells := omit,
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002183 template (present) RR_Cause expect_rr_cause := ?
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002184 ) runs on test_CT {
Harald Welte91d54a52018-01-28 15:35:07 +01002185
2186 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002187 var boolean got_deact_sacch := false;
2188 var boolean got_rr_chan_rel := false;
2189 var boolean got_rll_rel_req := false;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002190 var ASP_RSL_Unitdata ud;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002191 var RSL_IE_Body l3_ie;
2192 var PDU_ML3_NW_MS l3;
2193 var RR_Cause got_cause;
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002194 log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
2195 " expect_rll_rel_req=", expect_rll_rel_req);
Harald Welte91d54a52018-01-28 15:35:07 +01002196 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002197 [] 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 +01002198 got_deact_sacch := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002199 repeat;
2200 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002201 [] 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 +01002202 got_rr_chan_rel := true;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002203
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002204 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2205 setverdict(fail, "cannot find L3");
2206 mtc.stop;
2207 }
2208 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2209
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002210 if (not istemplatekind(expect_cells, "omit")) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002211 var CellSelIndValue cells := dec_CellSelIndValue(
2212 l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
2213
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002214 log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
2215 if (match(cells, expect_cells)) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002216 setverdict(pass);
2217 } else {
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002218 log("EXPECTED CELLS: ", expect_cells);
2219 setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002220 }
2221 }
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002222
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002223 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2224 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2225 if (match(got_cause, expect_rr_cause)) {
2226 setverdict(pass);
2227 } else {
2228 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2229 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002230 }
Harald Welte99787102019-02-04 10:41:36 +01002231 repeat;
2232 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002233 [] 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 +01002234 got_rll_rel_req := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002235 /* FIXME: Why are we getting this for LinkID SACCH? */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002236 if (handle_rll_rel) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002237 f_ipa_tx(ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002238 }
Harald Welte91d54a52018-01-28 15:35:07 +01002239 repeat;
2240 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002241 [] 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 +01002242 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002243 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
Harald Welte91d54a52018-01-28 15:35:07 +01002244 }
2245 /* ignore any user data */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002246 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002247 repeat;
2248 }
2249 }
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002250
2251 log("f_expect_chan_rel() summary: got_deact_sacch=", got_deact_sacch, " got_rr_chan_rel=", got_rr_chan_rel,
2252 " got_rll_rel_req=", got_rll_rel_req);
2253
2254 if (expect_deact_sacch != got_deact_sacch) {
2255 setverdict(fail, "f_expect_chan_rel(): expect_deact_sacch=", expect_deact_sacch, " got_deact_sacch=", got_deact_sacch);
2256 }
2257 if (expect_rr_chan_rel != got_rr_chan_rel) {
2258 setverdict(fail, "f_expect_chan_rel(): expect_rr_chan_rel=", expect_rr_chan_rel, " got_rr_chan_rel=", got_rr_chan_rel);
2259 }
2260 if (expect_rll_rel_req != got_rll_rel_req) {
2261 setverdict(fail, "f_expect_chan_rel(): expect_rll_rel_req=", expect_rll_rel_req, " got_rll_rel_req=", got_rll_rel_req);
2262 }
Harald Welte91d54a52018-01-28 15:35:07 +01002263}
2264
Harald Welte4003d112017-12-09 22:35:39 +01002265/* Test behavior of channel release after hard Clear Command from MSC */
2266testcase TC_chan_rel_hard_clear() runs on test_CT {
2267 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002268 var DchanTuple dt;
Harald Welte4003d112017-12-09 22:35:39 +01002269
Harald Welte89d42e82017-12-17 16:42:41 +01002270 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002271
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002272 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002273
2274 /* Instruct BSC to clear channel */
2275 var BssmapCause cause := 0;
2276 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2277
2278 /* expect Clear Complete from BSC on A */
2279 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2280 /* release the SCCP connection */
2281 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2282 }
2283
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002284 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002285 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002286}
2287
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002288function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
2289 var BSSAP_N_DATA_ind rx_di;
2290 var DchanTuple dt;
2291
2292 f_init(1);
2293
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002294 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002295 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2296 /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
2297 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
2298
2299 /* Instruct BSC to clear channel */
2300 var BssmapCause cause := 0;
2301 if (tx_csfb_ind) {
2302 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2303 } else {
2304 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2305 }
2306
2307 /* expect Clear Complete from BSC on A */
2308 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2309 /* release the SCCP connection */
2310 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2311 }
2312
2313 /* 1 neighbor is added by default in osmo-bts.cfg and
2314 SystemInformationConfig_default, use that: */
2315 var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
2316
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002317 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 +02002318 f_shutdown_helper();
2319}
2320
2321/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
2322 from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
2323 PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2324 EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
2325 Indicator or not shouldn't matter at all. */
2326testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
2327 f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
2328}
2329
2330/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
2331 MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
2332 Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2333 EUTRAN neighbor list sent later on by BSC in RR Channel. */
2334testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
2335 f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
2336}
2337
2338/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
2339 MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
2340 Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
2341 CSFB Indicator should not be used anymore, and hence, there should be no
2342 EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
2343 Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
Harald Welte99787102019-02-04 10:41:36 +01002344testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
2345 var BSSAP_N_DATA_ind rx_di;
2346 var DchanTuple dt;
2347
2348 f_init(1);
2349
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002350 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99787102019-02-04 10:41:36 +01002351
2352 /* Instruct BSC to clear channel */
2353 var BssmapCause cause := 0;
2354 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2355
2356 /* expect Clear Complete from BSC on A */
2357 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2358 /* release the SCCP connection */
2359 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2360 }
2361
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002362 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002363 f_shutdown_helper();
Harald Welte99787102019-02-04 10:41:36 +01002364}
2365
Harald Welted8c36cd2017-12-09 23:05:31 +01002366/* Test behavior of channel release after hard RLSD from MSC */
2367testcase TC_chan_rel_hard_rlsd() runs on test_CT {
Harald Welted8c36cd2017-12-09 23:05:31 +01002368 var DchanTuple dt;
Harald Welted8c36cd2017-12-09 23:05:31 +01002369
Harald Welte89d42e82017-12-17 16:42:41 +01002370 f_init(1);
Harald Welted8c36cd2017-12-09 23:05:31 +01002371
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002372 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welted8c36cd2017-12-09 23:05:31 +01002373
2374 /* release the SCCP connection */
2375 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2376
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002377 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002378 f_shutdown_helper();
Harald Welted8c36cd2017-12-09 23:05:31 +01002379}
2380
Harald Welte550daf92018-06-11 19:22:13 +02002381/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
2382testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
2383 var DchanTuple dt;
2384
2385 f_init(1);
2386
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002387 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte550daf92018-06-11 19:22:13 +02002388
2389 /* release the SCCP connection */
2390 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2391
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002392 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002393 f_shutdown_helper();
Harald Welte550daf92018-06-11 19:22:13 +02002394}
2395
Harald Welte85804d42017-12-10 14:11:58 +01002396/* Test behavior of channel release after BSSMAP RESET from MSC */
2397testcase TC_chan_rel_a_reset() runs on test_CT {
Harald Welte85804d42017-12-10 14:11:58 +01002398 var DchanTuple dt;
Harald Welte85804d42017-12-10 14:11:58 +01002399
Harald Welte89d42e82017-12-17 16:42:41 +01002400 f_init(1);
Harald Welte85804d42017-12-10 14:11:58 +01002401
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002402 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte85804d42017-12-10 14:11:58 +01002403
2404 /* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002405 IPA_RSL[0][0].clear;
Harald Welte85804d42017-12-10 14:11:58 +01002406
2407 /* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002408 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 +01002409 interleave {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002410 [] 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 +01002411 [] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
2412 }
2413
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002414 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002415 f_shutdown_helper();
Harald Welte85804d42017-12-10 14:11:58 +01002416}
2417
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002418/* Verify T(iar) triggers and releases the channel */
2419testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
2420 var DchanTuple dt;
2421
2422 /* Set T(iar) in BSC low enough that it will trigger before other side
2423 has time to keep alive with a T(ias). Keep recommended ratio of
2424 T(iar) >= T(ias)*2 */
2425 g_bsc_sccp_timer_ias := 2;
2426 g_bsc_sccp_timer_iar := 5;
2427
2428 f_init(1);
2429
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002430 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002431 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002432 f_shutdown_helper();
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002433}
2434
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002435private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause,
2436 template (present) RR_Cause expect_rr_cause)
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002437runs on test_CT
2438{
2439 var DchanTuple dt;
2440
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002441 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002442 var BssmapCause cause := 0;
2443 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
2444 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2445 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2446 }
2447
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002448 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 +02002449}
2450
2451/* Test that Clear Command cause codes affect the RR Channel Release cause code */
2452testcase TC_chan_rel_rr_cause() runs on test_CT {
2453 f_init(1);
2454
2455 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
2456 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
2457 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
2458 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
2459 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
2460 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
Vadim Yanitskiye18aebb2021-01-03 13:10:43 +01002461
2462 f_shutdown_helper();
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002463}
2464
Harald Welte5cd20ed2017-12-13 21:03:20 +01002465/* Test behavior if RSL EST IND for non-active channel */
2466testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
2467 timer T := 2.0;
2468
Harald Welte89d42e82017-12-17 16:42:41 +01002469 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002470
Harald Welte5cd20ed2017-12-13 21:03:20 +01002471 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002472 var octetstring l3_payload := gen_l3_valid_payload();
2473 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002474
2475 T.start;
2476 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002477 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002478 setverdict(fail, "MSC received COMPL L3 for non-active lchan");
2479 }
2480 [] BSSAP.receive {}
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002481 [] IPA_RSL[0][0].receive {}
Harald Welte5cd20ed2017-12-13 21:03:20 +01002482 [] T.timeout {}
2483 }
2484
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002485 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002486}
2487
2488/* Test behavior if RSL EST IND for invalid SAPI */
2489testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
2490 var RslChannelNr chan_nr;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002491 var octetstring l3_payload;
Harald Welte5cd20ed2017-12-13 21:03:20 +01002492
Harald Welte89d42e82017-12-17 16:42:41 +01002493 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002494
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002495 chan_nr := f_chreq_act_ack();
2496 l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002497
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002498 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002499
2500 timer T := 2.0;
2501 T.start;
2502 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002503 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002504 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
2505 }
2506 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002507 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002508 [] T.timeout {}
2509 }
2510
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002511 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002512}
2513
2514/* Test behavior if RSL EST IND for invalid SAPI */
2515testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
2516 timer T := 2.0;
2517
Harald Welte89d42e82017-12-17 16:42:41 +01002518 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002519
2520 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002521 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002522
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002523 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002524
2525 T.start;
2526 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002527 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002528 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
2529 }
2530 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002531 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002532 [] T.timeout {}
2533 }
2534
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002535 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002536}
2537
2538/* Test behavior if RSL EST IND for invalid SACCH */
2539testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
2540 timer T := 2.0;
2541
Harald Welte89d42e82017-12-17 16:42:41 +01002542 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002543
2544 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002545 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002546
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002547 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002548
2549 T.start;
2550 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002551 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002552 setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
2553 }
2554 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002555 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002556 [] T.timeout {}
2557 }
2558
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002559 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002560}
2561
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002562/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
2563private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
2564 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
2565 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2566
2567 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
2568 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
2569
2570 f_establish_fully(ass_cmd, exp_compl);
2571
2572 /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
2573 RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
2574 /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
2575 BSSAP.receive(PDU_BSSAP:{
2576 discriminator := '1'B,
2577 spare := '0000000'B,
2578 dlci := 'C3'O,
2579 lengthIndicator := ?,
2580 pdu := { dtap := '0904'O }
2581 });
2582
2583 /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
2584 for (var integer i := 0; i < 32; i := i + 1) {
2585 var octetstring l3 := '09'O & f_rnd_octstring(14);
2586 var template (value) RslLinkId link_id;
2587 var template (value) OCT1 dlci;
2588
2589 if (i mod 2 == 0) {
2590 /* SAPI0 on FACCH or SDCCH */
2591 link_id := ts_RslLinkID_DCCH(0);
2592 dlci := '80'O;
2593 } else {
2594 /* SAPI3 on SACCH */
2595 link_id := ts_RslLinkID_SACCH(3);
2596 dlci := 'C3'O;
2597 }
2598
2599 /* Send MO message: RSL -> BSSAP */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002600 f_mo_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002601 /* Send MT message: BSSAP -> RSL */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002602 f_mt_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002603 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002604 f_perform_clear();
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002605}
2606testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
2607 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2608 var MSC_ConnHdlr vc_conn;
2609
2610 f_init(1, true);
2611 f_sleep(1.0);
2612
2613 vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
2614 vc_conn.done;
2615
2616 f_shutdown_helper();
2617}
2618
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002619private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002620 template (present) myBSSMAP_Cause cause := ?,
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002621 template (present) BIT2 cc := ?,
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002622 float T_val := 2.0)
2623runs on test_CT {
2624 var BSSAP_N_DATA_ind rx_di;
2625 timer T;
2626
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002627 var template (present) BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
2628 var template (present) PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002629
2630 T.start(T_val);
2631 alt {
2632 [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
2633 var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
2634 if (not match(rx_cause, tr_cause)) {
2635 setverdict(fail, "Rx unexpected Cause IE: ",
2636 rx_cause, " vs expected ", tr_cause);
2637 }
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002638
2639 /* Who ever on the earth decided to define this field as two separate bits?!? */
2640 var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
2641 & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
2642 if (not match(rx_cc, cc)) {
2643 setverdict(fail, "Rx unexpected Control Channel type: ",
2644 rx_cc, " vs expected ", cc);
2645 }
2646
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002647 setverdict(pass);
2648 }
2649 [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
2650 setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
2651 }
2652 [] T.timeout {
2653 setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
2654 }
2655 }
2656}
2657
2658/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
2659testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002660 var RSL_Message rx_rsl;
2661 var DchanTuple dt;
2662
2663 f_init(1);
2664
2665 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002666 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002667
2668 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002669 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 +07002670 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002671 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 +07002672
2673 /* MS sends unexpected RELease INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002674 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002675 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2676 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
2677
2678 /* Clean up the connection */
2679 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002680 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002681
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002682 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002683}
2684
2685/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
2686testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002687 var RSL_Message rx_rsl;
2688 var DchanTuple dt;
2689
2690 f_init(1);
2691
2692 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002693 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002694
2695 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002696 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 +07002697 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002698 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 +07002699
2700 /* BTS sends unexpected ERROR INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002701 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002702 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2703 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
2704
2705 /* Clean up the connection */
2706 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002707 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002708
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002709 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002710}
2711
2712/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
2713testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002714 var RSL_Message rx_rsl;
2715 var DchanTuple dt;
2716
2717 f_init(1);
2718
2719 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002720 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002721
2722 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002723 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 +07002724 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002725 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 +07002726
2727 /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
2728 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
2729
2730 /* Clean up the connection */
2731 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002732 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002733
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002734 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002735}
2736
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002737/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
2738testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002739 var RSL_Message rx_rsl;
2740 var DchanTuple dt;
2741
2742 f_init(1);
2743
2744 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002745 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002746
2747 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002748 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 +07002749 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002750 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 +07002751
2752 /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002753 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Pau Espin Pedrol121f27f2022-01-12 12:02:10 +01002754 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, '10'B);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002755
2756 /* Clean up the connection */
2757 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002758 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002759
2760 f_shutdown_helper();
2761}
2762
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002763testcase TC_si_default() runs on test_CT {
2764 f_init(0);
2765 f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002766 f_shutdown_helper();
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002767}
Harald Welte4003d112017-12-09 22:35:39 +01002768
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002769/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
2770 * the entire value range. This function provides the same EARFCN numbers for the same earfcn_index */
2771private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uint16_t
2772{
2773 select (earfcn_index) {
2774 case (0) {
2775 /* E-ARFCN 111 is already added in the osmo-bsc.cfg */
2776 return 111;
2777 }
2778 case (1) {
2779 return 1;
2780 }
2781 case (2) {
2782 return 0;
2783 }
2784 case (3) {
2785 return 65535;
2786 }
2787 case else {
2788 return 23 * (earfcn_index - 3);
2789 }
2790 }
2791}
2792
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002793function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
2794 template CellSelIndValue expect_cells := omit) runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002795
2796 f_init(0);
2797
2798 /* E-ARFCN 111 is already added in the osmo-bsc.cfg, so only add more arfcns if total_earfcns > 1 */
2799 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002800 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2801 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002802 }
2803
2804 f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
2805
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002806 if (not istemplatekind(expect_cells, "omit")) {
2807 /* Also check that RR Channel Release contains these EARFCNs.
2808 * (copied code from TC_chan_rel_hard_clear_csfb) */
2809 var BSSAP_N_DATA_ind rx_di;
2810 var DchanTuple dt;
2811
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002812 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrold0046312021-04-19 16:35:58 +02002813 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2814 * yet when generating the EUTRAN neigh list in RR CHannel Release) */
2815 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002816
2817 /* Instruct BSC to clear channel */
2818 var BssmapCause cause := 0;
2819 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2820
2821 /* expect Clear Complete from BSC on A */
2822 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2823 /* release the SCCP connection */
2824 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2825 }
2826
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002827 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := expect_cells);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002828 }
2829
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002830 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002831 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 +02002832 }
2833}
2834
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002835private function f_tr_si2quater_earfcns(integer count) return template SI2quaterRestOctetsList
2836{
2837 var template SI2quaterRestOctetsList si2quater := {};
2838 var integer si2quater_count := (count + 2) / 3;
2839
2840 for (var integer i := 0; i < count; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002841 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002842 var integer index := i / 3;
2843 var integer earfcn_index := i mod 3;
2844 if (index >= lengthof(si2quater)) {
2845 si2quater[index] := tr_SI2quaterRestOctets_EUTRAN(index := index, count := si2quater_count - 1);
2846 }
2847 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);
2848 }
2849
2850 return si2quater;
2851}
2852
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002853private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
2854{
2855 var template CellSelIndValue_EUTRAN_Descrs cells := {};
2856
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002857 /* the lte neighbors must match the config & vty to pass this test */
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002858 for (var integer i := 0; i < count; i := i + 1) {
2859 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002860 cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002861 }
2862
2863 return tr_CellSelIndValue_EUTRAN(cells);
2864}
2865
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002866private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
2867{
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002868 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrol8ab62e42020-12-18 16:19:11 +01002869 sic.si2quater := f_tr_si2quater_earfcns(n);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002870 var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
2871 f_test_si2quater(n, sic, cells);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002872}
2873
2874testcase TC_si2quater_2_earfcns() runs on test_CT {
2875 f_tc_si2quater_n_earfcns(2);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002876 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002877}
2878
2879testcase TC_si2quater_3_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002880 f_tc_si2quater_n_earfcns(3);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002881 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002882}
2883
2884testcase TC_si2quater_4_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002885 f_tc_si2quater_n_earfcns(4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002886 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002887}
2888
2889testcase TC_si2quater_5_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002890 f_tc_si2quater_n_earfcns(5);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002891 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002892}
2893
2894testcase TC_si2quater_6_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002895 f_tc_si2quater_n_earfcns(6);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002896 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002897}
2898
2899testcase TC_si2quater_12_earfcns() runs on test_CT {
2900 f_tc_si2quater_n_earfcns(12);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002901 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002902}
2903
2904testcase TC_si2quater_23_earfcns() runs on test_CT {
2905 f_tc_si2quater_n_earfcns(23);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002906 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002907}
2908
2909testcase TC_si2quater_32_earfcns() runs on test_CT {
2910 f_tc_si2quater_n_earfcns(32);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002911 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002912}
2913
2914testcase TC_si2quater_33_earfcns() runs on test_CT {
2915 f_tc_si2quater_n_earfcns(33);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002916 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002917}
2918
2919testcase TC_si2quater_42_earfcns() runs on test_CT {
2920 f_tc_si2quater_n_earfcns(42);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002921 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002922}
2923
2924testcase TC_si2quater_48_earfcns() runs on test_CT {
2925 f_tc_si2quater_n_earfcns(48);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002926 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002927}
2928
2929/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
2930 * 48 EARFCNs. */
2931testcase TC_si2quater_49_earfcns() runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002932 var template SystemInformationConfig sic := SystemInformationConfig_default;
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002933 sic.si2quater := f_tr_si2quater_earfcns(48); /* 48, not 49! */
2934 f_init(0);
2935
2936 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002937 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2938 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002939 }
2940
2941 /* The 49th EARFCN no longer fits, expect VTY error */
2942 f_vty_enter_cfg_bts(BSCVTY, 0);
2943 var charstring vty_error;
2944 vty_error := f_vty_transceive_ret(BSCVTY,
2945 "si2quater neighbor-list add earfcn 70 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3")
2946 f_vty_transceive(BSCVTY, "end");
2947
2948 if (f_strstr(vty_error, "Unable to add ARFCN 70") >= 0) {
2949 log("Got expected VTY error: ", vty_error);
2950 setverdict(pass);
2951 } else {
2952 setverdict(fail, "Expected the 49th EUTRAN ARFCN to be rejected by vty config, got: ", vty_error);
2953 }
2954
2955 f_init_bts_and_check_sysinfo(0, expect_si := sic);
2956
2957 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002958 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 +02002959 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002960 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002961}
2962
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002963private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
2964{
2965 var uint8_t count := 0;
2966 for (var integer i := 5; i < 16; i := i + 1) {
2967 if (acc[i] == '0'B) { /* the list marks barred, we count allowed */
2968 count := count + 1;
2969 }
2970 }
2971 return count;
2972}
2973
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002974private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return SystemInformationType1
2975{
2976 var ASP_RSL_Unitdata rx_rsl_ud;
2977 var SystemInformationType1 last_si1;
2978
2979 timer T := 30.0;
2980 T.start;
2981 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002982 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
2983 tr_RSL_BCCH_INFO,
2984 tr_RSL_NO_SACCH_FILL,
2985 tr_RSL_SACCH_FILL))) -> value rx_rsl_ud {
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002986 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
2987 if (g_system_information[rsl_idx].si1 == omit) {
2988 repeat;
2989 }
2990 last_si1 := g_system_information[rsl_idx].si1;
2991 g_system_information[rsl_idx].si1 := omit;
2992 T.stop;
2993 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002994 [] IPA_RSL[rsl_idx][0].receive { repeat; }
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002995 [] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
2996 }
2997 return last_si1;
2998}
2999
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003000/* verify ACC rotate feature */
3001testcase TC_si_acc_rotate() runs on test_CT {
3002 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003003 var SystemInformationType1 last_si1;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003004 var AccessControlClass acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003005 var uint8_t count;
3006 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3007
3008 f_init(0, guard_timeout := 60.0);
3009
3010 f_bts_0_cfg(BSCVTY, {"rach access-control-class 5 barred",
3011 "access-control-class-rotate 3",
3012 "access-control-class-rotate-quantum 1"});
3013
3014 /* Init and get first sysinfo */
3015 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3016
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003017 for (var integer i:= 0; i < 20; i := i + 1) {
3018 last_si1 := f_recv_next_si1(0);
3019 acc := last_si1.rach_control.acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003020 count := f_acc09_count_allowed(acc);
3021 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3022
3023 if (count != 3) {
3024 log("RSL: EXPECTED SI ACC len=3");
3025 setverdict(fail, "received SI does not match expectations");
3026 break;
3027 }
3028
3029 for (var integer j := 0; j < 10; j := j + 1) {
3030 if (acc[16 - 1 - j] == '0'B) { /* the list marks barred, we count allowed */
3031 times_allowed[j] := times_allowed[j] + 1;
3032 }
3033 }
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003034 }
3035
3036 for (var integer j := 0; j < 10; j := j + 1) {
3037 log("ACC", j, " allowed ", times_allowed[j], " times" );
3038 if (j != 5 and times_allowed[j] < 3) {
3039 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " < 1 times");
3040 } else if (j == 5 and times_allowed[j] > 0) {
3041 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " > 0 times");
3042 }
3043 }
3044
3045 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3046 "rach access-control-class 5 allowed"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003047 f_shutdown_helper();
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003048}
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02003049
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003050/* verify ACC startup ramp+rotate feature */
3051testcase TC_si_acc_ramp_rotate() runs on test_CT {
3052 var template SystemInformationConfig sic := SystemInformationConfig_default;
3053 var SystemInformationType1 last_si1;
3054 var AccessControlClass acc;
3055 var ASP_RSL_Unitdata rx_rsl_ud;
3056 var uint8_t count;
3057 var uint8_t prev_count;
3058 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3059
3060 f_init(0, guard_timeout := 80.0);
3061
3062 f_bts_0_cfg(BSCVTY, {"rach access-control-class 4 barred",
3063 "access-control-class-rotate 0",
3064 "access-control-class-rotate-quantum 1",
3065 "access-control-class-ramping",
3066 "access-control-class-ramping-step-interval 5",
3067 "access-control-class-ramping-step-size 5"});
3068
3069 /* Init and get first sysinfo */
3070 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3071 last_si1 := g_system_information[0].si1;
3072 acc := last_si1.rach_control.acc;
3073 count := f_acc09_count_allowed(acc);
3074 /* Adm subset size was set to 0 above, so wait until all ACC are barred */
3075 while (count > 0) {
3076 last_si1 := f_recv_next_si1(0);
3077 acc := last_si1.rach_control.acc;
3078 count := f_acc09_count_allowed(acc);
3079 log("RSL: wait len()=0: GOT SI1 ACC len=", count, ": ", acc);
3080 }
3081
3082 /* Increase adm subset size, we should see ramping start up */
3083 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10"});
3084 prev_count := 0;
3085 while (true) {
3086 last_si1 := f_recv_next_si1(0);
3087 acc := last_si1.rach_control.acc;
3088 count := f_acc09_count_allowed(acc);
3089 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3090
3091 if (prev_count > count) {
3092 setverdict(fail, "ACC allowed count dropped while expecting grow: ", prev_count, " -> ", count);
3093 break;
3094 }
3095
3096 if (count == 9) {
3097 break; /* Maximum reached (10 - 1 perm barred), done here */
3098 }
3099
3100 prev_count := count;
3101 }
3102
3103 setverdict(pass);
3104
3105 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3106 "rach access-control-class 4 allowed",
3107 "no access-control-class-ramping"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003108 f_shutdown_helper();
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003109}
3110
Oliver Smith45a6dd32023-09-27 10:52:50 +02003111/* Verify NCC Permitted in System Information Type 2
3112 * 3GPP TS 44.018 § 10.5.2.27 */
3113testcase TC_si2_ncc_permitted() runs on test_CT {
3114 var ASP_RSL_Unitdata rx_rsl_ud;
3115 timer T := 5.0;
3116 var BIT8 exp;
3117
3118 f_init_vty();
3119
3120 /* Set NCC Permitted to 6 7 8 */
3121 f_vty_enter_cfg_bts(BSCVTY, 0);
3122 f_vty_transceive(BSCVTY, "ncc-permitted 6 7 8");
3123 f_vty_transceive(BSCVTY, "end");
3124 exp := '11100000'B;
3125
3126 f_init(1);
3127 T.start;
3128
3129 /* Check value in SI 2 */
3130 alt {
3131 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO(RSL_SYSTEM_INFO_2))) -> value rx_rsl_ud {
3132 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
3133 var SystemInformation si := dec_SystemInformation(ie.other.payload);
3134
3135 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_2) {
3136 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
3137 repeat;
3138 }
3139
3140 if (si.payload.si2.ncc_permitted != exp) {
3141 setverdict(fail, "NCC Permitted is ", si.payload.si2.ncc_permitted, " but expected ", exp);
3142 break;
3143 }
3144
3145 }
3146 [] IPA_RSL[0][0].receive { repeat; }
3147 [] T.timeout {
3148 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI2)");
3149 }
3150 }
3151
3152 /* Reset NCC Permitted to default (all permitted). This is already
3153 * getting tested in TC_si_default(). */
3154 f_vty_enter_cfg_bts(BSCVTY, 0);
3155 f_vty_transceive(BSCVTY, "ncc-permitted all");
3156 f_vty_transceive(BSCVTY, "end");
3157
3158 f_shutdown_helper();
3159}
3160
Harald Welte4003d112017-12-09 22:35:39 +01003161testcase TC_ctrl_msc_connection_status() runs on test_CT {
3162 var charstring ctrl_resp;
3163
Harald Welte89d42e82017-12-17 16:42:41 +01003164 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003165
3166 /* See https://osmocom.org/issues/2729 */
3167 f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003168 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01003169}
3170
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003171testcase TC_ctrl_msc0_connection_status() runs on test_CT {
3172 var charstring ctrl_resp;
3173
3174 f_init(1);
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003175
3176 f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003177 f_shutdown_helper();
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003178}
3179
Neels Hofmeyr0bc470d2021-08-21 13:37:13 +02003180/* Verify correct stats on the number of configured and connected MSCs */
3181private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
3182 g_pars := f_gen_test_hdlr_pars();
3183 var StatsDExpects expect := {
3184 { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
3185 { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
3186 };
3187 f_statsd_expect(expect);
3188}
3189
3190private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
3191{
3192 var MSC_ConnHdlr vc_conn;
3193
3194 f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
3195 f_sleep(1.0);
3196 vc_conn := f_start_handler(tc_fn);
3197 vc_conn.done;
3198
3199 /* Also verify stat exposed on CTRL interface */
3200 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
3201 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
3202
3203 f_shutdown_helper();
3204}
3205
3206/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
3207private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
3208 f_tc_stat_num_msc_connected_msc_connhdlr(1);
3209}
3210testcase TC_stat_num_msc_connected_1() runs on test_CT {
3211 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
3212}
3213
3214/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
3215private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
3216 f_tc_stat_num_msc_connected_msc_connhdlr(2);
3217}
3218testcase TC_stat_num_msc_connected_2() runs on test_CT {
3219 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
3220}
3221
3222/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
3223private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
3224 f_tc_stat_num_msc_connected_msc_connhdlr(3);
3225}
3226testcase TC_stat_num_msc_connected_3() runs on test_CT {
3227 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
3228}
3229
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003230/* Verify correct stats on the number of configured and connected MSCs */
3231private 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 +06003232 var integer num_trx_connected := 0;
3233 var integer num_trx_total := 0;
3234
3235 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3236 var integer trx_num := c_BtsParams[i].trx_num;
3237 num_trx_total := num_trx_total + trx_num;
3238 if (i < expect_num_bts_connected) {
3239 num_trx_connected := num_trx_connected + trx_num;
3240 }
3241 }
3242
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003243 var StatsDExpects expect := {
3244 { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
3245 { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3246 { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003247 { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := num_trx_connected, max := num_trx_connected },
3248 { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := num_trx_total, max := num_trx_total }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003249 };
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003250
3251 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003252 f_statsd_expect(expect);
3253}
3254
3255private 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 +06003256 var integer num_trx_connected := 0;
3257 var integer num_trx_total := 0;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003258 var MSC_ConnHdlr vc_conn;
3259
3260 f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
3261 f_sleep(1.0);
3262 vc_conn := f_start_handler(tc_fn);
3263 vc_conn.done;
3264
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003265 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3266 var integer trx_num := c_BtsParams[i].trx_num;
3267 num_trx_total := num_trx_total + trx_num;
3268 if (i < nr_bts) {
3269 num_trx_connected := num_trx_connected + trx_num;
3270 }
3271 }
3272
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003273 /* Also verify stat exposed on CTRL interface */
3274 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
3275 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 +06003276 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(num_trx_connected));
3277 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 +02003278
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003279 /* Verify rf_states exposed on CTRL interface */
3280 var charstring expect_net_rf_states := "";
3281 for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003282 var charstring expect_bts_rf_states := "";
3283
3284 for (var integer j := 0; j < c_BtsParams[i].trx_num; j := j + 1) {
3285 expect_bts_rf_states := expect_bts_rf_states &
3286 int2str(i) & "," & int2str(j) & ",";
3287 if (i < NUM_BTS) {
3288 /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
3289 expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
3290 } else {
3291 /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
3292 expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
3293 }
3294 /* The RF policy is still global in osmo-bsc, i.e. always "on" */
3295 expect_bts_rf_states := expect_bts_rf_states & "on,";
3296 if (i < nr_bts) {
3297 /* For BTS where RSL is connected, the RSL state will be "up" */
3298 expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
3299 } else {
3300 expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
3301 }
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003302 }
3303
3304 f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
3305 expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
3306 }
3307 f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
3308
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003309 f_shutdown_helper();
3310}
3311
3312/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
3313private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
3314 f_tc_stat_num_bts_connected_msc_connhdlr(1);
3315}
3316testcase TC_stat_num_bts_connected_1() runs on test_CT {
3317 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
3318}
3319
3320/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
3321private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
3322 f_tc_stat_num_bts_connected_msc_connhdlr(2);
3323}
3324testcase TC_stat_num_bts_connected_2() runs on test_CT {
3325 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
3326}
3327
3328/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
3329private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
3330 f_tc_stat_num_bts_connected_msc_connhdlr(3);
3331}
3332testcase TC_stat_num_bts_connected_3() runs on test_CT {
3333 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
3334}
3335
Harald Welte4003d112017-12-09 22:35:39 +01003336testcase TC_ctrl() runs on test_CT {
3337 var charstring ctrl_resp;
3338
Harald Welte89d42e82017-12-17 16:42:41 +01003339 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003340
3341 /* all below values must match the osmo-bsc.cfg config file used */
3342
Harald Welte6a129692018-03-17 17:30:14 +01003343 f_ctrl_get_exp(IPA_CTRL, "mcc", "001");
3344 f_ctrl_get_exp(IPA_CTRL, "mnc", "01");
Oliver Smith75aa0202019-08-19 14:17:50 +02003345 f_ctrl_get_exp(IPA_CTRL, "number-of-bts", "4");
Harald Welte4003d112017-12-09 22:35:39 +01003346
3347 var integer bts_nr := 0;
3348 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "location-area-code", "1");
3349 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "cell-identity", "0");
3350 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "oml-connection-state", "connected");
3351 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "gprs-mode", "gprs");
3352 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "rf_state", "operational,unlocked,on");
3353 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "arfcn", "871");
3354 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "max-power-reduction", "20");
3355
3356 var integer uptime := str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime"));
3357 f_sleep(2.0);
3358 if (str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime")) < uptime+1) {
3359 setverdict(fail, "oml-uptime not incrementing as expected");
3360 }
3361 /* TODO: Disconnect RSL, imply that OML is disconnected and check for uptime zero? */
3362
3363 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
3364
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003365 f_shutdown_helper();
Harald Welte96c94412017-12-09 03:12:45 +01003366}
3367
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003368/* Verify that Upon receival of SET "location", BSC forwards a TRAP
3369 "location-state" over the SCCPlite IPA conn */
3370testcase TC_ctrl_location() runs on test_CT {
3371 var MSC_ConnHdlr vc_conn;
3372 var integer bts_nr := 0;
3373
3374 f_init(1, true);
3375 f_sleep(1.0);
3376
3377 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234567,fix3d,0.340000,0.560000,0.780000");
3378 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3379 "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
3380
3381 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "1");
3382 f_sleep(2.0);
3383
3384 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234888,fix3d,0.350000,0.570000,0.790000");
3385 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3386 "1234888,fix3d,0.350000,0.570000,0.790000,operational,locked,off,001,01");
3387
3388 /* should match the one from config */
3389 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
3390
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003391 f_shutdown_helper();
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003392}
3393
Harald Welte6f521d82017-12-11 19:52:02 +01003394
3395/***********************************************************************
3396 * Paging Testing
3397 ***********************************************************************/
3398
3399type record Cell_Identity {
3400 GsmMcc mcc,
3401 GsmMnc mnc,
3402 GsmLac lac,
3403 GsmCellId ci
3404};
Harald Welte24135bd2018-03-17 19:27:53 +01003405private const Cell_Identity cid := { '001'H, '01'H, 1, 0 };
Stefan Sperling049a86e2018-03-20 15:51:00 +01003406private const Cell_Identity unknown_cid := { '678'H, 'f90'H, 1, 0 };
Harald Welte6f521d82017-12-11 19:52:02 +01003407
Harald Welte5d1a2202017-12-13 19:51:29 +01003408type set of integer BtsIdList;
3409
3410private function f_bts_in_list(integer bts_id, BtsIdList bts_ids) return boolean {
3411 for (var integer j := 0; j < sizeof(bts_ids); j := j + 1) {
3412 if (bts_id == bts_ids[j]) {
3413 return true;
3414 }
3415 }
3416 return false;
3417}
Harald Welte6f521d82017-12-11 19:52:02 +01003418
3419/* core paging test helper function; used by most paging test cases */
3420private function f_pageing_helper(hexstring imsi,
3421 template BSSMAP_FIELD_CellIdentificationList cid_list,
Harald Welte5d1a2202017-12-13 19:51:29 +01003422 BtsIdList bts_ids := { 0 },
Harald Welte6f521d82017-12-11 19:52:02 +01003423 template RSL_ChanNeeded rsl_chneed := omit,
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003424 template (omit) OCT4 tmsi := omit) runs on test_CT
Harald Welte6f521d82017-12-11 19:52:02 +01003425{
3426 var template BSSMAP_IE_ChannelNeeded bssmap_chneed;
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003427 var template MobileIdentityV mi;
Harald Welte6f521d82017-12-11 19:52:02 +01003428 var RSL_Message rx_rsl;
3429 var integer paging_group := hex2int(imsi[lengthof(imsi)-1]);
Harald Welte5d1a2202017-12-13 19:51:29 +01003430 var integer i;
Harald Welte6f521d82017-12-11 19:52:02 +01003431
3432 f_init();
Harald Welte6f521d82017-12-11 19:52:02 +01003433
3434 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Harald Weltec3068592018-03-17 19:55:31 +01003435 for (i := 0; i < NUM_BTS; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003436 IPA_RSL[i][0].clear;
Harald Welte5d1a2202017-12-13 19:51:29 +01003437 }
Harald Welte6f521d82017-12-11 19:52:02 +01003438
3439 if (isvalue(rsl_chneed)) {
3440 /* The values of 08.08 3.2.2.36 and 08.58 9.3.40 are luckily identical */
3441 bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
3442 } else {
3443 bssmap_chneed := omit;
3444 }
3445
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003446 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
3447 ts_BSSMAP_Paging(imsi, cid_list, tmsi, bssmap_chneed)));
Harald Welte6f521d82017-12-11 19:52:02 +01003448
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003449 if (not istemplatekind(tmsi, "omit")) {
3450 mi := t_MI_TMSI(tmsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003451 } else {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003452 mi := tr_MI_IMSI(imsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003453 }
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003454
Harald Welte5d1a2202017-12-13 19:51:29 +01003455 for (i := 0; i < sizeof(bts_ids); i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003456 rx_rsl := f_exp_ipa_rx(tr_RSL_PAGING_CMD(mi), idx := {bts_ids[i], 0});
Harald Welte5d1a2202017-12-13 19:51:29 +01003457 /* check channel type, paging group */
3458 if (rx_rsl.ies[1].body.paging_group != paging_group) {
3459 setverdict(fail, "Paging for wrong paging group");
3460 }
3461 if (ispresent(rsl_chneed) and
3462 rx_rsl.ies[3].body.chan_needed.chan_needed != valueof(rsl_chneed)) {
3463 setverdict(fail, "RSL Channel Needed != BSSMAP Channel Needed");
3464 }
Harald Welte6f521d82017-12-11 19:52:02 +01003465 }
Harald Welte2fccd982018-01-31 15:48:19 +01003466 f_sleep(2.0);
Harald Welte5d1a2202017-12-13 19:51:29 +01003467 /* do a quick check on all not-included BTSs if they received paging */
3468 for (i := 0; i < NUM_BTS; i := i + 1) {
3469 timer T := 0.1;
3470 if (f_bts_in_list(i, bts_ids)) {
3471 continue;
3472 }
3473 T.start;
3474 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003475 [] IPA_RSL[i][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003476 setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
3477 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003478 [] IPA_RSL[i][0].receive { repeat; }
Harald Welte5d1a2202017-12-13 19:51:29 +01003479 [] T.timeout { }
3480 }
Harald Welte6f521d82017-12-11 19:52:02 +01003481 }
3482
3483 setverdict(pass);
3484}
3485
Harald Welte5d1a2202017-12-13 19:51:29 +01003486const BtsIdList c_BtsId_all := { 0, 1, 2 };
Harald Welte751d3eb2018-01-31 15:51:06 +01003487const BtsIdList c_BtsId_none := { };
Harald Welte5d1a2202017-12-13 19:51:29 +01003488const BtsIdList c_BtsId_LAC1 := { 0, 1 };
3489const BtsIdList c_BtsId_LAC2 := { 2 };
3490
Harald Welte6f521d82017-12-11 19:52:02 +01003491/* PAGING by IMSI + TMSI */
3492testcase TC_paging_imsi_nochan() runs on test_CT {
3493 var BSSMAP_FIELD_CellIdentificationList cid_list;
3494 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Philipp Maier8c04b0a2018-02-23 13:48:48 +01003495 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, omit);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003496 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003497}
3498
3499/* PAGING by IMSI + TMSI */
3500testcase TC_paging_tmsi_nochan() runs on test_CT {
3501 var BSSMAP_FIELD_CellIdentificationList cid_list;
3502 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003503 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, 'A1B2C301'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003504 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003505}
3506
3507/* Paging with different "channel needed' values */
3508testcase TC_paging_tmsi_any() runs on test_CT {
3509 var BSSMAP_FIELD_CellIdentificationList cid_list;
3510 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003511 f_pageing_helper('001010100000002'H, cid_list, c_BtsId_all, RSL_CHANNEED_ANY, 'A1B2C302'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003512 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003513}
3514testcase TC_paging_tmsi_sdcch() runs on test_CT {
3515 var BSSMAP_FIELD_CellIdentificationList cid_list;
3516 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003517 f_pageing_helper('001010100000003'H, cid_list, c_BtsId_all, RSL_CHANNEED_SDCCH, 'A1B2C303'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003518 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003519}
3520testcase TC_paging_tmsi_tch_f() runs on test_CT {
3521 var BSSMAP_FIELD_CellIdentificationList cid_list;
3522 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003523 f_pageing_helper('001010000000004'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_F, 'A1B2C304'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003524 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003525}
3526testcase TC_paging_tmsi_tch_hf() runs on test_CT {
3527 var BSSMAP_FIELD_CellIdentificationList cid_list;
3528 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003529 f_pageing_helper('001010000000005'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_ForH, 'A1B2C305'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003530 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003531}
3532
3533/* Paging by CGI */
3534testcase TC_paging_imsi_nochan_cgi() runs on test_CT {
3535 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3536 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(cid.mcc, cid.mnc, cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003537 f_pageing_helper('001010000000006'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003538 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003539}
3540
3541/* Paging by LAC+CI */
3542testcase TC_paging_imsi_nochan_lac_ci() runs on test_CT {
3543 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3544 cid_list := { cIl_LAC_CI := { ts_BSSMAP_CI_LAC_CI(cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003545 f_pageing_helper('001010000000007'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003546 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003547}
3548
3549/* Paging by CI */
3550testcase TC_paging_imsi_nochan_ci() runs on test_CT {
3551 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3552 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003553 f_pageing_helper('001010000000008'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003554 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003555}
3556
3557/* Paging by LAI */
3558testcase TC_paging_imsi_nochan_lai() runs on test_CT {
3559 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3560 cid_list := { cIl_LAI := { ts_BSSMAP_CI_LAI(cid.mcc, cid.mnc, cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003561 f_pageing_helper('001010000000009'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003562 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003563}
3564
3565/* Paging by LAC */
3566testcase TC_paging_imsi_nochan_lac() runs on test_CT {
3567 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3568 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003569 f_pageing_helper('001010000000010'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003570 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003571}
3572
3573/* Paging by "all in BSS" */
3574testcase TC_paging_imsi_nochan_all() runs on test_CT {
3575 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3576 cid_list := { cIl_allInBSS := ''O };
Harald Welte5d1a2202017-12-13 19:51:29 +01003577 f_pageing_helper('001010000000011'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003578 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003579}
3580
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003581/* Paging by PLMN+LAC+RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003582testcase TC_paging_imsi_nochan_plmn_lac_rnc() runs on test_CT {
3583 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3584 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 +01003585 f_pageing_helper('001010000000012'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003586 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003587}
Harald Welte6f521d82017-12-11 19:52:02 +01003588
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003589/* Paging by RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003590testcase TC_paging_imsi_nochan_rnc() runs on test_CT {
3591 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3592 cid_list := { cIl_RNC := { int2oct(13, 2) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003593 f_pageing_helper('001010000000013'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003594 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003595}
3596
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003597/* Paging by LAC+RNC; We do not implement; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003598testcase TC_paging_imsi_nochan_lac_rnc() runs on test_CT {
3599 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3600 cid_list := { cIl_LAC_RNC := { ts_BSSMAP_CI_LAC_RNC(cid.lac, 14) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003601 f_pageing_helper('001010000000014'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003602 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003603}
3604
Harald Welte6f521d82017-12-11 19:52:02 +01003605/* Paging on multiple cells (multiple entries in list): Verify all of them page */
Harald Welte751d3eb2018-01-31 15:51:06 +01003606testcase TC_paging_imsi_nochan_lacs() runs on test_CT {
3607 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3608 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(1), ts_BSSMAP_CI_LAC(2) } };
3609 f_pageing_helper('001010000000015'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003610 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003611}
3612
3613/* Paging on empty list: Verify none of them page */
3614testcase TC_paging_imsi_nochan_lacs_empty() runs on test_CT {
3615 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3616 cid_list := { cIl_LAC := { } };
3617 f_pageing_helper('001010000000016'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003618 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003619}
3620
Stefan Sperling049a86e2018-03-20 15:51:00 +01003621/* Paging by CGI with unknown MCC/MNC: Verify nothing is paged. */
3622testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
3623 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3624 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(unknown_cid.mcc, unknown_cid.mnc, unknown_cid.lac, unknown_cid.ci) } };
3625 f_pageing_helper('001010000000006'H, cid_list, c_BtsId_none);
3626 f_shutdown_helper();
3627}
3628
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +01003629/* Send paging response containing invalid (wrongly formatted) MobileIdentity IE. */
3630testcase TC_paging_imsi_nochan_ci_resp_invalid_mi() runs on test_CT {
3631 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3632 var BSSAP_N_CONNECT_ind rx_c_ind;
3633 var DchanTuple dt;
3634 var octetstring rr_pag_resp := '06270003535992617965720000'O;
3635 /* { 06 27 } is { GSM48_PDISC_RR, GSM48_MT_RR_PAG_RESP }
3636 * see 3GPP TS 44.018, table 9.1.25.1
3637 * { 00 } or { 01 } is CKSN + Spare Half Octet, not important
3638 * { 03 53 59 92 } is Mobile Station Classmark
3639 * { 61 79 65 72 00 00 } is the invalid Mobile Identity IE (3GPP TS 24.008, 10.5.1.4),
3640 * Length is 0x61 (97 in decimal).
3641 */
3642
3643 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
3644 f_pageing_helper('001010000000008'H, cid_list, { 0 });
3645
3646 /* Send CHAN RQD and wait for allocation; acknowledge it */
3647 dt.rsl_chan_nr := f_chreq_act_ack();
3648 dt.idx := {0, 0};
3649
3650 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
3651 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), rr_pag_resp));
3652
3653 /* Expevct a CR with a matching Paging response on the A-Interface */
3654 timer T := 5.0;
3655 T.start;
3656 alt {
3657 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
3658 setverdict(pass);
3659 dt.sccp_conn_id := rx_c_ind.connectionId;
3660 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
3661 }
3662 [] BSSAP.receive {
3663 setverdict(fail, "Received unexpected message on A-Interface!");
3664 }
3665 [] T.timeout {
3666 setverdict(fail, "Received nothing on A-Interface!");
3667 }
3668 }
3669
3670 f_perform_clear_test_ct(dt);
3671 f_shutdown_helper();
3672}
3673
Harald Welte6f521d82017-12-11 19:52:02 +01003674/* Verify paging retransmission interval + count */
3675/* Verify paging stops after channel establishment */
Harald Welte6f521d82017-12-11 19:52:02 +01003676/* Test behavior under paging overload */
Harald Welteae026692017-12-09 01:03:01 +01003677
Harald Weltee65d40e2017-12-13 00:09:06 +01003678/* Verify PCH load */
3679testcase TC_paging_imsi_load() runs on test_CT {
3680 var BSSMAP_FIELD_CellIdentificationList cid_list;
3681 timer T := 4.0;
Harald Welte2caa1062018-03-17 18:19:05 +01003682 timer T_retrans := 1.0;
Harald Weltee65d40e2017-12-13 00:09:06 +01003683 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003684 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Weltee65d40e2017-12-13 00:09:06 +01003685
3686 /* tell BSC there is no paging space anymore */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003687 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte3b57ab52018-03-17 18:01:10 +01003688 f_sleep(0.2);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003689 IPA_RSL[0][0].clear;
Harald Weltee65d40e2017-12-13 00:09:06 +01003690
3691 /* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
3692 * there would be 8 retransmissions during 4 seconds */
3693 T.start;
Harald Welte2caa1062018-03-17 18:19:05 +01003694 T_retrans.start;
Harald Weltee65d40e2017-12-13 00:09:06 +01003695 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003696 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Weltee65d40e2017-12-13 00:09:06 +01003697 setverdict(fail, "Received PAGING after LOAD_IND(0)");
Daniel Willmannafce8662018-07-06 23:11:32 +02003698 mtc.stop;
Harald Weltee65d40e2017-12-13 00:09:06 +01003699 }
Harald Welte2caa1062018-03-17 18:19:05 +01003700 [] T_retrans.timeout {
3701 /* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003702 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte2caa1062018-03-17 18:19:05 +01003703 T_retrans.start;
3704 repeat;
3705 }
Harald Weltee65d40e2017-12-13 00:09:06 +01003706 [] T.timeout {
3707 setverdict(pass);
3708 }
3709 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003710
3711 f_shutdown_helper();
Harald Weltee65d40e2017-12-13 00:09:06 +01003712}
3713
Harald Welte235ebf12017-12-15 14:18:16 +01003714/* Verify Paging Counter */
Harald Welte1ff69992017-12-14 12:31:17 +01003715testcase TC_paging_counter() runs on test_CT {
3716 var BSSMAP_FIELD_CellIdentificationList cid_list;
3717 timer T := 4.0;
3718 var integer i;
3719 var integer paging_attempted_bsc;
3720 var integer paging_attempted_bts[NUM_BTS];
Oliver Smith8b343d32021-11-26 13:01:42 +01003721 var integer paging_expired_bsc;
Harald Welte1ff69992017-12-14 12:31:17 +01003722 var integer paging_expired_bts[NUM_BTS];
3723 cid_list := valueof(ts_BSSMAP_CIL_noCell);
3724
3725 f_init();
3726
3727 /* read counters before paging */
3728 paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003729 paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
Harald Welte1ff69992017-12-14 12:31:17 +01003730 for (i := 0; i < NUM_BTS; i := i+1) {
3731 paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
3732 paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
3733 }
3734
3735 f_pageing_helper('001230000000001'H, cid_list, c_BtsId_all);
3736
3737 /* expect the attempted pages on BSC and each BTSs to have incremented by one */
3738 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", paging_attempted_bsc+1);
3739 for (i := 0; i < NUM_BTS; i := i+1) {
3740 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted",
3741 paging_attempted_bts[i]+1);
3742 }
3743
3744 /* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
3745 f_sleep(12.0);
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003746 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
Harald Welte1ff69992017-12-14 12:31:17 +01003747 for (i := 0; i < NUM_BTS; i := i+1) {
3748 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
3749 paging_expired_bts[i]+1);
3750 }
Harald Welte1ff69992017-12-14 12:31:17 +01003751
Philipp Maier282ca4b2018-02-27 17:17:00 +01003752 f_shutdown_helper();
Harald Welte1ff69992017-12-14 12:31:17 +01003753}
3754
3755
Harald Welte10985002017-12-12 09:29:15 +01003756/* Verify paging stops after A-RESET */
3757testcase TC_paging_imsi_a_reset() runs on test_CT {
3758 var BSSMAP_FIELD_CellIdentificationList cid_list;
3759 timer T := 3.0;
3760 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003761 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Welte10985002017-12-12 09:29:15 +01003762
3763 /* Perform a BSSMAP Reset and wait for ACK */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003764 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 +01003765 alt {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003766 [] 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 +01003767 [] BSSAP.receive { repeat; }
3768 }
3769
Daniel Willmanncbef3982018-07-30 09:22:40 +02003770 /* Wait to avoid a possible race condition if a paging message is
3771 * received right before the reset ACK. */
3772 f_sleep(0.2);
3773
Harald Welte10985002017-12-12 09:29:15 +01003774 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Philipp Maier1e6b4422018-02-23 14:02:13 +01003775 for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003776 IPA_RSL[i][0].clear;
Philipp Maier1e6b4422018-02-23 14:02:13 +01003777 }
Harald Welte10985002017-12-12 09:29:15 +01003778
3779 /* Wait for 3 seconds if any more PAGING CMD are received on RSL */
3780 T.start;
3781 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003782 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte10985002017-12-12 09:29:15 +01003783 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003784 mtc.stop;
Harald Welte10985002017-12-12 09:29:15 +01003785 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003786 [] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003787 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003788 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003789 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003790 [] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003791 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003792 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003793 }
Harald Welte10985002017-12-12 09:29:15 +01003794 [] T.timeout {
3795 setverdict(pass);
3796 }
3797 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003798
3799 f_shutdown_helper();
Harald Welte10985002017-12-12 09:29:15 +01003800}
Harald Welteae026692017-12-09 01:03:01 +01003801
Philipp Maierf45824a2019-08-14 14:44:10 +02003802/* Verify how we handle unsolicited Paging Response. In case of an unsolicit
3803 * paging response we can not know which MSC is in charge, so we will blindly
3804 * pick the first configured MSC. This behavior is required in order to make
3805 * MT-CSFB calls working because in those cases the BSC can not know that the
3806 * MSC has already paged the subscriver via SGs. So any MT-CSFB call will look
3807 * like an unsolicited Paging Response to the MSC.
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003808 */
3809testcase TC_paging_resp_unsol() runs on test_CT {
3810
3811 f_init(1);
Philipp Maierf45824a2019-08-14 14:44:10 +02003812 timer T := 5.0;
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003813
3814 var BSSAP_N_CONNECT_ind rx_c_ind;
3815 var DchanTuple dt;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02003816 var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010008880018'H)));
Philipp Maierf45824a2019-08-14 14:44:10 +02003817 var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003818
3819 /* Send CHAN RQD and wait for allocation; acknowledge it */
3820 dt.rsl_chan_nr := f_chreq_act_ack();
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003821 dt.idx := {0, 0};
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003822
3823 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
Pau Espin Pedrole8a51012023-01-03 11:59:59 +01003824 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 +01003825
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003826
Philipp Maierf45824a2019-08-14 14:44:10 +02003827 /* Expevct a CR with a matching Paging response on the A-Interface */
3828 T.start;
3829 alt {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003830 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
Philipp Maierf45824a2019-08-14 14:44:10 +02003831 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003832 dt.sccp_conn_id := rx_c_ind.connectionId;
3833 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
Philipp Maierf45824a2019-08-14 14:44:10 +02003834 }
3835 [] BSSAP.receive {
3836 setverdict(fail, "Received unexpected message on A-Interface!");
3837 }
3838 [] T.timeout {
3839 setverdict(fail, "Received nothing on A-Interface!");
3840 }
3841 }
3842
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003843 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003844 f_shutdown_helper();
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003845}
3846
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003847/* Verify BSC can schedule N paging requests under one minute if BTS buffer is good enough */
3848function f_TC_paging_Nreq(integer num_subscribers, boolean send_pag_load_ind) runs on test_CT {
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003849 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003850 var Hexstrings imsis := {};
3851 var Booleans rx_paging_done := {};
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003852 var integer rx_paging_num := 0;
3853 var integer i;
3854 timer T_rx := 60.0;
3855 timer T_load_ind := 1.0;
3856
3857 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003858 imsis := imsis & {f_gen_imsi(i)};
3859 rx_paging_done := rx_paging_done & { false };
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003860 }
3861
3862 f_init(1, guard_timeout := 100.0);
3863
3864 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003865 IPA_RSL[0][0].clear;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003866 if (send_pag_load_ind) {
3867 /* Tell there's plenty of space at the BTS (UINT16_MAX): */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003868 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(65535));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003869 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003870
3871 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003872 /* Page on LAC-CI of BTS0: */
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003873 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 +02003874 ts_BSSMAP_Paging(imsis[i], valueof(ts_BSSMAP_CIL_LAC_CI({ts_BSSMAP_CI_LAC_CI(1, 0)})),
3875 omit, omit)));
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003876 }
3877
3878 T_rx.start;
3879 T_load_ind.start;
3880 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003881 [] 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 +02003882 var hexstring imsi := rx_rsl_ud.rsl.ies[2].body.ms_identity.mobileIdentityV.oddEvenInd_identity.imsi.digits;
3883 var hexstring imsi_suffix := substr(imsi, lengthof(imsi)-6, 6);
3884 var charstring imsi_str := hex2str(imsi_suffix);
3885 var integer imsi_idx := str2int(imsi_str);
3886 if (rx_paging_done[imsi_idx] == false) {
3887 rx_paging_done[imsi_idx] := true;
3888 rx_paging_num := rx_paging_num + 1;
Pau Espin Pedrolef7ef632022-04-25 13:34:57 +02003889 } else {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003890 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 +02003891 mtc.stop;
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003892 }
3893 if (rx_paging_num < num_subscribers) {
3894 repeat;
3895 }
3896 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003897 [] IPA_RSL[0][0].receive { repeat; }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003898 [] T_load_ind.timeout {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003899 log("[CCH Load Ind timer] received paging requests so far: ", rx_paging_num);
3900 if (send_pag_load_ind) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003901 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(40));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003902 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003903 T_load_ind.start;
3904 repeat;
3905 }
3906 [] T_rx.timeout {
3907 setverdict(fail, "Timeout expecting paging requests, so far ", rx_paging_num);
3908 mtc.stop;
3909 }
3910 }
3911
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003912 /* Drop OML connection to have all paging requests flushed: */
3913 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
3914
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003915 f_shutdown_helper();
3916}
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003917/* Verify BSC can schedule 500 paging requests under one minute if BTS buffer is good enough */
3918testcase TC_paging_500req() runs on test_CT {
3919 f_TC_paging_Nreq(500, true);
3920}
3921/* Same as TC_paging_500req, but without sending CCCH Load Indication, which
3922 * means BTS is always under CCH Load Threshold, aka capable of sending tons of requests.
3923 * Since No CCCH Load Ind, BSC uses a conservative estimation of BTS load, which
3924 * for current config yields ~8req/sec, so 480req/min maximum. */
3925testcase TC_paging_450req_no_paging_load_ind() runs on test_CT {
3926 f_TC_paging_Nreq(450, false);
3927}
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003928
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003929/* Test RSL link drop causes counter increment */
3930testcase TC_rsl_drop_counter() runs on test_CT {
3931 var integer rsl_fail;
3932
Harald Welte89d42e82017-12-17 16:42:41 +01003933 f_init(1);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003934
3935 rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
3936
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003937 f_ipa_rsl_stop(bts[0][0].rsl);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003938
3939 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
3940
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003941 f_shutdown_helper();
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003942}
3943
3944/* TODO: Test OML link drop causes counter increment */
3945
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003946/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
3947function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003948 var IPA_Client client;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003949 timer T := 10.0;
3950
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003951 client.id := "IPA-BTS0-TRX0-RSL";
3952 client.vc_IPA := IPA_Emulation_CT.create(client.id & "-IPA") alive;
3953 client.ccm_pars := c_IPA_default_ccm_pars;
3954 client.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
3955 client.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003956
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01003957 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003958
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003959 f_init_mgcp(0, "VirtMGW");
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003960
3961 /* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003962 map(client.vc_IPA:IPA_PORT, system:IPA);
3963 connect(client.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0][0]);
3964 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 +01003965
3966 /* wait for IPA OML link to connect and then disconnect */
3967 T.start;
3968 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003969 [] IPA_RSL[0][0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003970 T.stop;
3971 return true;
3972 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003973 [] IPA_RSL[0][0].receive { repeat }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003974 [] T.timeout {
Daniel Willmannafce8662018-07-06 23:11:32 +02003975 return false;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003976 }
3977 }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003978 return false;
3979}
3980
3981/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3982testcase TC_rsl_unknown_unit_id() runs on test_CT {
3983 if (f_ipa_unknown_unit_id(mp_bsc_rsl_port)) {
3984 setverdict(pass);
3985 } else {
3986 setverdict(fail, "Timeout RSL waiting for connection to close");
3987 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003988 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003989}
3990
3991
3992/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3993testcase TC_oml_unknown_unit_id() runs on test_CT {
3994 if (f_ipa_unknown_unit_id(mp_bsc_oml_port)) {
3995 setverdict(pass);
3996 } else {
3997 setverdict(fail, "Timeout OML waiting for connection to close");
3998 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003999 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01004000}
4001
4002
Harald Weltec1a2fff2017-12-17 11:06:19 +01004003/***********************************************************************
Harald Welte6811d102019-04-14 22:23:14 +02004004 * "New world" test cases using RSL_Emulation + RAN_Emulation
Harald Weltec1a2fff2017-12-17 11:06:19 +01004005 ***********************************************************************/
4006
Harald Welte6811d102019-04-14 22:23:14 +02004007import from RAN_Emulation all;
Harald Welte47cd0e32020-08-21 12:39:11 +02004008import from BSSAP_LE_Emulation all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01004009import from RSL_Emulation all;
4010import from MSC_ConnectionHandler all;
4011
4012type function void_fn(charstring id) runs on MSC_ConnHdlr;
4013
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06004014/* helper function to create and connect a MSC_ConnHdlr component
4015 * TODO: allow connecting to TRX1..N, not only TRX0 */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004016private 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 +02004017 connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06004018 connect(vc_conn:RSL, bts[0][0].rsl.vc_RSL:CLIENT_PT);
4019 connect(vc_conn:RSL_PROC, bts[0][0].rsl.vc_RSL:RSL_PROC);
4020 if (isvalue(bts[1][0])) {
4021 connect(vc_conn:RSL1, bts[1][0].rsl.vc_RSL:CLIENT_PT);
4022 connect(vc_conn:RSL1_PROC, bts[1][0].rsl.vc_RSL:RSL_PROC);
Philipp Maier956a92f2018-02-16 10:58:07 +01004023 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06004024 if (isvalue(bts[2][0])) {
4025 connect(vc_conn:RSL2, bts[2][0].rsl.vc_RSL:CLIENT_PT);
4026 connect(vc_conn:RSL2_PROC, bts[2][0].rsl.vc_RSL:RSL_PROC);
Neels Hofmeyr91401012019-07-11 00:42:35 +02004027 }
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004028 connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02004029 if (mp_enable_lcs_tests) {
4030 connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
4031 connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
4032 }
Daniel Willmannebdecc02020-08-12 15:30:17 +02004033 connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004034 connect(vc_conn:MGCP_PROC, vc_MGCP[mgwpool_idx]:MGCP_PROC);
4035 connect(vc_conn:MGCP, vc_MGCP[mgwpool_idx]:MGCP_CLIENT);
4036 connect(vc_conn:MGCP_MULTI, vc_MGCP[mgwpool_idx]:MGCP_CLIENT_MULTI);
Harald Welte336820c2018-05-31 20:34:52 +02004037}
4038
Neels Hofmeyrda436782021-07-20 22:09:06 +02004039function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
Harald Welte336820c2018-05-31 20:34:52 +02004040runs on test_CT return MSC_ConnHdlr {
4041 var charstring id := testcasename();
4042 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004043 var integer bssap_idx := 0;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004044 var integer mgwpool_idx := 0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004045 if (isvalue(pars)) {
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004046 var TestHdlrParams pars_val := valueof(pars);
4047 bssap_idx := pars_val.mscpool.bssap_idx;
4048 mgwpool_idx := pars_val.mgwpool_idx;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004049 }
Harald Welte336820c2018-05-31 20:34:52 +02004050 vc_conn := MSC_ConnHdlr.create(id);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004051 f_connect_handler(vc_conn, bssap_idx, mgwpool_idx);
Neels Hofmeyrda436782021-07-20 22:09:06 +02004052 return vc_conn;
4053}
4054
4055function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
4056runs on test_CT return MSC_ConnHdlr {
4057 var charstring id := testcasename();
Harald Weltea0630032018-03-20 21:09:55 +01004058 vc_conn.start(f_handler_init(fn, id, pars));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004059 return vc_conn;
4060}
4061
Neels Hofmeyrda436782021-07-20 22:09:06 +02004062function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
4063runs on test_CT return MSC_ConnHdlr {
4064 return f_start_handler_run(f_start_handler_create(pars), fn, pars);
4065}
4066
Harald Weltea0630032018-03-20 21:09:55 +01004067/* first function inside ConnHdlr component; sets g_pars + starts function */
4068private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
4069runs on MSC_ConnHdlr {
4070 if (isvalue(pars)) {
4071 g_pars := valueof(pars);
4072 }
4073 fn.apply(id);
4074}
4075
Oliver Smith26a3db72021-07-09 13:51:29 +02004076private function f_vty_encryption_a5(charstring options) runs on test_CT {
4077 f_vty_transceive(BSCVTY, "configure terminal");
4078 f_vty_transceive(BSCVTY, "network");
4079 f_vty_transceive(BSCVTY, "encryption a5 " & options);
4080 f_vty_transceive(BSCVTY, "exit");
4081 f_vty_transceive(BSCVTY, "exit");
4082}
4083
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004084const charstring VTY_A5_DEFAULT := "0 1 3";
4085
Oliver Smith26a3db72021-07-09 13:51:29 +02004086private function f_vty_encryption_a5_reset() runs on test_CT {
4087 /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004088 f_vty_encryption_a5(VTY_A5_DEFAULT);
Oliver Smith26a3db72021-07-09 13:51:29 +02004089}
4090
Harald Welte3c86ea02018-05-10 22:28:05 +02004091/* Establish signalling channel (non-assignment case) followed by cipher mode */
4092private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004093 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4094 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte3c86ea02018-05-10 22:28:05 +02004095 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Philipp Maier23000732018-05-18 11:25:37 +02004096 ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode := omit;
4097 ass_cmd.pdu.bssmap.assignmentRequest.aoIPTransportLayer := omit;
4098 exp_compl.pdu.bssmap.assignmentComplete.circuitIdentityCode := omit;
4099 exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
Harald Welte3c86ea02018-05-10 22:28:05 +02004100
Philipp Maier23000732018-05-18 11:25:37 +02004101 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004102 f_perform_clear();
Harald Welte3c86ea02018-05-10 22:28:05 +02004103}
4104testcase TC_ciph_mode_a5_0() runs on test_CT {
4105 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004106 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004107 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
4108
4109 f_init(1, true);
4110 f_sleep(1.0);
4111 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4112 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004113 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004114}
4115testcase TC_ciph_mode_a5_1() runs on test_CT {
4116 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004117 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004118 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
4119
4120 f_init(1, true);
4121 f_sleep(1.0);
4122 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4123 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004124 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004125}
Oliver Smith50b98122021-07-09 15:00:28 +02004126/* OS#4975: verify that A5/2 is preferred over A5/0 */
4127testcase TC_ciph_mode_a5_2_0() runs on test_CT {
4128 var MSC_ConnHdlr vc_conn;
4129 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4130
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004131 pars.encr := f_encr_params('05'O, '04'O); /* A5/0 and A5/2 (0x01|0x04)*/
Oliver Smith50b98122021-07-09 15:00:28 +02004132
4133 f_init(1, true);
4134 f_vty_encryption_a5("0 1 2 3");
4135 f_sleep(1.0);
4136 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4137 vc_conn.done;
4138 f_vty_encryption_a5_reset();
4139 f_shutdown_helper();
4140}
Oliver Smith1dff88d2021-07-09 08:45:51 +02004141/* OS#4975: verify that A5/1 is preferred over A5/2 */
4142testcase TC_ciph_mode_a5_2_1() runs on test_CT {
4143 var MSC_ConnHdlr vc_conn;
4144 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4145
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004146 pars.encr := f_encr_params('06'O, '02'O); /* A5/1 and A5/2 (0x02|0x04)*/
Oliver Smith1dff88d2021-07-09 08:45:51 +02004147
4148 f_init(1, true);
4149 f_vty_encryption_a5("1 2");
4150 f_sleep(1.0);
4151 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4152 vc_conn.done;
4153 f_vty_encryption_a5_reset();
4154 f_shutdown_helper();
4155}
Harald Welte3c86ea02018-05-10 22:28:05 +02004156testcase TC_ciph_mode_a5_3() runs on test_CT {
4157 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004158 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004159 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
4160
4161 f_init(1, true);
4162 f_sleep(1.0);
4163 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4164 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004165 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004166}
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004167/* Establish a Signalling channel with A5/4 encryption. */
4168testcase TC_ciph_mode_a5_4() runs on test_CT {
4169 var MSC_ConnHdlr vc_conn;
4170 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4171 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Harald Welte3c86ea02018-05-10 22:28:05 +02004172
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004173 f_init(1, true);
Oliver Smith26a3db72021-07-09 13:51:29 +02004174 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004175 f_sleep(1.0);
4176 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4177 vc_conn.done;
Oliver Smith26a3db72021-07-09 13:51:29 +02004178 f_vty_encryption_a5_reset();
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004179 f_shutdown_helper();
4180}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004181/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
4182private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
4183 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4184 var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
4185 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4186 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4187
4188 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004189 f_perform_clear();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004190}
4191testcase TC_assignment_aoip_tla_v6() runs on test_CT {
4192 var MSC_ConnHdlr vc_conn;
4193 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4194
4195 f_init(1, true);
4196 f_sleep(1.0);
4197 vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
4198 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004199 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004200}
4201
Harald Welte3c86ea02018-05-10 22:28:05 +02004202
4203/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
Harald Welte651fcdc2018-05-10 20:23:16 +02004204private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004205 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4206 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004207
Harald Welte552620d2017-12-16 23:21:36 +01004208 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4209 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte73cd2712017-12-17 00:44:52 +01004210
Harald Weltea0630032018-03-20 21:09:55 +01004211 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004212 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004213}
Harald Welte552620d2017-12-16 23:21:36 +01004214testcase TC_assignment_fr_a5_0() runs on test_CT {
4215 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004216 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004217 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
Harald Welte552620d2017-12-16 23:21:36 +01004218
Harald Welte89d42e82017-12-17 16:42:41 +01004219 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004220 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004221 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004222 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004223 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004224}
Harald Welte552620d2017-12-16 23:21:36 +01004225testcase TC_assignment_fr_a5_1() runs on test_CT {
Harald Weltec1a2fff2017-12-17 11:06:19 +01004226 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004227 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004228 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004229
Harald Welte89d42e82017-12-17 16:42:41 +01004230 f_init(1, true);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004231 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004232 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4233 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004234 f_shutdown_helper();
Harald Welte651fcdc2018-05-10 20:23:16 +02004235}
4236testcase TC_assignment_fr_a5_3() runs on test_CT {
4237 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004238 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004239 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004240
Harald Welte651fcdc2018-05-10 20:23:16 +02004241 f_init(1, true);
4242 f_sleep(1.0);
4243 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004244 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004245 f_shutdown_helper();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004246}
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004247/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
4248testcase TC_assignment_fr_a5_4() runs on test_CT {
4249 var MSC_ConnHdlr vc_conn;
4250 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4251 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
4252
4253 f_init(1, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02004254 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004255 f_sleep(1.0);
4256 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4257 vc_conn.done;
Oliver Smith7eabd312021-07-12 14:18:56 +02004258 f_vty_encryption_a5_reset();
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004259 f_shutdown_helper();
4260}
Harald Weltec1a2fff2017-12-17 11:06:19 +01004261
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +02004262/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
4263testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
4264 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4265 var MSC_ConnHdlr vc_conn;
4266
4267 f_init(1, true);
4268 f_sleep(1.0);
4269
4270 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
4271 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
4272 vc_conn.done;
4273 f_shutdown_helper();
4274}
4275
Harald Welte552620d2017-12-16 23:21:36 +01004276/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
4277private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004278 g_pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004279 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02004280 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004281
4282 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02004283 /* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
4284
Harald Weltea0630032018-03-20 21:09:55 +01004285 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004286 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004287}
Harald Welte552620d2017-12-16 23:21:36 +01004288testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
4289 var MSC_ConnHdlr vc_conn;
4290
Harald Welte89d42e82017-12-17 16:42:41 +01004291 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004292 f_sleep(1.0);
4293
Harald Welte8863fa12018-05-10 20:15:27 +02004294 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
Harald Welte552620d2017-12-16 23:21:36 +01004295 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004296 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004297}
4298
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004299private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
4300 var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
4301 var PDU_BSSAP exp_ass_req := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004302
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004303 exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4304 exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4305
4306 /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
4307
4308 var BSSMAP_FIELD_CodecType codecType;
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004309
4310 codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
4311 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
4312
4313 f_create_chan_and_exp();
4314 /* we should now have a COMPL_L3 at the MSC */
4315
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004316 /* Start ciphering, expect Cipher Mode Reject */
Neels Hofmeyr6c388f22021-06-11 02:36:56 +02004317 f_cipher_mode(g_pars.encr, exp_fail := true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004318 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004319}
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004320testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
4321 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004322 var MSC_ConnHdlr vc_conn;
4323
Harald Welte89d42e82017-12-17 16:42:41 +01004324 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004325 f_sleep(1.0);
4326
Neels Hofmeyr0588cad2021-06-11 01:38:18 +02004327 pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004328 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004329 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004330 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004331}
4332
4333
Harald Welte4532e0a2017-12-23 02:05:44 +01004334private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004335 g_pars := f_gen_test_hdlr_pars();
Harald Welte4532e0a2017-12-23 02:05:44 +01004336 var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
Philipp Maier48604732018-10-09 15:00:37 +02004337 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte4532e0a2017-12-23 02:05:44 +01004338 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004339
4340 f_statsd_reset();
Harald Weltea0630032018-03-20 21:09:55 +01004341 f_establish_fully(ass_cmd, exp_compl);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004342
4343 var StatsDExpects expect := {
Daniel Willmannc5398f72020-09-21 10:41:35 +02004344 { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
4345 { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
Daniel Willmannebdecc02020-08-12 15:30:17 +02004346 { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
4347 { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
4348 };
4349 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004350 f_perform_clear();
Harald Welte4532e0a2017-12-23 02:05:44 +01004351}
4352
4353testcase TC_assignment_sign() runs on test_CT {
4354 var MSC_ConnHdlr vc_conn;
4355
4356 f_init(1, true);
4357 f_sleep(1.0);
4358
Harald Welte8863fa12018-05-10 20:15:27 +02004359 vc_conn := f_start_handler(refers(f_tc_assignment_sign));
Harald Welte4532e0a2017-12-23 02:05:44 +01004360 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004361 f_shutdown_helper();
Harald Welte4532e0a2017-12-23 02:05:44 +01004362}
4363
Harald Welte60aa5762018-03-21 19:33:13 +01004364/***********************************************************************
4365 * Codec (list) testing
4366 ***********************************************************************/
4367
4368/* check if the given rsl_mode is compatible with the a_elem */
4369private function f_match_codec(BSSMAP_FIELD_CodecElement a_elem, RSL_IE_ChannelMode rsl_mode)
4370return boolean {
4371 select (a_elem.codecType) {
4372 case (GSM_FR) {
4373 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1))) {
4374 return true;
4375 }
4376 }
4377 case (GSM_HR) {
4378 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1))) {
4379 return true;
4380 }
4381 }
4382 case (GSM_EFR) {
4383 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2))) {
4384 return true;
4385 }
4386 }
4387 case (FR_AMR) {
4388 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3))) {
4389 return true;
4390 }
4391 }
4392 case (HR_AMR) {
4393 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3))) {
4394 return true;
4395 }
4396 }
4397 case else { }
4398 }
4399 return false;
4400}
4401
4402/* check if the given rsl_mode is compatible with the a_list */
4403private function f_match_codecs(BSSMAP_IE_SpeechCodecList a_list, RSL_IE_ChannelMode rsl_mode)
4404return boolean {
4405 for (var integer i := 0; i < sizeof(a_list); i := i+1) {
4406 if (f_match_codec(a_list.codecElements[i], rsl_mode)) {
4407 return true;
4408 }
4409 }
4410 return false;
4411}
4412
4413/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
Philipp Maier61f6b572018-07-06 14:03:38 +02004414function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
Harald Welte60aa5762018-03-21 19:33:13 +01004415return BSSMAP_IE_ChannelType {
4416 /* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
4417 var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
4418 select (a_elem.codecType) {
4419 case (GSM_FR) {
4420 ret.channelRateAndType := ChRate_TCHF;
4421 ret.speechId_DataIndicator := Spdi_TCHF_FR;
4422 }
4423 case (GSM_HR) {
4424 ret.channelRateAndType := ChRate_TCHH;
4425 ret.speechId_DataIndicator := Spdi_TCHH_HR;
4426 }
4427 case (GSM_EFR) {
4428 ret.channelRateAndType := ChRate_TCHF;
4429 ret.speechId_DataIndicator := Spdi_TCHF_EFR;
4430 }
4431 case (FR_AMR) {
4432 ret.channelRateAndType := ChRate_TCHF;
4433 ret.speechId_DataIndicator := Spdi_TCHF_AMR;
4434 }
4435 case (HR_AMR) {
4436 ret.channelRateAndType := ChRate_TCHH;
4437 ret.speechId_DataIndicator := Spdi_TCHH_AMR;
4438 }
4439 case else {
4440 setverdict(fail, "Unsupported codec ", a_elem);
Daniel Willmannafce8662018-07-06 23:11:32 +02004441 mtc.stop;
Harald Welte60aa5762018-03-21 19:33:13 +01004442 }
4443 }
4444 return ret;
4445}
4446
Harald Weltea63b9102018-03-22 20:36:16 +01004447private function f_rsl_chmod_tmpl_from_codec(BSSMAP_FIELD_CodecElement a_elem)
4448return template RSL_IE_Body {
4449 var template RSL_IE_Body mode_ie := {
4450 chan_mode := {
4451 len := ?,
4452 reserved := ?,
4453 dtx_d := ?,
4454 dtx_u := ?,
4455 spd_ind := RSL_SPDI_SPEECH,
4456 ch_rate_type := -,
Oliver Smith0033b122023-02-28 13:30:53 +01004457 u := { speech := - }
Harald Weltea63b9102018-03-22 20:36:16 +01004458 }
4459 }
4460
4461 select (a_elem.codecType) {
4462 case (GSM_FR) {
4463 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004464 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004465 }
4466 case (GSM_HR) {
4467 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004468 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004469 }
4470 case (GSM_EFR) {
4471 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004472 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM2;
Harald Weltea63b9102018-03-22 20:36:16 +01004473 }
4474 case (FR_AMR) {
4475 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004476 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004477 }
4478 case (HR_AMR) {
4479 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004480 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004481 }
4482 }
4483 return mode_ie;
4484}
4485
Harald Welte60aa5762018-03-21 19:33:13 +01004486type record CodecListTest {
4487 BSSMAP_IE_SpeechCodecList codec_list,
4488 charstring id
4489}
4490type record of CodecListTest CodecListTests
4491
4492private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004493 f_assignment_codec(id);
4494}
4495
4496private function f_assignment_codec(charstring id, boolean do_perform_clear := true) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02004497 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02004498 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welte60aa5762018-03-21 19:33:13 +01004499
4500 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004501 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte79f3f542018-05-25 20:02:37 +02004502 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4503 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
4504 g_pars.ass_codec_list.codecElements[0];
Philipp Maierd0e64b02019-03-13 14:15:23 +01004505 if (isvalue(g_pars.expect_mr_s0_s7)) {
4506 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
4507 g_pars.expect_mr_s0_s7;
4508 }
Harald Welte79f3f542018-05-25 20:02:37 +02004509 }
Harald Welte60aa5762018-03-21 19:33:13 +01004510 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4511 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
Harald Welte60aa5762018-03-21 19:33:13 +01004512 log("expecting ASS COMPL like this: ", exp_compl);
4513
4514 f_establish_fully(ass_cmd, exp_compl);
Harald Weltea63b9102018-03-22 20:36:16 +01004515
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004516 if (not g_pars.expect_channel_mode_modify) {
4517 /* Verify that the RSL-side activation actually matches our expectations */
4518 var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
Harald Weltea63b9102018-03-22 20:36:16 +01004519
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004520 var RSL_IE_Body mode_ie;
4521 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
4522 setverdict(fail, "Couldn't find CHAN_MODE IE");
Daniel Willmannafce8662018-07-06 23:11:32 +02004523 mtc.stop;
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004524 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004525 var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
4526 if (not match(mode_ie, t_mode_ie)) {
4527 log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
4528 setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004529 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004530
4531 var RSL_IE_Body mr_conf;
4532 if (g_pars.expect_mr_conf_ie != omit) {
4533 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
4534 setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
4535 mtc.stop;
4536 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004537 log("found RSL MR CONFIG IE: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004538
4539 if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
Vadim Yanitskiy8b189372022-09-14 17:31:17 +07004540 setverdict(fail, "RSL MR CONFIG IE does not match expectation. ",
4541 "Expected: ", g_pars.expect_mr_conf_ie, ", got: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004542 }
4543 } else {
4544 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
4545 log("found RSL MR CONFIG IE: ", mr_conf);
4546 setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
4547 mtc.stop;
4548 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004549 }
4550 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004551
4552 if (do_perform_clear) {
4553 f_perform_clear();
4554 }
Harald Welte60aa5762018-03-21 19:33:13 +01004555}
4556
Philipp Maierd0e64b02019-03-13 14:15:23 +01004557private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
4558
4559 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4560 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4561
4562 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004563 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maierd0e64b02019-03-13 14:15:23 +01004564 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4565 }
4566 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4567 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
4568 log("expecting ASS FAIL like this: ", exp_fail);
4569
4570 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004571 f_perform_clear();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004572}
4573
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004574const CounterNameVals counternames_bsc_bts_assignment := {
4575 { "assignment:attempted", 0 },
4576 { "assignment:completed", 0 },
4577 { "assignment:stopped", 0 },
4578 { "assignment:no_channel", 0 },
4579 { "assignment:timeout", 0 },
4580 { "assignment:failed", 0 },
4581 { "assignment:error", 0 }
4582};
4583
4584const CounterNameVals counternames_bts_assignment := {
4585 { "assignment:attempted_sign", 0 },
4586 { "assignment:attempted_speech", 0 },
4587 { "assignment:completed_sign", 0 },
4588 { "assignment:completed_speech", 0 },
4589 { "assignment:stopped_sign", 0 },
4590 { "assignment:stopped_speech", 0 },
4591 { "assignment:no_channel_sign", 0 },
4592 { "assignment:no_channel_speech", 0 },
4593 { "assignment:timeout_sign", 0 },
4594 { "assignment:timeout_speech", 0 },
4595 { "assignment:failed_sign", 0 },
4596 { "assignment:failed_speech", 0 },
4597 { "assignment:error_sign", 0 },
4598 { "assignment:error_speech", 0 }
4599};
4600
4601function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
4602 var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
4603 f_ctrs_bts_init(bts_count, bts_names);
4604 f_ctrs_bsc_init(counternames_bsc_bts_assignment);
4605}
4606
Harald Welte60aa5762018-03-21 19:33:13 +01004607testcase TC_assignment_codec_fr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004608 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004609 var MSC_ConnHdlr vc_conn;
4610
4611 f_init(1, true);
4612 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004613 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004614
4615 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004616 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004617 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004618
4619 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4620 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4621 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4622 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4623 f_ctrs_bts_verify();
4624
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004625 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004626}
4627
4628testcase TC_assignment_codec_hr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004629 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004630 var MSC_ConnHdlr vc_conn;
4631
4632 f_init(1, true);
4633 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004634 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004635
4636 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004637 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004638 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004639
4640 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4641 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4642 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4643 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4644 f_ctrs_bts_verify();
4645
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004646 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004647}
4648
4649testcase TC_assignment_codec_efr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004650 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004651 var MSC_ConnHdlr vc_conn;
4652
4653 f_init(1, true);
4654 f_sleep(1.0);
4655
4656 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004657 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004658 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004659 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004660}
4661
Philipp Maierd0e64b02019-03-13 14:15:23 +01004662/* Allow 5,90k only (current default config) */
4663private function f_allow_amr_rate_5_90k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004664 f_vty_cfg_msc(BSCVTY, 0, {
4665 "amr-config 12_2k forbidden",
4666 "amr-config 10_2k forbidden",
4667 "amr-config 7_95k forbidden",
4668 "amr-config 7_40k forbidden",
4669 "amr-config 6_70k forbidden",
4670 "amr-config 5_90k allowed",
4671 "amr-config 5_15k forbidden",
4672 "amr-config 4_75k forbidden"
4673 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004674}
4675
4676/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
4677 * ("Config-NB-Code = 1") */
4678private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004679 f_vty_cfg_msc(BSCVTY, 0, {
4680 "amr-config 12_2k allowed",
4681 "amr-config 10_2k forbidden",
4682 "amr-config 7_95k forbidden",
4683 "amr-config 7_40k allowed",
4684 "amr-config 6_70k forbidden",
4685 "amr-config 5_90k allowed",
4686 "amr-config 5_15k forbidden",
4687 "amr-config 4_75k allowed"
4688 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004689}
4690
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004691private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
4692 var charstring tch;
4693 if (fr) {
4694 tch := "tch-f";
4695 } else {
4696 tch := "tch-h";
4697 }
4698 f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
4699}
4700
4701/* Set the AMR start-mode for this TCH back to the default configuration. */
4702private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
4703 f_vty_amr_start_mode_set(fr, "auto");
4704}
4705
Harald Welte60aa5762018-03-21 19:33:13 +01004706testcase TC_assignment_codec_amr_f() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004707 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004708 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004709
4710 /* Note: This setups the codec configuration. The parameter payload in
4711 * mr_conf must be consistant with the parameter codecElements in pars
4712 * and also must match the amr-config in osmo-bsc.cfg! */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004713 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004714 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004715 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004716 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004717
Harald Welte60aa5762018-03-21 19:33:13 +01004718 f_init(1, true);
4719 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004720 f_vty_amr_start_mode_set(true, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004721 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004722
Harald Welte8863fa12018-05-10 20:15:27 +02004723 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004724 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004725
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004726 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4727 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4728 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4729 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4730 f_ctrs_bts_verify();
4731
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004732 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004733 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004734}
4735
4736testcase TC_assignment_codec_amr_h() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004737 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004738 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004739
4740 /* See note above */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004741 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004742 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004743 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004744 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004745
Harald Welte60aa5762018-03-21 19:33:13 +01004746 f_init(1, true);
4747 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004748 f_vty_amr_start_mode_set(false, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004749 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004750
Harald Welte8863fa12018-05-10 20:15:27 +02004751 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004752 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004753
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004754 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4755 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4756 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4757 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4758 f_ctrs_bts_verify();
4759
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004760 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004761 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004762}
4763
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004764/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
4765testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
4766 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4767 var MSC_ConnHdlr vc_conn;
4768
4769 f_init(1, true);
4770 f_sleep(1.0);
4771
4772 /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
4773 * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
4774 * expecting a Channel Mode Modify if the channel type is compatible. */
4775 f_disable_all_sdcch();
4776 f_disable_all_tch_h();
4777
4778 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4779 pars.expect_channel_mode_modify := true;
4780 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4781 vc_conn.done;
4782
4783 f_enable_all_sdcch();
4784 f_enable_all_tch();
4785 f_shutdown_helper();
4786}
4787
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004788/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
4789testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
4790 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4791 var MSC_ConnHdlr vc_conn;
4792
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004793 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4794 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
4795 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy36fe9582022-09-14 15:25:04 +07004796 pars.expect_mr_conf_ie := c_mr_conf_5_90;
4797 pars.expect_mr_conf_ie.multirate_cfg.icmi := false; /* expect ICMI=0, smod=00: */
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004798
4799 f_init(1, true);
4800 f_sleep(1.0);
4801
4802 /* First set nonzero start mode bits */
4803 f_vty_amr_start_mode_set(true, "4");
4804 /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
4805 * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
4806 * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
4807 f_vty_amr_start_mode_set(true, "auto");
4808
4809 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4810 vc_conn.done;
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004811
4812 /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
4813 f_vty_amr_start_mode_set(true, "1");
4814 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004815 f_shutdown_helper();
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004816}
4817
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004818function f_TC_assignment_codec_amr(boolean fr, RSL_IE_MultirateCfg mr_cfg,
4819 bitstring s8_s0, bitstring exp_s8_s0,
4820 charstring start_mode := "1")
Philipp Maierd0e64b02019-03-13 14:15:23 +01004821runs on test_CT {
4822
4823 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4824 var MSC_ConnHdlr vc_conn;
4825
Philipp Maierd0e64b02019-03-13 14:15:23 +01004826 if (fr) {
4827 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4828 } else {
4829 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4830 }
4831 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4832 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004833 pars.expect_mr_conf_ie := { multirate_cfg := mr_cfg };
Philipp Maierd0e64b02019-03-13 14:15:23 +01004834 pars.expect_mr_s0_s7 := exp_s8_s0;
4835
4836 f_init(1, true);
4837 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004838 f_vty_amr_start_mode_set(fr, start_mode);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004839 f_sleep(1.0);
4840
4841 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4842 vc_conn.done;
4843 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004844 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004845}
4846
4847function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
4848runs on test_CT {
4849
4850 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4851 var MSC_ConnHdlr vc_conn;
4852
4853 if (fr) {
4854 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4855 } else {
4856 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4857 }
4858 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4859 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4860
4861 f_init(1, true);
4862 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004863 f_vty_amr_start_mode_set(fr, "1");
Philipp Maierd0e64b02019-03-13 14:15:23 +01004864 f_sleep(1.0);
4865
4866 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
4867 vc_conn.done;
4868 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004869 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004870}
4871
Philipp Maierd0e64b02019-03-13 14:15:23 +01004872/* Set S1, we expect an AMR multirate configuration IE with all four rates
4873 * set. */
4874testcase TC_assignment_codec_amr_f_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004875 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4876 params := '20882208'O));
4877 f_TC_assignment_codec_amr(true, mr_cfg, '00000011'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004878 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004879}
4880
4881/* Set S1, we expect an AMR multirate configuration IE with the lower three
4882 * rates set. */
4883testcase TC_assignment_codec_amr_h_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004884 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4885 params := '208820'O));
4886 f_TC_assignment_codec_amr(false, mr_cfg, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004887 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004888}
4889
4890/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4891 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4892testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004893 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4894 params := '20882208'O));
4895 f_TC_assignment_codec_amr(true, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004896 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004897}
4898
4899/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4900 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4901testcase TC_assignment_codec_amr_h_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004902 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4903 params := '208820'O));
4904 f_TC_assignment_codec_amr(false, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004905 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004906}
4907
4908/* The following block of tests selects more and more rates until all four
4909 * possible rates are in the active set (full rate) */
4910testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004911 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4912 f_TC_assignment_codec_amr(true, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004913 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004914}
4915
4916testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004917 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4918 params := '2080'O));
4919 f_TC_assignment_codec_amr(true, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004920 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004921}
4922
4923testcase TC_assignment_codec_amr_f_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004924 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4925 params := '208820'O));
4926 f_TC_assignment_codec_amr(true, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004927 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004928}
4929
4930testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004931 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4932 params := '20882208'O));
4933 f_TC_assignment_codec_amr(true, mr_cfg, '10010101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004934 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004935}
4936
4937/* The following block of tests selects more and more rates until all three
4938 * possible rates are in the active set (half rate) */
4939testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004940 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4941 f_TC_assignment_codec_amr(false, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004942 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004943}
4944
4945testcase TC_assignment_codec_amr_h_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004946 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4947 params := '2080'O));
4948 f_TC_assignment_codec_amr(false, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004949 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004950}
4951
4952testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004953 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4954 params := '208820'O));
4955 f_TC_assignment_codec_amr(false, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004956 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004957}
4958
4959/* The following block tests what happens when the MSC does offer rate
4960 * configurations that are not supported by the BSC. Normally such situations
4961 * should not happen because the MSC gets informed by the BSC in advance via
4962 * the L3 COMPLETE message which rates are applicable. The MSC should not try
4963 * to offer rates that are not applicable anyway. */
4964
4965testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004966 /* Try to include 12,2k in into the active set even though the channel
4967 * is half rate only. The BSC is expected to remove the 12,0k */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004968 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4969 params := '208820'O));
4970 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004971 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004972}
4973
4974testcase TC_assignment_codec_amr_f_S01234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004975 /* See what happens when all rates are selected at once. Since then
4976 * Also S1 is selected, this setting will be prefered and we should
4977 * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004978 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4979 params := '20882208'O));
4980 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004981 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004982}
4983
4984testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004985 /* Same as above, but with S1 missing, the MSC is then expected to
4986 * select the currently supported rates, which are also 12.2k, 7,40k,
4987 * 5,90k, and 4,75k, into the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004988 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4989 params := '20882208'O));
4990 f_TC_assignment_codec_amr(true, mr_cfg, '11111101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004991 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004992}
4993
4994testcase TC_assignment_codec_amr_f_zero() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004995 /* Try to select no rates at all */
4996 f_TC_assignment_codec_amr_fail(true, '00000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004997 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004998}
4999
5000testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02005001 /* Try to select only unsupported rates */
5002 f_TC_assignment_codec_amr_fail(true, '01101000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005003 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01005004}
5005
5006testcase TC_assignment_codec_amr_h_S7() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02005007 /* Try to select 12,2k for half rate */
5008 f_TC_assignment_codec_amr_fail(false, '10000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005009 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01005010}
5011
Neels Hofmeyr21863562020-11-26 00:34:33 +00005012testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07005013 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
5014 codec_modes := '10010101'B,
5015 params := '20882208'O));
5016 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01005017 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00005018}
5019
5020testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07005021 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
5022 codec_modes := '00010101'B,
5023 params := '208820'O));
5024 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B,
Neels Hofmeyr21863562020-11-26 00:34:33 +00005025 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01005026 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00005027}
5028
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00005029testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01005030 /* "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 +07005031 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 3,
5032 codec_modes := '10010101'B,
5033 params := '20882208'O));
5034 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01005035 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00005036}
5037
5038testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01005039 /* "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 +07005040 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 2,
5041 codec_modes := '00010101'B,
5042 params := '208820'O));
5043 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01005044 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00005045}
5046
Philipp Maierac09bfc2019-01-08 13:41:39 +01005047private function f_disable_all_tch_f() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005048 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 borken");
5049 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 borken");
5050 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 borken");
5051 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005052}
5053
5054private function f_disable_all_tch_h() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005055 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 borken");
5056 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005057}
5058
5059private function f_enable_all_tch() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005060 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 unused");
5061 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 unused");
5062 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 unused");
5063 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 unused");
5064 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 unused");
5065 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005066}
5067
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02005068private function f_disable_all_sdcch() runs on test_CT {
5069 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
5070 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
5071 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
5072 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
5073}
5074
5075private function f_enable_all_sdcch() runs on test_CT {
5076 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
5077 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
5078 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
5079 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
5080}
5081
Philipp Maierac09bfc2019-01-08 13:41:39 +01005082/* Allow HR only */
5083private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs on MSC_ConnHdlr {
5084 g_pars := f_gen_test_hdlr_pars();
5085 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5086 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5087 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5088 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5089 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5090 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5091 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005092 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005093}
5094
5095/* Allow FR only */
5096private function f_TC_assignment_codec_xr_exhausted_req_fr(charstring id) runs on MSC_ConnHdlr {
5097 g_pars := f_gen_test_hdlr_pars();
5098 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5099 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5100 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5101 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5102 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5103 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5104 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005105 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005106}
5107
5108/* Allow HR only (expect assignment failure) */
5109private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) runs on MSC_ConnHdlr {
5110 g_pars := f_gen_test_hdlr_pars();
5111 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5112 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5113 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5114 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5115 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5116 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5117 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005118 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005119}
5120
5121/* Allow FR only (expect assignment failure) */
5122private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) runs on MSC_ConnHdlr {
5123 g_pars := f_gen_test_hdlr_pars();
5124 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5125 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5126 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5127 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5128 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5129 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5130 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005131 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005132}
5133
5134/* Allow FR and HR, but prefer FR */
5135private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5136 g_pars := f_gen_test_hdlr_pars();
5137 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5138 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5139 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5140 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5141 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5142 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5143 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5144 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005145 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005146}
5147
5148/* Allow FR and HR, but prefer HR */
5149private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5150 g_pars := f_gen_test_hdlr_pars();
5151 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5152 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5153 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5154 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5155 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5156 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5157 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5158 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005159 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005160}
5161
5162/* Allow FR and HR, but prefer FR */
5163private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5164 g_pars := f_gen_test_hdlr_pars();
5165 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5166 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5167 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5168 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5169 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5170 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5171 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5172 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005173 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005174}
5175
5176/* Allow FR and HR, but prefer HR */
5177private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5178 g_pars := f_gen_test_hdlr_pars();
5179 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5180 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5181 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5182 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5183 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5184 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5185 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5186 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005187 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005188}
5189
5190/* Request a HR channel while all FR channels are exhausted, this is expected
5191 * to work without conflicts */
5192testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
5193 var MSC_ConnHdlr vc_conn;
5194 f_init(1, true);
5195 f_sleep(1.0);
5196 f_enable_all_tch();
5197 f_disable_all_tch_f();
5198 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
5199 vc_conn.done;
5200 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005201 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005202}
5203
5204/* Request a FR channel while all FR channels are exhausted, this is expected
5205 * to fail. */
5206testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
5207 var MSC_ConnHdlr vc_conn;
5208 f_init(1, true);
5209 f_sleep(1.0);
5210 f_enable_all_tch();
5211 f_disable_all_tch_f();
5212 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
5213 vc_conn.done;
5214 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005215 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005216}
5217
5218/* Request a FR (prefered) or alternatively a HR channel while all FR channels
5219 * are exhausted, this is expected to be resolved by selecting a HR channel. */
5220testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
5221 var MSC_ConnHdlr vc_conn;
5222 f_init(1, true);
5223 f_sleep(1.0);
5224 f_enable_all_tch();
5225 f_disable_all_tch_f();
5226 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
5227 vc_conn.done;
5228 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005229 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005230}
5231
5232/* Request a HR (prefered) or alternatively a FR channel while all FR channels
5233 * are exhausted, this is expected to work without conflicts. */
5234testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
5235 var MSC_ConnHdlr vc_conn;
5236 f_init(1, true);
5237 f_sleep(1.0);
5238 f_enable_all_tch();
5239 f_disable_all_tch_f();
5240 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
5241 vc_conn.done;
5242 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005243 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005244}
5245
5246/* Request a FR channel while all HR channels are exhausted, this is expected
5247 * to work without conflicts */
5248testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
5249 var MSC_ConnHdlr vc_conn;
5250 f_init(1, true);
5251 f_sleep(1.0);
5252 f_enable_all_tch();
5253 f_disable_all_tch_h();
5254 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
5255 vc_conn.done;
5256 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005257 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005258}
5259
5260/* Request a HR channel while all HR channels are exhausted, this is expected
5261 * to fail. */
5262testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
5263 var MSC_ConnHdlr vc_conn;
5264 f_init(1, true);
5265 f_sleep(1.0);
5266 f_enable_all_tch();
5267 f_disable_all_tch_h();
5268 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
5269 vc_conn.done;
5270 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005271 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005272}
5273
5274/* Request a HR (prefered) or alternatively a FR channel while all HR channels
5275 * are exhausted, this is expected to be resolved by selecting a FR channel. */
5276testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
5277 var MSC_ConnHdlr vc_conn;
5278 f_init(1, true);
5279 f_sleep(1.0);
5280 f_enable_all_tch();
5281 f_disable_all_tch_h();
5282 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
5283 vc_conn.done;
5284 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005285 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005286}
5287
5288/* Request a FR (prefered) or alternatively a HR channel while all HR channels
5289 * are exhausted, this is expected to work without conflicts. */
5290testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
5291 var MSC_ConnHdlr vc_conn;
5292 f_init(1, true);
5293 f_sleep(1.0);
5294 f_enable_all_tch();
5295 f_disable_all_tch_h();
5296 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
5297 vc_conn.done;
5298 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005299 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005300}
5301
5302/* Allow FR and HR, but prefer HR */
5303private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5304 g_pars := f_gen_test_hdlr_pars();
5305 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5306 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5307 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5308 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5309 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5310 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5311 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5312 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005313 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005314}
5315
5316/* Allow FR and HR, but prefer FR */
5317private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5318 g_pars := f_gen_test_hdlr_pars();
5319 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5320 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5321 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5322 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5323 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5324 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5325 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5326 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005327 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005328}
5329
5330/* Request a HR (prefered) or alternatively a FR channel, it is expected that
5331 * HR, which is the prefered type, is selected. */
5332testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
5333 var MSC_ConnHdlr vc_conn;
5334 f_init(1, true);
5335 f_sleep(1.0);
5336 f_enable_all_tch();
5337 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
5338 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005339 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005340}
5341
5342/* Request a FR (prefered) or alternatively a HR channel, it is expected that
5343 * FR, which is the prefered type, is selected. */
5344testcase TC_assignment_codec_req_fr_hr() runs on test_CT {
5345 var MSC_ConnHdlr vc_conn;
5346 f_init(1, true);
5347 f_sleep(1.0);
5348 f_enable_all_tch();
5349 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_fr_hr));
5350 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005351 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005352}
5353
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005354/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
5355private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
5356 g_pars := f_gen_test_hdlr_pars();
5357 g_pars.ra := '02'O; /* RA containing reason=LU */
5358
5359 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5360 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5361 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5362 var template uint3_t tsc := ?;
5363
5364 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5365 f_create_bssmap_exp(l3_enc);
5366 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5367 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5368
5369 /* we should now have a COMPL_L3 at the MSC */
5370 timer T := 10.0;
5371 T.start;
5372 alt {
5373 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5374 [] T.timeout {
5375 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5376 }
5377 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005378
5379 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005380}
5381testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
5382 var MSC_ConnHdlr vc_conn;
5383 f_init(1, true);
5384 f_sleep(1.0);
5385 f_disable_all_sdcch();
5386 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
5387 vc_conn.done;
5388 f_enable_all_sdcch();
5389 f_shutdown_helper();
5390}
5391
5392/* Request a signalling channel with all SDCCH exhausted, it is
5393 expected that no TCH will be selected for signalling and assigment will fail
5394 because it's dictated by VTY config */
5395testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
5396 var RSL_Message rsl_unused, rsl_msg;
5397 var GsmRrMessage rr;
5398 f_init(1, false);
5399 f_sleep(1.0);
5400 f_vty_allow_tch_for_signalling(false, 0);
5401 f_disable_all_sdcch();
5402
5403 /* RA containing reason=LU */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005404 f_ipa_tx(ts_RSL_CHAN_RQD('02'O, 2342));
5405 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005406 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
5407 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
5408 setverdict(fail, "Expected reject");
5409 }
5410
5411 f_vty_allow_tch_for_signalling(true, 0);
5412 f_enable_all_sdcch();
5413 f_shutdown_helper();
5414}
5415
5416/* Request a voice channel with all SDCCH exhausted, it is
5417 * expected that TCH channel will be allocated since the VTY option is only
5418 * aimed at signalling requests */
5419private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
5420 g_pars := f_gen_test_hdlr_pars();
5421 g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
5422
5423 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5424 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5425 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5426 var template uint3_t tsc := ?;
5427
5428 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5429 f_create_bssmap_exp(l3_enc);
5430 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5431 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5432
5433 /* we should now have a COMPL_L3 at the MSC */
5434 timer T := 10.0;
5435 T.start;
5436 alt {
5437 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5438 [] T.timeout {
5439 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5440 }
5441 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005442 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005443}
5444testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
5445 var MSC_ConnHdlr vc_conn;
5446 f_init(1, true);
5447 f_sleep(1.0);
5448 f_vty_allow_tch_for_signalling(false, 0);
5449 f_disable_all_sdcch();
5450
5451 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
5452 vc_conn.done;
5453
5454 f_vty_allow_tch_for_signalling(true, 0);
5455 f_enable_all_sdcch();
5456 f_shutdown_helper();
5457}
5458
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005459/* Test Osmux setup BSC<->MSC */
5460testcase TC_assignment_osmux_cn() runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005461 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5462 var MSC_ConnHdlr vc_conn;
5463
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005464 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5465 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5466 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiyb9bf00f2022-09-14 15:35:37 +07005467 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02005468 pars.use_osmux_cn := true;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005469
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02005470 g_osmux_enabled_cn := true;
5471 f_init(1, true);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005472 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005473 f_vty_amr_start_mode_set(false, "1");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005474
5475 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5476 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005477
5478 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01005479 f_shutdown_helper();
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005480}
5481
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005482/* Test Osmux setup BTS<->BSC */
5483testcase TC_assignment_osmux_bts() runs on test_CT {
5484 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5485 var MSC_ConnHdlr vc_conn;
5486
5487 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5488 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5489 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005490 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005491 pars.use_osmux_bts := true;
5492
5493 g_osmux_enabled_bts := true;
5494 f_init(1, true);
5495 f_sleep(1.0);
5496 f_vty_amr_start_mode_set(false, "1");
5497
5498 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5499 vc_conn.done;
5500
5501 f_vty_amr_start_mode_restore(false);
5502 f_shutdown_helper();
5503}
5504
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +02005505/* Test non-AMR codecs still work fine as RTP when Osmux is enabled BTS<->BSC<->MSC */
5506testcase TC_assignment_codec_hr_osmux_on() runs on test_CT {
5507 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5508 var MSC_ConnHdlr vc_conn;
5509
5510 g_osmux_enabled_cn := true;
5511 g_osmux_enabled_bts := true;
5512 f_init(1, true);
5513 f_sleep(1.0);
5514 f_ctrs_bsc_and_bts_assignment_init(1);
5515
5516 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5517 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5518 vc_conn.done;
5519
5520 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
5521 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
5522 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
5523 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
5524 f_ctrs_bts_verify();
5525
5526 f_shutdown_helper();
5527}
5528
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005529/* Test Osmux setup BTS<->BSC<->MSC */
5530testcase TC_assignment_osmux() runs on test_CT {
5531 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5532 var MSC_ConnHdlr vc_conn;
5533
5534 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5535 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5536 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005537 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005538 pars.use_osmux_cn := true;
5539 pars.use_osmux_bts := true;
5540
5541 g_osmux_enabled_cn := true;
5542 g_osmux_enabled_bts := true;
5543 f_init(1, true);
5544 f_sleep(1.0);
5545 f_vty_amr_start_mode_set(false, "1");
5546
5547 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5548 vc_conn.done;
5549
5550 f_vty_amr_start_mode_restore(false);
5551 f_shutdown_helper();
5552}
5553
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005554/* test the procedure of the MSC requesting a Classmark Update:
5555 * a) BSSMAP Classmark Request should result in RR CLASSMARK ENQUIRY,
5556 * b) L3 RR CLASSMARK CHANGE should result in BSSMAP CLASSMARK UPDATE */
Harald Welte898113b2018-01-31 18:32:21 +01005557private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005558 g_pars := f_gen_test_hdlr_pars();
5559
Harald Weltea0630032018-03-20 21:09:55 +01005560 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005561 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005562
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005563 BSSAP.send(ts_BSSMAP_ClassmarkRequest);
5564 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
5565
Harald Welte898113b2018-01-31 18:32:21 +01005566 f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
5567 BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
5568 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005569
5570 f_perform_clear();
Harald Welte898113b2018-01-31 18:32:21 +01005571}
5572testcase TC_classmark() runs on test_CT {
5573 var MSC_ConnHdlr vc_conn;
5574 f_init(1, true);
5575 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005576 vc_conn := f_start_handler(refers(f_tc_classmark));
Harald Welte898113b2018-01-31 18:32:21 +01005577 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005578 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005579}
5580
Harald Welteeddf0e92020-06-21 19:42:15 +02005581/* Send a CommonID from the simulated MSC and verify that the information is used to
5582 * fill BSC-internal data structures (specifically, bsc_subscr associated with subscr_conn) */
5583private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
5584 g_pars := f_gen_test_hdlr_pars();
5585 f_MscConnHdlr_init_vty();
5586
5587 f_create_chan_and_exp();
5588 /* we should now have a COMPL_L3 at the MSC */
Harald Welteeddf0e92020-06-21 19:42:15 +02005589
5590 /* Send CommonID */
5591 BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
5592
5593 /* Use VTY to verify that the IMSI of the subscr_conn is set */
5594 var charstring regex := "*(IMSI: " & hex2str(g_pars.imsi) & ")*";
5595 f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
5596
5597 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005598
5599 f_perform_clear();
Harald Welteeddf0e92020-06-21 19:42:15 +02005600}
5601testcase TC_common_id() runs on test_CT {
5602 var MSC_ConnHdlr vc_conn;
5603 f_init(1, true);
5604 f_sleep(1.0);
5605 vc_conn := f_start_handler(refers(f_tc_common_id));
5606 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005607 f_shutdown_helper();
Harald Welteeddf0e92020-06-21 19:42:15 +02005608}
5609
Harald Weltee3bd6582018-01-31 22:51:25 +01005610private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005611 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005612 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005613 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005614
Harald Weltee3bd6582018-01-31 22:51:25 +01005615 /* send the single message we want to send */
5616 f_rsl_send_l3(l3);
5617}
5618
5619private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr {
5620 timer T := sec;
5621 var PDU_BSSAP bssap;
Harald Welte898113b2018-01-31 18:32:21 +01005622 T.start;
5623 alt {
Harald Weltee3bd6582018-01-31 22:51:25 +01005624 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap {
5625 setverdict(fail, "Unexpected BSSMAP ", bssap);
Daniel Willmannafce8662018-07-06 23:11:32 +02005626 mtc.stop;
Harald Welte898113b2018-01-31 18:32:21 +01005627 }
5628 [] T.timeout {
5629 setverdict(pass);
5630 }
5631 }
5632}
5633
Harald Weltee3bd6582018-01-31 22:51:25 +01005634/* unsolicited ASSIGNMENT FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5635private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
5636 f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
5637 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005638 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005639}
Harald Welte898113b2018-01-31 18:32:21 +01005640testcase TC_unsol_ass_fail() runs on test_CT {
5641 var MSC_ConnHdlr vc_conn;
5642 f_init(1, true);
5643 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005644 vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
Harald Welte898113b2018-01-31 18:32:21 +01005645 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005646 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005647}
Harald Welte552620d2017-12-16 23:21:36 +01005648
Harald Welteea99a002018-01-31 20:46:43 +01005649
5650/* unsolicited ASSIGNMENT COMPLETE (without ASSIGN) from MS shouldn't bring BSC down */
5651private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005652 f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
5653 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005654 f_perform_clear();
Harald Welteea99a002018-01-31 20:46:43 +01005655}
5656testcase TC_unsol_ass_compl() runs on test_CT {
5657 var MSC_ConnHdlr vc_conn;
5658 f_init(1, true);
5659 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005660 vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
Harald Welteea99a002018-01-31 20:46:43 +01005661 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005662 f_shutdown_helper();
Harald Welteea99a002018-01-31 20:46:43 +01005663}
5664
5665
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005666/* unsolicited HANDOVER FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5667private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005668 f_est_single_l3(ts_RRM_HandoverFailure('00'O));
5669 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005670 f_perform_clear();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005671}
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005672testcase TC_unsol_ho_fail() runs on test_CT {
5673 var MSC_ConnHdlr vc_conn;
5674 f_init(1, true);
5675 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005676 vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005677 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005678 f_shutdown_helper();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005679}
5680
5681
Harald Weltee3bd6582018-01-31 22:51:25 +01005682/* short message from MS should be ignored */
5683private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005684 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005685 f_create_chan_and_exp();
Harald Weltee3bd6582018-01-31 22:51:25 +01005686 /* we should now have a COMPL_L3 at the MSC */
Harald Weltee3bd6582018-01-31 22:51:25 +01005687
5688 /* send short message */
5689 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
5690 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005691 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005692}
5693testcase TC_err_82_short_msg() runs on test_CT {
5694 var MSC_ConnHdlr vc_conn;
5695 f_init(1, true);
5696 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005697 vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
Harald Weltee3bd6582018-01-31 22:51:25 +01005698 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005699 f_shutdown_helper();
Harald Weltee3bd6582018-01-31 22:51:25 +01005700}
5701
Harald Weltee9e02e42018-01-31 23:36:25 +01005702/* 24.008 8.4 Unknown message must trigger RR STATUS */
5703private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
Andreas Eversberg9ff96e62023-07-25 12:37:42 +02005704 f_est_single_l3(ts_RRM_DTM_ASS_FAIL('00'O));
Harald Weltee9e02e42018-01-31 23:36:25 +01005705 timer T := 3.0
5706 alt {
5707 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
5708 setverdict(pass);
5709 }
5710 [] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
Harald Welte458fd372018-03-21 11:26:23 +01005711 [] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
Harald Weltee9e02e42018-01-31 23:36:25 +01005712 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005713 f_perform_clear();
Harald Weltee9e02e42018-01-31 23:36:25 +01005714}
5715testcase TC_err_84_unknown_msg() runs on test_CT {
5716 var MSC_ConnHdlr vc_conn;
5717 f_init(1, true);
5718 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005719 vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
Harald Weltee9e02e42018-01-31 23:36:25 +01005720 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005721 f_shutdown_helper();
Harald Weltee9e02e42018-01-31 23:36:25 +01005722}
5723
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005724/***********************************************************************
5725 * Handover
5726 ***********************************************************************/
5727
Harald Welte94e0c342018-04-07 11:33:23 +02005728/* execute a "bts <0-255> trx <0-255> timeslot <0-7> " command on given Dchan */
5729private function f_vty_ts_action(charstring suffix, integer bts_nr, integer trx_nr, integer ts_nr)
5730runs on test_CT {
5731 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5732 " timeslot "&int2str(ts_nr)&" ";
5733 f_vty_transceive(BSCVTY, cmd & suffix);
5734}
5735
Harald Welte261af4b2018-02-12 21:20:39 +01005736/* 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 +07005737private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
5738 uint8_t bts_nr, uint8_t trx_nr,
5739 in RslChannelNr chan_nr)
5740{
Harald Welte261af4b2018-02-12 21:20:39 +01005741 /* FIXME: resolve those from component-global state */
5742 var integer ts_nr := chan_nr.tn;
5743 var integer ss_nr;
5744 if (ischosen(chan_nr.u.ch0)) {
5745 ss_nr := 0;
5746 } else if (ischosen(chan_nr.u.lm)) {
5747 ss_nr := chan_nr.u.lm.sub_chan;
5748 } else if (ischosen(chan_nr.u.sdcch4)) {
5749 ss_nr := chan_nr.u.sdcch4.sub_chan;
5750 } else if (ischosen(chan_nr.u.sdcch8)) {
5751 ss_nr := chan_nr.u.sdcch8.sub_chan;
5752 } else {
5753 setverdict(fail, "Invalid ChanNr ", chan_nr);
Daniel Willmannafce8662018-07-06 23:11:32 +02005754 mtc.stop;
Harald Welte261af4b2018-02-12 21:20:39 +01005755 }
5756
5757 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5758 " timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005759 f_vty_transceive(pt, cmd & suffix);
Harald Welte261af4b2018-02-12 21:20:39 +01005760}
5761
Neels Hofmeyr91401012019-07-11 00:42:35 +02005762/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
5763 * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor
5764 * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
5765 * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
5766 * pair, not really to a specific BTS number. */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005767private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
5768 in RslChannelNr chan_nr, uint8_t new_bts_nr)
5769{
5770 f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
Harald Welte261af4b2018-02-12 21:20:39 +01005771}
5772
5773/* intra-BSC hand-over between BTS0 and BTS1 */
5774private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02005775 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5776 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte261af4b2018-02-12 21:20:39 +01005777
5778 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5779 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5780
Harald Weltea0630032018-03-20 21:09:55 +01005781 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005782 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Harald Welte261af4b2018-02-12 21:20:39 +01005783
5784 var HandoverState hs := {
5785 rr_ho_cmpl_seen := false,
5786 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005787 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005788 expect_target_tsc := c_BtsParams[1].tsc
Harald Welte261af4b2018-02-12 21:20:39 +01005789 };
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005790 /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005791 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
Harald Welte261af4b2018-02-12 21:20:39 +01005792 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5793 f_rslem_suspend(RSL1_PROC);
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005794
5795 /* From the MGW perspective, a handover is is characterized by
5796 * performing one MDCX operation with the MGW. So we expect to see
5797 * one more MDCX during handover. */
5798 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5799
Harald Welte261af4b2018-02-12 21:20:39 +01005800 alt {
5801 [] as_handover(hs);
Harald Welte261af4b2018-02-12 21:20:39 +01005802 }
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005803
Philipp Maier4dae0652018-11-12 12:03:26 +01005804 /* Since this is an internal handover we expect the BSC to inform the
5805 * MSC about the event */
5806 BSSAP.receive(tr_BSSMAP_HandoverPerformed);
5807
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005808 /* Check the amount of MGCP transactions is still consistant with the
5809 * test expectation */
5810 f_check_mgcp_expectations()
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005811
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005812 var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
5813
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005814 /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
5815 * 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 +02005816 f_verify_encr_info(chan_act);
5817
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005818 f_chan_act_verify_tsc(chan_act, c_BtsParams[1].tsc);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005819
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005820 f_perform_clear(RSL1, RSL1_PROC);
5821
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005822 f_sleep(0.5);
Harald Welte261af4b2018-02-12 21:20:39 +01005823}
5824
5825testcase TC_ho_int() runs on test_CT {
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005826 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte261af4b2018-02-12 21:20:39 +01005827 var MSC_ConnHdlr vc_conn;
5828 f_init(2, true);
5829 f_sleep(1.0);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005830
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005831 pars.expect_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005832
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005833 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005834
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005835 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
Harald Welte261af4b2018-02-12 21:20:39 +01005836 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005837
5838 /* from f_establish_fully() */
5839 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5840 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5841 /* from handover */
5842 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5843 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5844 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5845 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005846 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5847 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005848 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005849 f_shutdown_helper(ho := true);
Harald Welte261af4b2018-02-12 21:20:39 +01005850}
Harald Weltee9e02e42018-01-31 23:36:25 +01005851
Oliver Smith7eabd312021-07-12 14:18:56 +02005852function 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 +02005853 var MSC_ConnHdlr vc_conn;
5854 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5855 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
5856
5857 f_init(2, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02005858 f_vty_encryption_a5(enc_a5);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005859 f_sleep(1.0);
5860
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005861 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005862
5863 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
5864 vc_conn.done;
5865
5866 /* from f_establish_fully() */
5867 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5868 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5869 /* from handover */
5870 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5871 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5872 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5873 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005874 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5875 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005876 f_ctrs_bsc_and_bts_verify();
Oliver Smith7eabd312021-07-12 14:18:56 +02005877 f_vty_encryption_a5_reset();
Oliver Smith39f53072022-10-27 14:44:04 +02005878 f_shutdown_helper(ho := true);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005879}
5880
5881testcase TC_ho_int_a5_0() runs on test_CT {
5882 f_tc_ho_int_a5('01'O);
5883}
5884
5885testcase TC_ho_int_a5_1() runs on test_CT {
5886 f_tc_ho_int_a5('02'O);
5887}
5888
5889testcase TC_ho_int_a5_3() runs on test_CT {
5890 f_tc_ho_int_a5('08'O);
5891}
5892
5893testcase TC_ho_int_a5_4() runs on test_CT {
Oliver Smith7eabd312021-07-12 14:18:56 +02005894 f_tc_ho_int_a5('10'O, "0 1 3 4");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005895}
5896
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005897/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
5898private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
5899 g_pars := f_gen_test_hdlr_pars();
5900 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5901 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005902
5903 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5904 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5905
5906 f_establish_fully(ass_cmd, exp_compl);
5907 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
5908
5909 var HandoverState hs := {
5910 rr_ho_cmpl_seen := false,
5911 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005912 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005913 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005914 };
5915 /* issue hand-over command on VTY */
5916 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
5917 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5918 f_rslem_suspend(RSL1_PROC);
5919
5920 /* From the MGW perspective, a handover is is characterized by
5921 * performing one MDCX operation with the MGW. So we expect to see
5922 * one more MDCX during handover. */
5923 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5924
5925 var RSL_Message rsl;
5926 var PDU_ML3_NW_MS l3;
5927 var RslChannelNr new_chan_nr;
5928 var GsmArfcn arfcn;
5929 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
5930 l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
5931 if (not ischosen(l3.msgs.rrm.handoverCommand)) {
5932 setverdict(fail, "Expected handoverCommand");
5933 mtc.stop;
5934 }
5935 }
5936 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
5937 new_chan_nr, arfcn);
5938
5939 f_rslem_register(0, new_chan_nr, RSL1_PROC);
5940
5941 /* resume processing of RSL DChan messages, which was temporarily suspended
5942 * before performing a hand-over */
5943 f_rslem_resume(RSL1_PROC);
5944 RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
5945
5946 f_sleep(1.0);
5947
5948 /* Handover fails because no HANDO DET appears on the new lchan,
5949 * and the old lchan reports a Radio Link Failure. */
5950 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
5951
5952 var PDU_BSSAP rx_clear_request;
5953 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5954 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5955 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5956
5957 var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
5958
5959 var MgcpCommand mgcp;
5960 interleave {
5961 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
5962 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005963 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005964 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005965 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005966 }
5967 [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005968 [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005969 RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005970 f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005971 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005972 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5973 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5974 }
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005975 }
5976
5977 f_sleep(0.5);
5978 setverdict(pass);
5979}
5980testcase TC_ho_int_radio_link_failure() runs on test_CT {
5981 var MSC_ConnHdlr vc_conn;
5982 f_init(2, true);
5983 f_sleep(1.0);
5984
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005985 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005986
5987 vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
5988 vc_conn.done;
5989
5990 /* from f_establish_fully() */
5991 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5992 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5993 /* from handover */
5994 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5995 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
5996 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5997 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005998 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5999 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
Neels Hofmeyr5f144212020-11-03 15:41:58 +00006000 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006001 f_shutdown_helper(ho := true);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00006002}
6003
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006004/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006005private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006006 var MgcpCommand mgcp;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02006007 var template MgcpResponse mgcp_resp;
6008 var MGCP_RecvFrom mrf;
6009 var template MgcpMessage msg_resp;
6010 var template MgcpMessage msg_dlcx := {
6011 command := tr_DLCX()
6012 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006013
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02006014 if (g_pars.aoip) {
6015 MGCP.receive(tr_DLCX()) -> value mgcp {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006016 log("Got first DLCX: ", mgcp);
6017 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02006018 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006019
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006020 MGCP.receive(tr_DLCX()) -> value mgcp {
6021 log("Got second DLCX: ", mgcp);
6022 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
6023 };
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02006024 } else {
6025 /* For SCCPLite, BSC doesn't handle the MSC-side */
6026 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
6027 log("Got first DLCX: ", mrf.msg.command);
6028 msg_resp := {
6029 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
6030 }
6031 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
6032 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006033 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006034}
6035
Oliver Smithc9a5f532022-10-21 11:32:23 +02006036private function f_ho_out_of_this_bsc(template (omit) BSSMAP_oldToNewBSSIEs exp_oldToNewBSSIEs := omit,
6037 boolean skip_meas_rep := false) runs on MSC_ConnHdlr {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006038
Oliver Smithc9a5f532022-10-21 11:32:23 +02006039 if (not skip_meas_rep) {
6040 var NcellReports neighbor_rep := {
6041 { rxlev := 20, bcch_freq := 0, bsic := 11 }
6042 };
6043 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
6044 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
6045 l3_mr, 0));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006046
Oliver Smithc9a5f532022-10-21 11:32:23 +02006047 BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
6048 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006049
6050 f_sleep(0.5);
6051 /* The MSC negotiates Handover Request and Handover Request Ack with
6052 * the other BSS and comes back with a BSSMAP Handover Command
6053 * containing an RR Handover Command coming from the target BSS... */
6054
6055 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6056 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6057 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6058 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6059 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6060
6061 /* expect the Handover Command to go out on RR */
6062 var RSL_Message rsl_ho_cmd
6063 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6064 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6065 var RSL_IE_Body rsl_ho_cmd_l3;
6066 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6067 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6068 setverdict(fail);
6069 } else {
6070 log("Found L3 Info: ", rsl_ho_cmd_l3);
6071 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6072 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6073 setverdict(fail);
6074 } else {
6075 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6076 setverdict(pass);
6077 }
6078 }
6079
6080 /* When the other BSS has reported a completed handover, this side is
6081 * torn down. */
6082
6083 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_HANDOVER_SUCCESSFUL;
6084 var BssmapCause cause := enum2int(cause_val);
6085 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6086
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006087 f_expect_dlcx_conns();
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006088
6089 interleave {
6090 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
6091 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
6092 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006093 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
6094 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
6095 }
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006096 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006097 setverdict(pass);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006098}
6099
6100private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
6101 g_pars := f_gen_test_hdlr_pars();
6102 var PDU_BSSAP ass_req := f_gen_ass_req();
6103 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6104 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6105 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6106 f_establish_fully(ass_req, exp_compl);
6107
6108 f_ho_out_of_this_bsc();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006109}
6110testcase TC_ho_out_of_this_bsc() runs on test_CT {
6111 var MSC_ConnHdlr vc_conn;
6112
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006113 f_init_vty();
6114 f_bts_0_cfg(BSCVTY,
6115 {"neighbor-list mode automatic",
6116 "handover 1",
6117 "handover algorithm 2",
6118 "handover2 window rxlev averaging 1",
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006119 "no neighbors",
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006120 "neighbor lac 99 arfcn 123 bsic any"});
6121 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6122
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006123 f_init(1, true);
6124 f_sleep(1.0);
6125
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006126 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006127
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006128 vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
6129 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006130
6131 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6132 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6133 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6134 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6135 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6136 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
6137 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006138 f_shutdown_helper(ho := true);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006139}
6140
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006141private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6142 template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
Vadim Yanitskiy2ef6a2f2020-10-08 23:17:32 +07006143 template (present) OCT1 dlci := ?,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006144 octetstring l3 := '0123456789'O)
6145runs on MSC_ConnHdlr {
Neels Hofmeyr43654812020-09-25 01:35:35 +02006146 /* The old lchan and conn should still be active. See that arbitrary L3
6147 * is still going through. */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006148 rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
Neels Hofmeyr43654812020-09-25 01:35:35 +02006149 var template PDU_BSSAP exp_data := {
6150 discriminator := '1'B,
6151 spare := '0000000'B,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006152 dlci := dlci,
6153 lengthIndicator := lengthof(l3),
Neels Hofmeyr43654812020-09-25 01:35:35 +02006154 pdu := {
6155 dtap := l3
6156 }
6157 };
6158 BSSAP.receive(exp_data);
6159 setverdict(pass);
6160}
6161
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006162private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6163 template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006164 template (value) OCT1 dlci := '00'O,
6165 octetstring l3 := '0123456789'O)
6166runs on MSC_ConnHdlr {
6167 BSSAP.send(PDU_BSSAP:{
6168 discriminator := '1'B,
6169 spare := '0000000'B,
6170 dlci := dlci,
6171 lengthIndicator := lengthof(l3),
6172 pdu := {
6173 dtap := l3
6174 }
6175 });
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006176 rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006177 setverdict(pass);
6178}
6179
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006180/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
6181 * simply never sends a BSSMAP Handover Command. */
6182private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006183 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006184
6185 var PDU_BSSAP ass_req := f_gen_ass_req();
6186 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6187 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6188 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6189 f_establish_fully(ass_req, exp_compl);
6190
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006191 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006192 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6193
6194 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6195
6196 /* osmo-bsc should time out 10 seconds after the handover started.
6197 * Let's give it a bit extra. */
6198 f_sleep(15.0);
6199
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006200 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006201 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006202 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006203}
6204testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
6205 var MSC_ConnHdlr vc_conn;
6206
6207 f_init(1, true);
6208 f_sleep(1.0);
6209
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006210 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006211
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006212 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
6213 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006214
6215 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6216 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6217 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6218 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6219 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6220 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6221 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006222 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006223}
6224
6225/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
6226 * RR Handover Failure. */
6227private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006228 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006229
6230 var PDU_BSSAP ass_req := f_gen_ass_req();
6231 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6232 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6233 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6234 f_establish_fully(ass_req, exp_compl);
6235
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006236 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006237 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6238
6239 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6240
6241 f_sleep(0.5);
6242 /* The MSC negotiates Handover Request and Handover Request Ack with
6243 * the other BSS and comes back with a BSSMAP Handover Command
6244 * containing an RR Handover Command coming from the target BSS... */
6245
6246 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6247 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6248 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6249 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6250 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6251
6252 /* expect the Handover Command to go out on RR */
6253 var RSL_Message rsl_ho_cmd
6254 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6255 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6256 var RSL_IE_Body rsl_ho_cmd_l3;
6257 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6258 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6259 setverdict(fail);
6260 } else {
6261 log("Found L3 Info: ", rsl_ho_cmd_l3);
6262 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6263 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6264 setverdict(fail);
6265 } else {
6266 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6267 setverdict(pass);
6268 }
6269 }
6270
6271 f_sleep(0.2);
6272 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
6273
6274 /* Should tell the MSC about the failure */
6275 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6276
6277 f_sleep(1.0);
6278
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006279 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006280 f_sleep(1.0);
6281
6282 setverdict(pass);
6283 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006284 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006285}
6286testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
6287 var MSC_ConnHdlr vc_conn;
6288
6289 f_init(1, true);
6290 f_sleep(1.0);
6291
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006292 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006293
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006294 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
6295 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006296
6297 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6298 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6299 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6300 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6301 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6302 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
6303 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006304 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006305}
6306
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006307/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
6308 * (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 +02006309 * and the lchan is released. */
6310private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006311 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006312
6313 var PDU_BSSAP ass_req := f_gen_ass_req();
6314 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6315 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6316 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6317 f_establish_fully(ass_req, exp_compl);
6318
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006319 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006320 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6321
6322 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6323
6324 f_sleep(0.5);
6325 /* The MSC negotiates Handover Request and Handover Request Ack with
6326 * the other BSS and comes back with a BSSMAP Handover Command
6327 * containing an RR Handover Command coming from the target BSS... */
6328
6329 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6330 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6331 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6332 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6333 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6334
6335 /* expect the Handover Command to go out on RR */
6336 var RSL_Message rsl_ho_cmd
6337 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6338 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6339 var RSL_IE_Body rsl_ho_cmd_l3;
6340 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6341 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6342 setverdict(fail);
6343 } else {
6344 log("Found L3 Info: ", rsl_ho_cmd_l3);
6345 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6346 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6347 setverdict(fail);
6348 } else {
6349 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6350 setverdict(pass);
6351 }
6352 }
6353
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006354 /* We get neither success nor failure report from the remote BSS. Eventually T8 times out and we run into 3GPP
6355 * TS 48.008 3.1.5.3.3 "Abnormal Conditions": Clear Request should go to the MSC, and RR should be released
6356 * after Clear Command */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006357
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006358 var PDU_BSSAP rx_clear_request;
Neels Hofmeyre1797aa2019-07-09 19:34:04 +02006359 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
6360 log("Got BSSMAP Clear Request");
6361 /* Instruct BSC to clear channel */
6362 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6363 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6364
6365 var MgcpCommand mgcp;
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006366 interleave {
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01006367 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
6368 log("Got Deact SACCH");
6369 }
Harald Welte924b6ea2019-02-04 01:05:34 +01006370 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
Neels Hofmeyr211169d2018-11-07 00:37:29 +01006371 log("Got RR Release");
6372 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02006373 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006374 log("Got RF Chan Rel");
6375 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02006376 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006377 }
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006378 }
6379
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006380 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006381 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006382 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006383
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006384 setverdict(pass);
6385 f_sleep(1.0);
6386}
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006387testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006388 var MSC_ConnHdlr vc_conn;
6389
6390 f_init(1, true);
6391 f_sleep(1.0);
6392
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006393 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006394
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006395 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006396 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006397
6398 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6399 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6400 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6401 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6402 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6403 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6404 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006405 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006406}
6407
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006408private 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 +01006409 var PDU_BSSAP rx_bssap;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006410 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6411 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6412 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6413 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6414 * before we get started. */
6415 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6416 f_rslem_register(0, new_chan_nr);
6417 g_chan_nr := new_chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06006418 var uint3_t expect_target_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006419 f_sleep(1.0);
6420
6421 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6422 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006423 var default as_media := activate(as_Media());
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006424
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01006425 var PDU_BSSAP ho_req := f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
6426 cell_id_source := g_pars.cell_id_source,
6427 oldToNewBSSIEs := oldToNewBSSIEs,
6428 enc := g_pars.encr);
6429 if (g_pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr) {
6430 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, ho_req));
6431 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6432 } else {
6433 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, omit));
6434 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6435 BSSAP.send(ho_req);
6436 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006437
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006438 alt {
6439 [] BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap {
6440 if (g_pars.expect_ho_fail) {
6441 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6442 "Expected Handover Request to fail, but got Handover Request Ack")
6443 }
6444 }
6445 [] BSSAP.receive(tr_BSSMAP_HandoverFailure) -> value rx_bssap {
6446 if (not g_pars.expect_ho_fail) {
6447 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6448 "Expected Handover Request to succeed, but got Handover Failure")
6449 }
6450 // TODO: evaluate correct cause value. But osmo-bsc doesn't seem to send meaningful causes yet!
6451 // For now just accept any cause.
6452 BSSAP.receive(tr_BSSMAP_ClearRequest);
6453 setverdict(pass);
6454 return;
6455 }
6456 }
6457
Oliver Smith7a8594a2023-02-13 14:30:49 +01006458 if (g_pars.expect_ho_fail_lchan_est) {
6459 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6460 setverdict(pass);
Oliver Smitha1cbec52023-02-21 12:44:12 +01006461
6462 /* When we let MGCP MDCX run into a timeout, it's still in the
6463 * queue and additionally after BSSAP HandoverFailure, two DLCX
Oliver Smith30eb8822023-03-06 12:31:53 +01006464 * get sent (for AoIP, for SCCPlite one DLCX). */
Oliver Smitha1cbec52023-02-21 12:44:12 +01006465 if (g_pars.ignore_mgw_mdcx) {
Oliver Smith30eb8822023-03-06 12:31:53 +01006466 if (g_pars.aoip) {
6467 MGCP.receive(tr_MDCX);
6468 MGCP.receive(tr_DLCX);
6469 MGCP.receive(tr_DLCX);
6470 } else {
6471 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_MDCX}));
6472 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_DLCX}));
6473 }
Oliver Smitha1cbec52023-02-21 12:44:12 +01006474 }
Oliver Smith7a8594a2023-02-13 14:30:49 +01006475 return;
6476 }
6477
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006478 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6479
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006480 /* we're sure that the channel activation is done now, verify the parameters in it */
6481 var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
6482 f_verify_encr_info(chan_act);
6483 f_chan_act_verify_tsc(chan_act, expect_target_tsc);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006484
Neels Hofmeyr46e16e52022-02-23 17:04:00 +01006485 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.codecList)) {
6486 if (not g_pars.aoip) {
6487 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6488 "handoverRequestAck: Expected no Speech Codec List (BSS Supported), because this is not AoIP");
6489 }
6490 /* TODO: check actual codecs? */
6491 } else {
6492 if (g_pars.aoip) {
6493 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6494 "handoverRequestAck: Expected Speech Codec List (BSS Supported), but none found");
6495 }
6496 }
6497
6498 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.speechCodec)) {
6499 if (not g_pars.aoip) {
6500 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6501 "handoverRequestAck: Expected no Speech Codec (Chosen), because this is not AoIP");
6502 }
6503 /* TODO: check actual codec? */
6504 } else {
6505 if (g_pars.aoip) {
6506 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6507 "handoverRequestAck: Expected Speech Codec (Chosen), but none found");
6508 }
6509 }
6510
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006511 var octetstring ho_command_str;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006512 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6513 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6514 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6515 log("L3 Info in HO Request Ack is ", ho_command);
6516
6517 var GsmArfcn arfcn;
6518 var RslChannelNr actual_new_chan_nr;
6519 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6520 actual_new_chan_nr, arfcn);
6521
6522 if (actual_new_chan_nr != new_chan_nr) {
6523 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6524 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6525 setverdict(fail);
6526 return;
6527 }
6528 log("Handover Command chan_nr is", actual_new_chan_nr);
6529
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006530 var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
6531 if (not match(got_tsc, expect_target_tsc)) {
6532 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6533 expect_target_tsc, " got ", got_tsc);
6534 mtc.stop;
6535 } else {
6536 log("handoverCommand: verified TSC = ", got_tsc);
6537 }
6538
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006539 /* Check the Cipher Mode Setting IE (shall be present during inter-RAT handover) */
6540 if (ispresent(ho_command.msgs.rrm.handoverCommand.cipherModeSetting)) {
6541 var CipherModeSetting_TV cms := ho_command.msgs.rrm.handoverCommand.cipherModeSetting;
6542 var template (present) CipherModeSetting_TV tr_cms := {
6543 sC := '0'B, /* no ciphering by default */
6544 algorithmIdentifier := '000'B,
6545 elementIdentifier := ?
6546 };
6547 if (ispresent(g_pars.encr) and g_pars.encr.enc_alg_expect != '01'O) { /* A5/N */
6548 tr_cms.algorithmIdentifier := f_cipher_mode_bssmap_to_rr(g_pars.encr.enc_alg_expect);
6549 tr_cms.sC := '1'B;
6550 }
6551 if (not match(cms, tr_cms)) {
6552 setverdict(fail, "RR Handover Command: unexpected Cipher Mode Setting IE: ",
6553 cms, ", expected: ", tr_cms);
6554 }
6555 } else {
6556 setverdict(fail, "RR Handover Command: Cipher Mode Setting IE is not present");
6557 }
6558
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006559 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6560 * tells the MS to handover to the new lchan. Here comes the new MS on
6561 * the new lchan with a Handover RACH: */
6562
6563 /* send handover detect */
6564
6565 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6566
6567 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6568
6569 /* send handover complete over the new channel */
6570
6571 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_HandoverComplete('00'O));
6572 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
6573 enc_PDU_ML3_MS_NW(l3_tx)));
6574
6575 BSSAP.receive(tr_BSSMAP_HandoverComplete);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006576 deactivate(as_media);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006577 setverdict(pass);
6578}
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006579
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006580private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006581 var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006582 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
6583 if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
6584 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006585 }
6586 if (g_pars.exp_fast_return) {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006587 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006588 } else {
6589 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006590 }
6591 f_ho_into_this_bsc(id, oldToNewBSSIEs);
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006592 if (g_pars.expect_ho_fail) {
6593 f_perform_clear_no_lchan();
Oliver Smith7a8594a2023-02-13 14:30:49 +01006594 } else if (g_pars.expect_ho_fail_lchan_est) {
6595 BSSAP.receive(tr_BSSMAP_ClearRequest);
6596 f_perform_clear_no_lchan();
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006597 } else {
6598 f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
6599 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006600 setverdict(pass);
6601}
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006602function 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 +01006603 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006604
6605 f_init(1, true);
6606 f_sleep(1.0);
6607
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006608 f_vty_encryption_a5(vty_a5_cfg);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006609 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006610
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006611 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6612 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006613
6614 vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
6615 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006616
6617 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006618 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006619 if (pars.expect_ho_fail) {
6620 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6621 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:failed");
Oliver Smith7a8594a2023-02-13 14:30:49 +01006622 } else if (pars.expect_ho_fail_lchan_est) {
6623 f_ctrs_bsc_and_bts_add(0, "handover:error");
6624 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006625 } else {
6626 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6627 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
6628 }
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006629 f_ctrs_bsc_and_bts_verify();
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006630
6631 f_vty_encryption_a5_reset();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006632}
6633
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006634testcase TC_ho_into_this_bsc() runs on test_CT {
6635 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6636 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006637 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006638}
6639
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006640function f_tc_ho_into_this_bsc_a5(TestHdlrEncrParams encr, charstring vty_a5_cfg := VTY_A5_DEFAULT,
6641 boolean expect_fail := false) runs on test_CT {
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006642 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006643 pars.encr := encr;
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006644 pars.expect_ho_fail := expect_fail;
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006645 f_tc_ho_into_this_bsc_main(pars, vty_a5_cfg);
Oliver Smith39f53072022-10-27 14:44:04 +02006646 f_shutdown_helper(ho := true);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006647}
6648
6649testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006650 f_tc_ho_into_this_bsc_a5(f_encr_params('01'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006651}
6652
6653testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006654 f_tc_ho_into_this_bsc_a5(f_encr_params('02'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006655}
6656
6657testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006658 f_tc_ho_into_this_bsc_a5(f_encr_params('08'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006659}
6660
6661testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006662 f_tc_ho_into_this_bsc_a5(f_encr_params('10'O, kc128 := true), "3 4");
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006663}
6664
Neels Hofmeyr1951be22022-02-16 16:21:07 +01006665/* Report: in inter-BSC incoming handover, when the MSC omits the Chosen Encryption Algorithm IE in the Handover Request
6666 * message, then osmo-bsc starts an unencrypted lchan even if A5/0 is not permitted.
6667 *
6668 * This test verifies that the Encryption Information is present in the Channel Activation when the Chosen Enc Alg is
6669 * omitted.
6670 *
6671 * Related: SYS#5839
6672 */
6673testcase TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() runs on test_CT {
6674 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O, alg_chosen := omit));
6675}
6676
6677testcase TC_ho_into_this_bsc_a5_1_3() runs on test_CT {
6678 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O));
6679}
6680
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006681/* Send a permitted algo mask that does not intersect with osmo-bsc.cfg */
6682testcase TC_ho_into_this_bsc_a5_mismatch() runs on test_CT {
6683 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '18'O, alg_expect := '10'O), "0 1",
6684 expect_fail := true); // 0x18 = A5/3 and A5/4
6685}
6686
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006687testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
6688 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6689 pars.host_aoip_tla := "::6";
6690 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006691 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006692}
6693
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006694/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006695 to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006696 channel is later released (RR CHannel Release), should trigger inclusion of
6697 IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
6698 neighbors. */
6699testcase TC_srvcc_eutran_to_geran() runs on test_CT {
6700 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6701 pars.last_used_eutran_plmn := '323454'O;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006702 pars.exp_fast_return := true;
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006703 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006704
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();
Oliver Smith39f53072022-10-27 14:44:04 +02006708 f_shutdown_helper(ho := true);
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006709}
6710
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006711/* Same as TC_srvcc_eutran_to_geran, but enables ciphering on the target channel. */
6712testcase TC_srvcc_eutran_to_geran_a5_3() runs on test_CT {
6713 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6714 pars.encr := f_encr_params('08'O); /* only A5/3 */
6715 pars.last_used_eutran_plmn := '323454'O;
6716 pars.exp_fast_return := true;
6717 f_tc_ho_into_this_bsc_main(pars);
6718
6719 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6720 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6721 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006722 f_shutdown_helper(ho := true);
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006723}
6724
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006725/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
6726 on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
6727 list when the channel is released. */
6728testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
6729 f_init_vty();
6730 f_vty_allow_srvcc_fast_return(true, 0)
6731
6732 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6733 pars.last_used_eutran_plmn := '323454'O;
6734 pars.exp_fast_return := false;
6735 f_tc_ho_into_this_bsc_main(pars);
6736 f_vty_allow_srvcc_fast_return(false, 0);
6737 f_shutdown_helper();
6738}
6739
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01006740/* Same as TC_srvcc_eutran_to_geran, but using SAI as serving Cell Identifier. SYS#5838 */
6741testcase TC_srvcc_eutran_to_geran_src_sai() runs on test_CT {
6742 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6743 pars.last_used_eutran_plmn := '323454'O;
6744 pars.cell_id_source := valueof(ts_CellID_SAI('123456'O, 300, 444));
6745 f_tc_ho_into_this_bsc_main(pars);
6746
6747 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6748 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6749 f_ctrs_bsc_and_bts_verify();
6750 f_shutdown_helper();
6751}
6752
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006753private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
6754 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
6755 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
6756 f_ho_into_this_bsc(id, oldToNewBSSIEs);
6757 f_ho_out_of_this_bsc(oldToNewBSSIEs);
6758 setverdict(pass);
6759}
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006760
6761private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
6762 runs on test_CT {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006763 var MSC_ConnHdlr vc_conn;
6764 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6765
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006766 f_init_vty();
6767 f_bts_0_cfg(BSCVTY,
6768 {"neighbor-list mode automatic",
6769 "handover 1",
6770 "handover algorithm 2",
6771 "handover2 window rxlev averaging 1",
6772 "no neighbors",
6773 "neighbor lac 99 arfcn 123 bsic any"});
6774 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6775
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006776 f_init(1, true);
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006777 if (disable_fast_return) {
6778 f_vty_allow_srvcc_fast_return(true, 0);
6779 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006780 f_sleep(1.0);
6781
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006782 f_ctrs_bsc_and_bts_handover_init();
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006783
6784 pars.last_used_eutran_plmn := '323454'O;
6785 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6786 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
6787
6788 vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
6789 vc_conn.done;
6790
6791 f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
6792 f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
6793 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
6794 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
6795 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
6796 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006797
6798 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
6799 f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006800 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006801
6802 if (disable_fast_return) {
6803 f_vty_allow_srvcc_fast_return(false, 0);
6804 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006805 f_shutdown_helper();
6806}
6807
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006808/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
6809 BSS Information" IE with "Last Used E-UTRAN PLMN Id".
6810 Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
6811 IE with "Last Used E-UTRAN PLMN Id" from first step. */
6812testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
6813 f_tc_srvcc_eutran_to_geran_ho_out_main(false);
6814}
6815/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
6816 * independently of fast-reture allowed/forbidden in local BTS */
6817testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
6818 f_tc_srvcc_eutran_to_geran_ho_out_main(true);
6819}
6820
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006821private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
6822 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6823 f_rslem_register(0, new_chan_nr);
6824 g_chan_nr := new_chan_nr;
6825 f_sleep(1.0);
6826
6827 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6828 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6829 activate(as_Media());
6830
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006831 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006832 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006833 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006834
6835 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6836
6837 var PDU_BSSAP rx_bssap;
6838 var octetstring ho_command_str;
6839
6840 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6841
6842 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6843 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6844 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6845 log("L3 Info in HO Request Ack is ", ho_command);
6846
6847 var GsmArfcn arfcn;
6848 var RslChannelNr actual_new_chan_nr;
6849 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6850 actual_new_chan_nr, arfcn);
6851
6852 if (actual_new_chan_nr != new_chan_nr) {
6853 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6854 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6855 setverdict(fail);
6856 return;
6857 }
6858 log("Handover Command chan_nr is", actual_new_chan_nr);
6859
Neels Hofmeyr61ca08d2019-05-06 23:52:22 +02006860 /* For deterministic test results, give some time for the MGW endpoint to be configured */
6861 f_sleep(1.0);
6862
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006863 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6864 * tells the MS to handover to the new lchan. In this case, the MS
6865 * reports a Handover Failure to the old BSS, which forwards a BSSMAP
6866 * Handover Failure to the MSC. The procedure according to 3GPP TS
6867 * 48.008 3.1.5.3.2 "Handover Failure" is then that the MSC sends a
6868 * BSSMAP Clear Command: */
6869
6870 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6871 var BssmapCause cause := enum2int(cause_val);
6872 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6873
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006874 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006875 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006876 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006877
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006878 setverdict(pass);
6879 f_sleep(1.0);
6880
6881 setverdict(pass);
6882}
6883testcase TC_ho_in_fail_msc_clears() runs on test_CT {
6884 var MSC_ConnHdlr vc_conn;
6885 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6886
6887 f_init(1, true);
6888 f_sleep(1.0);
6889
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006890 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006891
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006892 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6893 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006894
6895 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
6896 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006897
6898 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6899 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6900 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6901 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6902 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006903 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006904}
6905
6906private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
6907 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6908 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6909 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6910 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6911 * before we get started. */
6912 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6913 f_rslem_register(0, new_chan_nr);
6914 g_chan_nr := new_chan_nr;
6915 f_sleep(1.0);
6916
6917 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6918 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6919 activate(as_Media());
6920
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006921 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006922 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006923 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006924
6925 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6926
6927 var PDU_BSSAP rx_bssap;
6928 var octetstring ho_command_str;
6929
6930 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6931
6932 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6933 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6934 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6935 log("L3 Info in HO Request Ack is ", ho_command);
6936
6937 var GsmArfcn arfcn;
6938 var RslChannelNr actual_new_chan_nr;
6939 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6940 actual_new_chan_nr, arfcn);
6941
6942 if (actual_new_chan_nr != new_chan_nr) {
6943 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6944 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6945 setverdict(fail);
6946 return;
6947 }
6948 log("Handover Command chan_nr is", actual_new_chan_nr);
6949
6950 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6951 * tells the MS to handover to the new lchan. Here comes the new MS on
6952 * the new lchan with a Handover RACH: */
6953
6954 /* send handover detect */
6955
6956 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6957
6958 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6959
6960 /* The MSC chooses to clear the connection now, maybe we got the
6961 * Handover RACH on the new cell but the MS still signaled Handover
6962 * Failure to the old BSS? */
6963
6964 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6965 var BssmapCause cause := enum2int(cause_val);
6966 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6967
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006968 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006969 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006970 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006971
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006972 f_sleep(1.0);
6973}
6974testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
6975 var MSC_ConnHdlr vc_conn;
6976 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6977
6978 f_init(1, true);
6979 f_sleep(1.0);
6980
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006981 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006982
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006983 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6984 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006985
6986 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
6987 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006988
6989 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6990 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6991 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6992 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6993 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006994 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006995}
6996
6997/* The new BSS's lchan times out before the MSC decides that handover failed. */
6998private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
6999 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
7000 f_rslem_register(0, new_chan_nr);
7001 g_chan_nr := new_chan_nr;
7002 f_sleep(1.0);
7003
7004 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
7005 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01007006 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007007
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007008 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007009 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02007010 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007011
7012 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
7013
7014 var PDU_BSSAP rx_bssap;
7015 var octetstring ho_command_str;
7016
7017 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
7018
7019 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
7020 log("Received L3 Info in HO Request Ack: ", ho_command_str);
7021 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
7022 log("L3 Info in HO Request Ack is ", ho_command);
7023
7024 var GsmArfcn arfcn;
7025 var RslChannelNr actual_new_chan_nr;
7026 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
7027 actual_new_chan_nr, arfcn);
7028
7029 if (actual_new_chan_nr != new_chan_nr) {
7030 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
7031 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
7032 setverdict(fail);
7033 return;
7034 }
7035 log("Handover Command chan_nr is", actual_new_chan_nr);
7036
7037 /* Now the MSC forwards the RR Handover Command to the other BSC, which
7038 * tells the MS to handover to the new lchan. But the MS never shows up
7039 * on the new lchan. */
7040
7041 BSSAP.receive(tr_BSSMAP_HandoverFailure);
7042
7043 /* Did osmo-bsc also send a Clear Request? */
7044 timer T := 0.5;
7045 T.start;
7046 alt {
7047 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
7048 [] T.timeout { }
7049 }
7050
7051 /* MSC plays along with a Clear Command (no matter whether osmo-bsc
7052 * asked for it, this is a Handover Failure after all). */
7053
7054 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
7055 var BssmapCause cause := enum2int(cause_val);
7056 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7057
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007058 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007059 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007060 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007061
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007062 f_sleep(1.0);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007063}
7064testcase TC_ho_in_fail_no_detect() runs on test_CT {
7065 var MSC_ConnHdlr vc_conn;
7066 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7067
Oliver Smithd49f46d2023-03-08 12:23:13 +01007068 pars.fail_on_dlcx := false;
7069
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007070 f_init(1, true);
7071 f_sleep(1.0);
7072
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007073 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007074
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007075 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7076 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007077
7078 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect), pars);
7079 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007080
7081 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7082 f_ctrs_bsc_and_bts_add(0, "handover:error");
7083 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7084 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7085 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007086 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007087}
7088
7089/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
7090private function f_tc_ho_in_fail_no_detect2(charstring id) runs on MSC_ConnHdlr {
7091 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
7092 f_rslem_register(0, new_chan_nr);
7093 g_chan_nr := new_chan_nr;
7094 f_sleep(1.0);
7095
7096 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
7097 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01007098 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007099
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007100 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007101 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02007102 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007103
7104 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
7105
7106 var PDU_BSSAP rx_bssap;
7107 var octetstring ho_command_str;
7108
7109 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
7110
7111 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
7112 log("Received L3 Info in HO Request Ack: ", ho_command_str);
7113 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
7114 log("L3 Info in HO Request Ack is ", ho_command);
7115
7116 var GsmArfcn arfcn;
7117 var RslChannelNr actual_new_chan_nr;
7118 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
7119 actual_new_chan_nr, arfcn);
7120
7121 if (actual_new_chan_nr != new_chan_nr) {
7122 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
7123 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
7124 setverdict(fail);
7125 return;
7126 }
7127 log("Handover Command chan_nr is", actual_new_chan_nr);
7128
7129 /* Now the MSC forwards the RR Handover Command to the other BSC, which
7130 * tells the MS to handover to the new lchan. But the MS never shows up
7131 * on the new lchan. */
7132
7133 BSSAP.receive(tr_BSSMAP_HandoverFailure);
7134
7135 /* MSC plays dumb and sends no Clear Command */
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007136 var PDU_BSSAP rx_clear_request;
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02007137
7138 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request {
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007139 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
7140 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7141 };
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007142 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007143 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007144 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007145
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007146 f_sleep(1.0);
7147}
7148testcase TC_ho_in_fail_no_detect2() runs on test_CT {
7149 var MSC_ConnHdlr vc_conn;
7150 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7151
Oliver Smith735b47c2023-02-15 16:03:54 +01007152 pars.fail_on_dlcx := false;
7153
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007154 f_init(1, true);
7155 f_sleep(1.0);
7156
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007157 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007158
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007159 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7160 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007161
7162 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
7163 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007164
7165 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7166 f_ctrs_bsc_and_bts_add(0, "handover:error");
7167 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7168 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7169 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007170 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007171}
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01007172
Oliver Smith7a8594a2023-02-13 14:30:49 +01007173testcase TC_ho_in_fail_mgw_mdcx_timeout() runs on test_CT {
7174 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7175
7176 pars.ignore_mgw_mdcx := true;
7177 pars.expect_ho_fail_lchan_est := true;
7178
7179 f_tc_ho_into_this_bsc_main(pars);
7180 f_shutdown_helper(ho := true);
7181}
7182
Oliver Smith4eed06f2023-02-15 15:43:19 +01007183testcase TC_ho_in_fail_ipa_crcx_timeout() runs on test_CT {
7184 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7185
7186 pars.ignore_ipa_media := true;
7187 pars.expect_ho_fail_lchan_est := true;
7188 pars.fail_on_dlcx := false;
7189
7190 f_tc_ho_into_this_bsc_main(pars);
7191 f_shutdown_helper(ho := true);
7192}
7193
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007194/* An incoming inter-BSC HO can either issue the Handover Request message attached to the initial SCCP N-Connect (as in
7195 * the other tests we have so far), or the first CR can be "empty" with the BSSAP request following later. Test the
7196 * empty N-Connect case. */
7197testcase TC_ho_into_this_bsc_sccp_cr_without_bssap() runs on test_CT {
7198 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7199 pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr := false;
7200 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02007201 f_shutdown_helper(ho := true);
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007202}
7203
Neels Hofmeyr91401012019-07-11 00:42:35 +02007204type record of charstring Commands;
7205
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007206private function f_bts_0_cfg(TELNETasp_PT pt, Commands cmds := {})
Neels Hofmeyr91401012019-07-11 00:42:35 +02007207{
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007208 f_vty_enter_cfg_bts(pt, 0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007209 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007210 f_vty_transceive(pt, cmds[i]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007211 }
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007212 f_vty_transceive(pt, "end");
Neels Hofmeyr91401012019-07-11 00:42:35 +02007213}
7214
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01007215private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
7216{
7217 f_vty_enter_cfg_cs7_inst(pt, 0);
7218 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
7219 f_vty_transceive(pt, cmds[i]);
7220 }
7221 f_vty_transceive(pt, "end");
7222}
7223
Neels Hofmeyr91401012019-07-11 00:42:35 +02007224private function f_probe_for_handover(charstring log_label,
7225 charstring log_descr,
7226 charstring handover_vty_cmd,
7227 boolean expect_handover,
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007228 boolean is_inter_bsc_handover := false,
7229 template uint3_t expect_target_tsc := ?)
Neels Hofmeyr91401012019-07-11 00:42:35 +02007230runs on MSC_ConnHdlr
7231{
Neels Hofmeyrb3fc8982020-05-11 00:16:42 +02007232 /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
7233 * lchans to be established on bts 1 or bts 2. */
7234 f_rslem_suspend(RSL1_PROC);
7235 f_rslem_suspend(RSL2_PROC);
7236
Neels Hofmeyr91401012019-07-11 00:42:35 +02007237 var RSL_Message rsl;
7238
7239 var charstring log_msg := " (expecting handover)"
7240 if (not expect_handover) {
7241 log_msg := " (expecting NO handover)";
7242 }
7243 log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg);
7244 f_vty_transceive(BSCVTY, handover_vty_cmd);
7245
Neels Hofmeyr91401012019-07-11 00:42:35 +02007246 timer T := 2.0;
7247 T.start;
7248
7249 alt {
7250 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
7251 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
7252 log("Rx L3 from net: ", l3);
7253 if (ischosen(l3.msgs.rrm.handoverCommand)) {
7254 var RslChannelNr new_chan_nr;
7255 var GsmArfcn arfcn;
7256 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
7257 new_chan_nr, arfcn);
7258 log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
7259 log(l3.msgs.rrm.handoverCommand);
7260
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007261 /* Verify correct TSC in handoverCommand */
7262 var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
7263 if (not match(got_tsc, expect_target_tsc)) {
7264 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
7265 expect_target_tsc, " got ", got_tsc);
7266 mtc.stop;
7267 } else {
7268 log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
7269 expect_target_tsc, ")");
7270 }
7271
Neels Hofmeyr91401012019-07-11 00:42:35 +02007272 /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
7273 * matter on which BTS it really is, we're not going to follow through an entire handover
7274 * anyway. */
7275 f_rslem_register(0, new_chan_nr, RSL1_PROC);
7276 f_rslem_resume(RSL1_PROC);
7277 f_rslem_register(0, new_chan_nr, RSL2_PROC);
7278 f_rslem_resume(RSL2_PROC);
7279
7280 if (expect_handover and not is_inter_bsc_handover) {
7281 setverdict(pass);
7282 log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected.");
7283 } else {
7284 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. "
7285 & log_label & ": " & log_descr);
7286 }
7287
7288 log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
7289 /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with
7290 * Handover Failure. */
7291 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
7292
7293 /* target BTS is told to release lchan again; don't care which BTS nor what messages. */
7294 f_sleep(0.5);
7295 RSL1.clear;
7296 RSL2.clear;
7297 log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)");
7298 break;
7299 } else {
7300 repeat;
7301 }
7302 }
7303 [] BSSAP.receive(tr_BSSMAP_HandoverRequired) {
7304 if (expect_handover and is_inter_bsc_handover) {
7305 setverdict(pass);
7306 log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected.");
7307 } else {
7308 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. "
7309 & log_label & ": " & log_descr);
7310 }
7311
7312 log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)");
7313
7314 /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to
7315 * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required,
7316 * setting a short timeout and waiting is the only way. */
7317 log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out...");
7318 f_sleep(1.5);
7319 log("f_probe_for_handover(" & log_label & "): ...done");
7320
7321 break;
7322 }
7323 [] T.timeout {
7324 if (expect_handover) {
7325 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. "
7326 & log_label & ": " & log_descr);
7327 } else {
7328 setverdict(pass);
7329 log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected.");
7330 }
7331 log("f_probe_for_handover(" & log_label & "): done (got no Handover)");
7332 break;
7333 }
7334 }
7335
7336 f_rslem_resume(RSL1_PROC);
7337 f_rslem_resume(RSL2_PROC);
7338 f_sleep(3.0);
7339 RSL.clear;
7340
7341 log("f_probe_for_handover(" & log_label & "): done clearing");
7342}
7343
7344/* Test the effect of various neighbor configuration scenarios:
7345 *
7346 * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0.
7347 * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO.
7348 */
7349private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
7350 g_pars := f_gen_test_hdlr_pars();
7351 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
7352 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007353
7354 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
7355 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
7356
7357 /* Establish lchan at bts 0 */
7358 f_establish_fully(ass_cmd, exp_compl);
7359
7360 /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */
7361 f_vty_enter_cfg_network(BSCVTY);
7362 f_vty_transceive(BSCVTY, "timer T7 1");
7363 f_vty_transceive(BSCVTY, "end");
7364}
7365
7366private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
7367 f_tc_ho_neighbor_config_start();
7368
7369 /*
7370 * bts 0 ARFCN 871 BSIC 10
7371 * bts 1 ARFCN 871 BSIC 11
7372 * bts 2 ARFCN 871 BSIC 12
7373 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7374 */
7375
7376 log("f_tc_ho_neighbor_config: 1. No 'neighbor' config");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007377 f_bts_0_cfg(BSCVTY, {"no neighbors"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007378 f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
7379 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007380 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007381
7382 f_probe_for_handover("1.b", "HO to unknown cell does not start",
7383 "handover any to arfcn 13 bsic 39",
7384 false);
7385
7386 f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error",
7387 "handover any to arfcn 871 bsic 12",
7388 false);
7389
7390 f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
7391 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007392 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007393
7394 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007395}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007396testcase TC_ho_neighbor_config_1() runs on test_CT {
7397 var MSC_ConnHdlr vc_conn;
7398 f_init(3, true, guard_timeout := 60.0);
7399 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007400 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007401 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
7402 vc_conn.done;
7403
7404 /* f_tc_ho_neighbor_config_start() */
7405 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7406 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7407
7408 /* 1.a */
7409 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7410 * handover quickly by sending a Handover Failure message. */
7411 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7412 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7413 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7414 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007415 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7416 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007417
7418 /* 1.b */
7419 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7420 f_ctrs_bsc_and_bts_add(0, "handover:error");
7421
7422 /* 1.c */
7423 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7424 f_ctrs_bsc_and_bts_add(0, "handover:error");
7425
7426 /* 1.d */
7427 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7428 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7429 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7430 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007431 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7432 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007433
7434 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007435 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007436}
7437
Neels Hofmeyr91401012019-07-11 00:42:35 +02007438private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
7439 f_tc_ho_neighbor_config_start();
7440
7441 /*
7442 * bts 0 ARFCN 871 BSIC 10
7443 * bts 1 ARFCN 871 BSIC 11
7444 * bts 2 ARFCN 871 BSIC 12
7445 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7446 */
7447
7448 log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007449 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007450 f_sleep(0.5);
7451
7452 f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
7453 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007454 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007455
7456 f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
7457 "handover any to arfcn 871 bsic 12",
7458 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007459 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007460}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007461testcase TC_ho_neighbor_config_2() runs on test_CT {
7462 var MSC_ConnHdlr vc_conn;
7463 f_init(3, true, guard_timeout := 50.0);
7464 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007465 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007466 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
7467 vc_conn.done;
7468
7469 /* f_tc_ho_neighbor_config_start() */
7470 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7471 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7472
7473 /* 2.a */
7474 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7475 * handover quickly by sending a Handover Failure message. */
7476 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7477 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7478 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7479 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007480 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7481 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007482
7483 /* 2.b */
7484 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7485 f_ctrs_bsc_and_bts_add(0, "handover:error");
7486
7487 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007488 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007489}
7490
Neels Hofmeyr91401012019-07-11 00:42:35 +02007491private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
7492 f_tc_ho_neighbor_config_start();
7493
7494 /*
7495 * bts 0 ARFCN 871 BSIC 10
7496 * bts 1 ARFCN 871 BSIC 11
7497 * bts 2 ARFCN 871 BSIC 12
7498 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7499 */
7500
7501 log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007502 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007503 f_sleep(0.5);
7504
7505 f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor",
7506 "handover any to arfcn 871 bsic 11",
7507 false);
7508 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",
7509 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007510 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007511 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007512}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007513testcase TC_ho_neighbor_config_3() runs on test_CT {
7514 var MSC_ConnHdlr vc_conn;
7515 f_init(3, true, guard_timeout := 50.0);
7516 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007517 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007518 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
7519 vc_conn.done;
7520
7521 /* f_tc_ho_neighbor_config_start() */
7522 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7523 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7524
7525 /* 3.a */
7526 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7527 f_ctrs_bsc_and_bts_add(0, "handover:error");
7528
7529 /* 3.b */
7530 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7531 * handover quickly by sending a Handover Failure message. */
7532 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7533 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7534 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7535 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007536 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7537 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007538
7539 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007540 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007541}
7542
Neels Hofmeyr91401012019-07-11 00:42:35 +02007543private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
7544 f_tc_ho_neighbor_config_start();
7545
7546 /*
7547 * bts 0 ARFCN 871 BSIC 10
7548 * bts 1 ARFCN 871 BSIC 11
7549 * bts 2 ARFCN 871 BSIC 12
7550 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7551 */
7552
7553 log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007554 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007555 f_sleep(0.5);
7556
7557 f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor",
7558 "handover any to arfcn 871 bsic 11",
7559 false);
7560 f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor",
7561 "handover any to arfcn 871 bsic 12",
7562 false);
7563 f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
7564 "handover any to arfcn 123 bsic 45",
7565 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007566 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007567}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007568testcase TC_ho_neighbor_config_4() runs on test_CT {
7569 var MSC_ConnHdlr vc_conn;
7570 f_init(3, true, guard_timeout := 50.0);
7571 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007572 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007573 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
7574 vc_conn.done;
7575
7576 /* f_tc_ho_neighbor_config_start() */
7577 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7578 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7579
7580 /* 4.a */
7581 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7582 f_ctrs_bsc_and_bts_add(0, "handover:error");
7583
7584 /* 4.b */
7585 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7586 f_ctrs_bsc_and_bts_add(0, "handover:error");
7587
7588 /* 4.c */
7589 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7590 * handover quickly by timing out after the Handover Required message */
7591 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7592 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7593 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7594 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7595
7596 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007597 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007598}
7599
Neels Hofmeyr91401012019-07-11 00:42:35 +02007600private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
7601 f_tc_ho_neighbor_config_start();
7602
7603 /*
7604 * bts 0 ARFCN 871 BSIC 10
7605 * bts 1 ARFCN 871 BSIC 11
7606 * bts 2 ARFCN 871 BSIC 12
7607 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7608 */
7609
7610 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 +02007611 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007612 f_sleep(0.5);
7613
7614 f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
7615 "handover any to arfcn 871 bsic 12",
7616 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007617 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007618}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007619testcase TC_ho_neighbor_config_5() runs on test_CT {
7620 var MSC_ConnHdlr vc_conn;
7621 f_init(3, true);
7622 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007623 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007624 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
7625 vc_conn.done;
7626
7627 /* f_tc_ho_neighbor_config_start() */
7628 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7629 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7630
7631 /* 5 */
7632 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7633 * handover quickly by timing out after the Handover Required message */
7634 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7635 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7636 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7637 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
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_6(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: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:"
7654 & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007655 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007656 f_sleep(0.5);
7657
7658 f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
7659 "handover any to arfcn 871 bsic 12",
7660 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007661 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007662}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007663testcase TC_ho_neighbor_config_6() runs on test_CT {
7664 var MSC_ConnHdlr vc_conn;
7665 f_init(3, true);
7666 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007667 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007668 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
7669 vc_conn.done;
7670
7671 /* f_tc_ho_neighbor_config_start() */
7672 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7673 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7674
7675 /* 6.a */
7676 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7677 * handover quickly by timing out after the Handover Required message */
7678 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7679 f_ctrs_bsc_and_bts_add(0, "handover:error");
7680
7681 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007682 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007683}
7684
Neels Hofmeyr91401012019-07-11 00:42:35 +02007685private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
7686 f_tc_ho_neighbor_config_start();
7687
7688 /*
7689 * bts 0 ARFCN 871 BSIC 10
7690 * bts 1 ARFCN 871 BSIC 11
7691 * bts 2 ARFCN 871 BSIC 12
7692 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7693 */
7694
7695 log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:"
7696 & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007697 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007698 f_sleep(0.5);
7699
7700 f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
7701 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007702 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007703 f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
7704 "handover any to arfcn 123 bsic 45",
7705 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007706 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007707}
Neels Hofmeyr91401012019-07-11 00:42:35 +02007708testcase TC_ho_neighbor_config_7() runs on test_CT {
7709 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf2b88032020-06-16 00:35:04 +02007710 f_init(3, true, guard_timeout := 50.0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007711 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007712 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007713 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
7714 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007715
7716 /* f_tc_ho_neighbor_config_start() */
7717 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7718 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7719
7720 /* 7.a */
7721 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7722 * handover quickly by sending a Handover Failure message. */
7723 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7724 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7725 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7726 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007727 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7728 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007729
7730 /* 7.b */
7731 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7732 * handover quickly by timing out after the Handover Required message */
7733 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7734 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7735 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7736 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7737
7738 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007739 f_shutdown_helper(ho := true);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007740}
7741
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007742/* OS#3041: Open and close N connections in a normal fashion, and expect no
7743 * BSSMAP Reset just because of that. */
7744testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
7745 var default d;
7746 var integer i;
7747 var DchanTuple dt;
7748
7749 f_init();
7750
7751 /* Wait for initial BSSMAP Reset to pass */
7752 f_sleep(4.0);
7753
7754 d := activate(no_bssmap_reset());
7755
7756 /* Setup up a number of connections and RLSD them again from the MSC
7757 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7758 * Let's do it some more times for good measure. */
Harald Weltec3260d92018-06-11 17:48:16 +02007759 for (i := 0; i < 4; i := i+1) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007760 /* Since we're doing a lot of runs, give each one a fresh
7761 * T_guard from the top. */
7762 T_guard.start;
7763
7764 /* Setup a BSSAP connection and clear it right away. This is
7765 * the MSC telling the BSC about a planned release, it's not an
7766 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007767 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007768
7769 /* MSC disconnects (RLSD). */
7770 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
7771 }
7772
7773 /* In the buggy behavior, a timeout of 2 seconds happens between above
7774 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7775 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7776 f_sleep(4.0);
7777
7778 deactivate(d);
7779 f_shutdown_helper();
7780}
Harald Welte552620d2017-12-16 23:21:36 +01007781
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007782/* OS#3041: Open and close N connections in a normal fashion, and expect no
7783 * BSSMAP Reset just because of that. Invoke the release by a BSSMAP Clear from
7784 * the MSC. */
7785testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
7786 var default d;
7787 var integer i;
7788 var DchanTuple dt;
7789 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007790 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
7791 var BssmapCause cause := enum2int(cause_val);
7792
7793 f_init();
7794
7795 /* Wait for initial BSSMAP Reset to pass */
7796 f_sleep(4.0);
7797
7798 d := activate(no_bssmap_reset());
7799
7800 /* Setup up a number of connections and RLSD them again from the MSC
7801 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7802 * Let's do it some more times for good measure. */
7803 for (i := 0; i < 8; i := i+1) {
7804 /* Since we're doing a lot of runs, give each one a fresh
7805 * T_guard from the top. */
7806 T_guard.start;
7807
7808 /* Setup a BSSAP connection and clear it right away. This is
7809 * the MSC telling the BSC about a planned release, it's not an
7810 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007811 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007812
7813 /* Instruct BSC to clear channel */
7814 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7815
7816 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007817 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007818 }
7819
7820 /* In the buggy behavior, a timeout of 2 seconds happens between above
7821 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7822 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7823 f_sleep(4.0);
7824
7825 deactivate(d);
7826 f_shutdown_helper();
7827}
7828
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007829/* OS#3041: Open and close N connections in a normal fashion, and expect no
7830 * BSSMAP Reset just because of that. Close connections from the MS side with a
7831 * Release Ind on RSL. */
7832testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
7833 var default d;
7834 var integer i;
7835 var DchanTuple dt;
7836 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007837 var integer j;
7838
7839 f_init();
7840
7841 /* Wait for initial BSSMAP Reset to pass */
7842 f_sleep(4.0);
7843
7844 d := activate(no_bssmap_reset());
7845
7846 /* Setup up a number of connections and RLSD them again from the MSC
7847 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7848 * Let's do it some more times for good measure. */
7849 for (i := 0; i < 8; i := i+1) {
7850 /* Since we're doing a lot of runs, give each one a fresh
7851 * T_guard from the top. */
7852 T_guard.start;
7853
7854 /* Setup a BSSAP connection and clear it right away. This is
7855 * the MSC telling the BSC about a planned release, it's not an
7856 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007857 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007858
7859 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007860 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007861
7862 /* expect Clear Request on MSC side */
7863 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
7864
7865 /* Instruct BSC to clear channel */
7866 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
7867 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7868
7869 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007870 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007871 }
7872
7873 /* In the buggy behavior, a timeout of 2 seconds happens between above
7874 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7875 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7876 f_sleep(4.0);
7877
7878 deactivate(d);
7879 f_shutdown_helper();
7880}
7881
Harald Welte94e0c342018-04-07 11:33:23 +02007882/***********************************************************************
7883 * IPA style dynamic PDCH
7884 ***********************************************************************/
7885
7886private function f_dyn_ipa_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7887 template (omit) RSL_Cause nack := omit)
7888runs on test_CT {
7889 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7890 var RSL_Message rsl_unused;
7891 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7892 f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
7893 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007894 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007895 if (istemplatekind(nack, "omit")) {
7896 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007897 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007898 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007899 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007900 }
7901}
7902
7903private function f_dyn_ipa_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7904 template (omit) RSL_Cause nack := omit)
7905runs on test_CT {
7906 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7907 var RSL_Message rsl_unused;
7908 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7909 f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
7910 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007911 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_DEACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007912 if (istemplatekind(nack, "omit")) {
7913 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007914 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007915 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007916 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007917 }
7918}
7919
7920private function f_ts_dyn_mode_get(integer bts_nr, integer trx_nr, integer ts_nr)
7921runs on test_CT return charstring {
7922 var charstring cmd, resp;
7923 cmd := "show timeslot "&int2str(bts_nr)&" "&int2str(trx_nr)&" "&int2str(ts_nr);
Stefan Sperlingcff13562018-11-13 15:24:06 +01007924 return f_vty_transceive_match_regexp_retry(BSCVTY, cmd, "*\((*)\)*", 0, 4, 1.0);
Harald Welte94e0c342018-04-07 11:33:23 +02007925}
7926
7927private function f_ts_dyn_mode_assert(integer bts_nr, integer trx_nr, integer ts_nr,
7928 template charstring exp)
7929runs on test_CT {
7930 var charstring mode := f_ts_dyn_mode_get(bts_nr, trx_nr, ts_nr);
7931 if (not match(mode, exp)) {
7932 setverdict(fail, "Unexpected TS Mode: ", mode);
Daniel Willmannafce8662018-07-06 23:11:32 +02007933 mtc.stop;
Harald Welte94e0c342018-04-07 11:33:23 +02007934 }
7935}
7936
7937private function f_ts_set_chcomb(integer bts_nr, integer trx_nr, integer ts_nr, charstring chcomb)
7938runs on test_CT {
7939 f_vty_enter_cfg_ts(BSCVTY, bts_nr, trx_nr, ts_nr);
7940 f_vty_transceive(BSCVTY, "phys_chan_config " & chcomb);
7941 f_vty_transceive(BSCVTY, "end");
7942}
7943
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007944
7945private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
7946 var integer i;
7947 for (i := 0; i < 8; i := i + 1) {
7948 f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
7949 }
7950}
7951
Harald Welte94e0c342018-04-07 11:33:23 +02007952private const charstring TCHF_MODE := "TCH/F mode";
7953private const charstring TCHH_MODE := "TCH/H mode";
7954private const charstring PDCH_MODE := "PDCH mode";
7955private const charstring NONE_MODE := "NONE mode";
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007956private const charstring SDCCH8_MODE := "SDCCH8 mode";
Harald Welte94e0c342018-04-07 11:33:23 +02007957
7958/* Test IPA PDCH activation / deactivation triggered by VTY */
7959testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
7960 var RSL_Message rsl_unused;
7961
7962 /* change Timeslot 6 before f_init() starts RSL */
7963 f_init_vty();
7964 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7965 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7966
7967 f_init(1, false);
7968 f_sleep(1.0);
7969
7970 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7971
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007972 log("TCH/F_PDCH pchan starts out in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007973 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7974 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007975 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7976 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007977 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007978 log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007979 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7980
7981 /* De-activate it via VTY */
7982 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7983 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007984 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007985 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7986
7987 /* re-activate it via VTY */
7988 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn);
7989 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007990 log("TCH/F_PDCH pchan, PDCH ACT via VTY, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007991 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7992
7993 /* and finally de-activate it again */
7994 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7995 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007996 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007997 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7998
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007999 /* clean up config */
8000 f_ts_set_chcomb(0, 0, 6, "PDCH");
8001
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008002 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008003}
8004
8005/* Test IPA PDCH activation NACK */
8006testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
8007 var RSL_Message rsl_unused;
8008
8009 /* change Timeslot 6 before f_init() starts RSL */
8010 f_init_vty();
8011 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
8012 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8013
8014 f_init(1, false);
8015 f_sleep(1.0);
8016
8017 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
8018
8019 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
8020 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008021 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
8022 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02008023 f_sleep(1.0);
8024 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
8025
8026 /* De-activate it via VTY */
8027 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
8028 f_sleep(1.0);
8029 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
8030
8031 /* re-activate it via VTY, but fail that; check BSC still assumes TCH/F mode */
8032 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn, RSL_ERR_EQUIPMENT_FAIL);
8033 f_sleep(1.0);
8034 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
8035
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008036 /* clean up config */
8037 f_ts_set_chcomb(0, 0, 6, "PDCH");
8038
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008039 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008040}
8041
8042
8043/***********************************************************************
8044 * Osmocom style dynamic PDCH
8045 ***********************************************************************/
8046
8047private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
8048 template (omit) RSL_Cause nack := omit)
8049runs on test_CT {
8050 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
8051 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02008052 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02008053 /* FIXME: no VTY command to activate Osmocom PDCH !! */
8054 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008055 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT(chan_nr, ?));
Harald Welte94e0c342018-04-07 11:33:23 +02008056 if (istemplatekind(nack, "omit")) {
8057 /* respond with a related acknowledgement */
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 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008060 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02008061 }
8062}
8063
8064private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
8065 template (omit) RSL_Cause nack := omit)
8066runs on test_CT {
8067 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
8068 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02008069 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02008070 /* FIXME: no VTY command to activate Osmocom PDCH !! */
8071 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008072 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008073 if (istemplatekind(nack, "omit")) {
8074 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008075 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008076 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008077 //f_ipa_tx(ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02008078 }
8079}
8080
8081/* Test Osmocom dyn PDCH activation / deactivation triggered by VTY */
8082testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
8083 var RSL_Message rsl_unused;
8084
8085 /* change Timeslot 6 before f_init() starts RSL */
8086 f_init_vty();
8087 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8088 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8089
8090 f_init(1, false);
8091 f_sleep(1.0);
8092
8093 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8094
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008095 log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02008096 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8097 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008098 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008099
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008100 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02008101 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008102 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 +02008103 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
8104
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008105 /* clean up config */
8106 f_ts_set_chcomb(0, 0, 6, "PDCH");
8107
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008108 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008109}
8110
8111/* Test Osmocom dyn PDCH activation NACK behavior */
8112testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
8113 var RSL_Message rsl_unused;
8114
8115 /* change Timeslot 6 before f_init() starts RSL */
8116 f_init_vty();
8117 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8118 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8119
8120 f_init(1, false);
8121 f_sleep(1.0);
8122
8123 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8124
8125 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8126 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008127 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008128
8129 /* NACK this activation and expect the "show timeslot" mode still to be NONE */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008130 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte94e0c342018-04-07 11:33:23 +02008131 f_sleep(1.0);
8132 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8133
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008134 /* clean up config */
8135 f_ts_set_chcomb(0, 0, 6, "PDCH");
8136
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008137 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008138}
8139
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008140/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
8141testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
8142 var RSL_Message rsl_unused, rsl_msg;
8143 var DchanTuple dt;
8144 var BSSAP_N_CONNECT_ind rx_c_ind;
8145
8146 /* change Timeslot 6 before f_init() starts RSL */
8147 f_init_vty();
8148 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8149 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8150
8151 f_init(1, false);
8152 f_sleep(1.0);
8153
8154 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8155
8156 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8157 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8158 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008159 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008160
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008161 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008162 f_sleep(1.0);
8163 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8164 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8165
8166 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8167 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008168 var DchanTuples sdcch_cleanup := {};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008169 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008170 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008171 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008172 sdcch_cleanup := sdcch_cleanup & { dt };
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008173 }
8174
8175 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008176 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8177 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8178 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008179
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008180 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008181 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008182 dt.idx := {0, 0};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008183
8184 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008185 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8186 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008187 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
8188
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008189 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 +02008190 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8191 dt.sccp_conn_id := rx_c_ind.connectionId;
8192 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8193
8194 /* Instruct BSC to clear channel */
8195 var BssmapCause cause := 0;
8196 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008197 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008198
8199 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008200 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8201 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008202 f_sleep(1.0);
8203 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8204
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008205 /* Clean up SDCCH lchans */
8206 for (i := 0; i < lengthof(sdcch_cleanup); i := i + 1) {
8207 f_perform_clear_test_ct(sdcch_cleanup[i]);
8208 }
8209
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008210 /* clean up config */
8211 f_ts_set_chcomb(0, 0, 6, "PDCH");
8212
8213 f_shutdown_helper();
8214}
8215
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008216/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
8217testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
8218 var ASP_RSL_Unitdata rsl_ud;
8219 var integer i;
8220 var integer chreq_total, chreq_nochan;
8221
8222 f_init_vty();
8223 for (i := 1; i < 8; i := i + 1) {
8224 if (i == 2) {
8225 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8226 } else {
8227 f_ts_set_chcomb(0, 0, i, "PDCH");
8228 }
8229 }
8230 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8231
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008232 f_init(1, guard_timeout := 60.0);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008233
8234 /* The dyn TS want to activate PDCH mode, ACK that. */
8235 var RslChannelNr chan_nr;
8236 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008237 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
8238 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008239
8240 f_sleep(1.0);
8241
8242 /* Exhaust all dedicated SDCCH lchans.
8243 /* GSM 44.018 Table 9.1.8.2:
8244 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
8245 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008246 var DchanTuples chan_cleanup := {};
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008247 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008248 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 +02008249 }
8250
8251 /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008252 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 +02008253 /* Also occupy the seven other SDCCH of the dyn TS */
8254 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008255 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 +01008256 }
8257
8258 /* Clean up SDCCH lchans */
8259 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8260 f_perform_clear_test_ct(chan_cleanup[i]);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008261 }
8262
8263 /* clean up config */
8264 f_ts_reset_chcomb(0);
8265
8266 f_shutdown_helper();
8267}
8268
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008269/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
8270 SDCCH8 would end up in having no free TCH, then BSC should decide to activate
8271 it as TCH directly instead. SYS#5309. */
8272testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
8273 var RSL_Message rsl_unused, rsl_msg;
8274 var DchanTuple dt;
8275 var BSSAP_N_CONNECT_ind rx_c_ind;
8276 var integer i;
8277
8278 /* change Timeslot 6 before f_init() starts RSL */
8279 f_init_vty();
8280 for (i := 1; i < 8; i := i + 1) {
8281 if (i == 6) {
8282 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8283 } else {
8284 f_ts_set_chcomb(0, 0, i, "PDCH");
8285 }
8286 }
8287 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8288
8289 f_init(1, false);
8290 f_sleep(1.0);
8291
8292 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8293
8294 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8295 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8296 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008297 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008298
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008299 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008300 f_sleep(1.0);
8301 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8302 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8303
8304 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8305 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008306 var DchanTuples chan_cleanup := {};
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02008307 var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008308 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008309 dt := f_est_dchan(ra, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008310 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008311 }
8312
8313 /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008314 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
8315 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8316 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008317
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008318 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008319 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008320 dt.idx := {0, 0};
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008321
8322 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008323 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8324 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008325 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
8326
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008327 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 +02008328 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8329 dt.sccp_conn_id := rx_c_ind.connectionId;
8330 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8331
8332 /* Instruct BSC to clear channel */
8333 var BssmapCause cause := 0;
8334 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008335 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008336
8337 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008338 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8339 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008340 f_sleep(1.0);
8341 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8342
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008343 /* Clean up SDCCH lchans */
8344 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8345 f_perform_clear_test_ct(chan_cleanup[i]);
8346 }
8347
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008348 /* clean up config */
8349 f_ts_reset_chcomb(0);
8350 /* TODO: clean up other channels? */
8351
8352 f_shutdown_helper();
8353}
8354
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008355/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
8356testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
8357 var RSL_Message rsl_unused, rsl_msg;
8358 var DchanTuple dt;
8359 var BSSAP_N_CONNECT_ind rx_c_ind;
8360 var GsmRrMessage rr;
8361
8362 /* change Timeslot 6 before f_init() starts RSL */
8363 f_init_vty();
8364 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8365 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8366
8367 f_init(1, false);
8368 f_sleep(1.0);
8369
8370 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8371
8372 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8373 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8374 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008375 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008376
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008377 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008378 f_sleep(1.0);
8379 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8380 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8381
8382 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8383 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008384 var DchanTuples chan_cleanup := {};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008385 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008386 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008387 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008388 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008389 }
8390
8391 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008392 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8393 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8394 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008395
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008396 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008397 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008398 dt.idx := {0, 0};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008399
8400 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008401 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
8402 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008403 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
8404 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
8405 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
8406 }
8407
8408 /* FIXME? Currently the TS stays in state BORKEN: */
8409
8410 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008411 /* rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8412 * f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008413 * f_sleep(1.0);
8414 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
8415 */
8416
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008417 /* Clean up SDCCH lchans */
8418 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8419 f_perform_clear_test_ct(chan_cleanup[i]);
8420 }
8421
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008422 /* clean up config */
8423 f_ts_set_chcomb(0, 0, 6, "PDCH");
8424
8425 f_shutdown_helper();
8426}
8427
Stefan Sperling0796a822018-10-05 13:01:39 +02008428testcase TC_chopped_ipa_ping() runs on test_CT {
Stefan Sperling554123f2018-10-09 14:12:30 +02008429 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port, mp_bsc_ctrl_port};
Stefan Sperling0796a822018-10-05 13:01:39 +02008430 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8431 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8432 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008433 f_shutdown_helper();
Stefan Sperling0796a822018-10-05 13:01:39 +02008434}
8435
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008436testcase TC_chopped_ipa_payload() runs on test_CT {
8437 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port
8438 /* TODO: mp_bsc_ctrl_port does not work yet */};
8439 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8440 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8441 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008442 f_shutdown_helper();
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008443}
8444
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008445/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
8446 the BTS does autonomous MS power control loop */
8447testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
8448 var MSC_ConnHdlr vc_conn;
8449 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8450 //pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
8451 pars.exp_ms_power_params := true;
8452
8453 f_init(1, true);
8454 f_sleep(1.0);
8455 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
8456 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008457 f_shutdown_helper();
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008458}
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008459
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008460/* Verify activation and deactivation of the BCCH carrier power reduction mode */
8461testcase TC_c0_power_red_mode() runs on test_CT {
8462 f_init(1);
8463
8464 for (var integer red := 6; red >= 0; red := red - 2) {
8465 /* Configure BCCH carrier power reduction mode via the VTY */
8466 f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
8467
8468 /* Expect Osmocom specific BS Power Control message on the RSL */
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03008469 var template (present) RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008470 chan_nr := t_RslChanNr_BCCH(0),
8471 bs_power := tr_RSL_IE_BS_Power(red / 2));
8472 tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008473 var RSL_Message unused := f_exp_ipa_rx(tr_rsl_pdu);
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008474
8475 /* Additionally verify the applied value over the CTRL interface */
8476 var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
8477 if (cred != int2str(red)) {
8478 setverdict(fail, "Unexpected BCCH carrier power reduction value ",
8479 cred, " (expected ", red, ")");
8480 }
8481 }
8482
8483 f_shutdown_helper();
8484}
8485
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008486/***********************************************************************
8487 * MSC Pooling
8488 ***********************************************************************/
8489
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008490template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
Harald Weltebf397612021-01-14 20:39:46 +01008491 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 +02008492
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008493private 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 +02008494runs on MSC_ConnHdlr {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008495 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008496 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008497 f_logp(BSCVTY, "Got RSL RR Release");
8498 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008499 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008500 f_logp(BSCVTY, "Got RSL Deact SACCH");
8501 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008502 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008503 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008504 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8505 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008506 break;
8507 }
8508 }
8509}
8510
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008511private altstep as_mgcp_ack_all_dlcx() runs on MSC_ConnHdlr {
8512 var MgcpCommand mgcp_cmd;
Oliver Smithab7354b2023-05-08 11:34:30 +02008513 var template MgcpMessage msg_dlcx := {
8514 command := tr_DLCX
8515 }
8516 var MGCP_RecvFrom mrf;
8517
8518 [g_pars.aoip] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008519 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
8520 repeat;
8521 }
Oliver Smithab7354b2023-05-08 11:34:30 +02008522
8523 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
8524 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
8525 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
8526 }));
8527 repeat;
8528 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008529}
8530
8531private altstep as_rsl_ack_all_rel_req() runs on MSC_ConnHdlr {
8532 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
8533 [] RSL.receive(tr_RSL_REL_REQ(g_chan_nr, ?)) {
8534 RSL.send(ts_RSL_REL_CONF(g_chan_nr, main_dcch));
8535 repeat;
8536 }
8537}
8538
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008539friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
8540 template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02008541runs on MSC_ConnHdlr {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008542 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8543 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008544 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008545 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8546 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008547 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008548 f_logp(BSCVTY, "Got RSL RR Release");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008549 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008550 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008551 f_logp(BSCVTY, "Got RSL Deact SACCH");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008552 }
8553 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008554 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008555 /* Also drop the SCCP connection */
8556 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8557 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008558 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008559 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008560 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8561 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008562 }
8563 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008564 deactivate(ack_dlcx);
8565 deactivate(ack_rel_req);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008566}
8567
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01008568friend function f_perform_clear_no_rr_rel(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC)
8569runs on MSC_ConnHdlr {
8570 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8571 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
8572 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8573 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8574 interleave {
8575 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
8576 f_logp(BSCVTY, "Got RSL Deact SACCH");
8577 }
8578 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
8579 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8580 /* Also drop the SCCP connection */
8581 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8582 }
8583 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
8584 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
8585 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8586 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
8587 }
8588 }
8589 deactivate(ack_dlcx);
8590 deactivate(ack_rel_req);
8591}
8592
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01008593friend function f_perform_clear_no_lchan()
8594runs on MSC_ConnHdlr {
8595 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8596 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8597 BSSAP.receive(tr_BSSMAP_ClearComplete);
8598 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8599 /* Also drop the SCCP connection */
8600 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8601}
8602
Vadim Yanitskiy65d879d2022-06-23 18:15:39 +07008603friend function f_perform_clear_test_ct(DchanTuple dt)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008604 runs on test_CT
8605{
8606 /* Instruct BSC to clear channel */
8607 var BssmapCause cause := 0;
8608 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008609 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008610}
8611
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008612private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
8613 template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008614runs on MSC_ConnHdlr {
8615 timer T := 10.0;
8616 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
8617
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008618 f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008619 f_create_bssmap_exp(l3_enc);
8620
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008621 /* RSL_Emulation.f_chan_est() on rsl_pt:
8622 * This is basically code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008623 * RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
8624 */
8625 var RSL_Message rx_rsl;
8626 var GsmRrMessage rr;
8627
8628 /* request a channel to be established */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008629 rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008630 /* expect immediate assignment.
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008631 * Code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008632 * rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
8633 */
8634 timer Tt := 10.0;
8635
8636 /* request a channel to be established */
8637 Tt.start;
8638 alt {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008639 [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008640 Tt.stop;
8641 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008642 [] rsl_pt.receive {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008643 setverdict(fail, "Unexpected RSL message on DCHAN");
8644 mtc.stop;
8645 }
8646 [] Tt.timeout {
8647 setverdict(fail, "Timeout waiting for RSL on DCHAN");
8648 mtc.stop;
8649 }
8650 }
8651 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
8652 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008653 rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008654
8655
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008656 if (expect_bssmap_l3) {
8657 f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
8658 var template PDU_BSSAP exp_l3_compl;
8659 exp_l3_compl := tr_BSSMAP_ComplL3()
8660 if (g_pars.aoip == false) {
8661 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
8662 } else {
8663 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
8664 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008665
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008666 var PDU_BSSAP bssap;
8667 T.start;
8668 alt {
8669 [] BSSAP.receive(exp_l3_compl) -> value bssap {
8670 f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
8671 log("rx exp_l3_compl = ", bssap);
8672 }
8673 [] BSSAP.receive(tr_BSSMAP_ComplL3) {
8674 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
8675 }
8676 [] T.timeout {
8677 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
8678 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008679 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008680
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008681 /* start ciphering, if requested */
8682 if (ispresent(g_pars.encr)) {
8683 f_logp(BSCVTY, "start ciphering");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008684 f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008685 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008686 }
8687
8688 if (do_clear) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008689 f_perform_clear(rsl_pt, rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008690 }
8691 setverdict(pass);
8692 f_sleep(1.0);
8693}
8694
8695private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
8696 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8697 if (g_pars.mscpool.rsl_idx == 0) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008698 f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008699 } else if (g_pars.mscpool.rsl_idx == 1) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008700 f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008701 } else if (g_pars.mscpool.rsl_idx == 2) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008702 f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008703 }
8704}
8705
8706/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
8707private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
8708 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008709 f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
8710 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 +02008711 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)) );
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008712 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 +02008713}
8714testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
8715
8716 f_init(1, true);
8717 f_sleep(1.0);
8718 var MSC_ConnHdlr vc_conn;
8719 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008720
8721 f_ctrs_msc_init();
8722
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008723 vc_conn := f_start_handler(refers(f_tc_mscpool_L3Compl_on_1_msc), pars);
8724 vc_conn.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008725
8726 f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008727 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008728}
8729
8730/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
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_L3Complete_by_imsi_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_IMSI_LV('001010000000001'H)), '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:new");
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_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
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:new");
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;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008764 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008765 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:new");
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 0
8772 * (configured in osmo-bsc.cfg). */
8773/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8774 * just as well using only RSL. */
8775testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
8776
8777 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8778 f_sleep(1.0);
8779
8780 /* Control which MSC gets chosen next by the round-robin, otherwise
8781 * would be randomly affected by which other tests ran before this. */
8782 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8783
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008784 f_ctrs_msc_init();
8785
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008786 var MSC_ConnHdlr vc_conn1;
8787 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8788 pars1.mscpool.rsl_idx := 0;
8789 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8790 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8791 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008792 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008793
8794 var MSC_ConnHdlr vc_conn2;
8795 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8796 pars2.mscpool.rsl_idx := 1;
8797 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8798 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8799 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008800 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008801
8802 /* Test round-robin wrap to the first MSC */
8803 var MSC_ConnHdlr vc_conn3;
8804 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8805 pars3.mscpool.rsl_idx := 2;
8806 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8807 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8808 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008809 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008810 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008811}
8812
8813/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
8814 * (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
8815 * NULL-NRI setting is stronger than that. */
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_LU_by_tmsi_null_nri_1_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 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8833 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8834 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008835 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008836
8837 var MSC_ConnHdlr vc_conn2;
8838 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8839 pars2.mscpool.rsl_idx := 1;
8840 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8841 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8842 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008843 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008844
8845 /* Test round-robin wrap to the first MSC */
8846 var MSC_ConnHdlr vc_conn3;
8847 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8848 pars3.mscpool.rsl_idx := 2;
8849 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8850 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8851 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008852 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008853 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008854}
8855
8856/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
8857 * assigned to any MSC (configured in osmo-bsc.cfg). */
8858/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8859 * just as well using only RSL. */
8860testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test_CT {
8861
8862 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8863 f_sleep(1.0);
8864
8865 /* Control which MSC gets chosen next by the round-robin, otherwise
8866 * would be randomly affected by which other tests ran before this. */
8867 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8868
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008869 f_ctrs_msc_init();
8870
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008871 var MSC_ConnHdlr vc_conn1;
8872 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8873 pars1.mscpool.rsl_idx := 0;
8874 /* An NRI that is not assigned to any MSC */
8875 pars1.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(1023))));
8876 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8877 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008878 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008879
8880 var MSC_ConnHdlr vc_conn2;
8881 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8882 pars2.mscpool.rsl_idx := 1;
8883 /* An NRI that is not assigned to any MSC */
8884 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(768)), '00F110'O));
8885 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8886 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008887 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008888
8889 /* Test round-robin wrap to the first MSC */
8890 var MSC_ConnHdlr vc_conn3;
8891 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8892 pars3.mscpool.rsl_idx := 2;
8893 /* An NRI that is not assigned to any MSC */
8894 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, valueof(ts_MI_TMSI_NRI_LV(819))));
8895 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8896 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008897 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008898 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008899}
8900
8901/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
8902 * assigned to an MSC that is currently not connected (configured in osmo-bsc.cfg). */
8903/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8904 * just as well using only RSL. */
8905testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
8906
8907 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8908 f_sleep(1.0);
8909
8910 /* Control which MSC gets chosen next by the round-robin, otherwise
8911 * would be randomly affected by which other tests ran before this. */
8912 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8913
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008914 f_ctrs_msc_init();
8915
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008916 var MSC_ConnHdlr vc_conn1;
8917 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8918 pars1.mscpool.rsl_idx := 0;
8919 /* An NRI that is assigned to an unconnected MSC */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008920 pars1.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(512)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008921 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8922 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008923 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8924 f_ctrs_msc_add(0, "mscpool:subscr:new");
8925 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008926
8927 var MSC_ConnHdlr vc_conn2;
8928 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8929 pars2.mscpool.rsl_idx := 1;
8930 /* An NRI that is assigned to an unconnected MSC */
8931 pars2.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(767))));
8932 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8933 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008934 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8935 f_ctrs_msc_add(1, "mscpool:subscr:new");
8936 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008937
8938 /* Test round-robin wrap to the first MSC */
8939 var MSC_ConnHdlr vc_conn3;
8940 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8941 pars3.mscpool.rsl_idx := 2;
8942 /* An NRI that is assigned to an unconnected MSC */
8943 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(750)), '00F110'O));
8944 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8945 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008946 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8947 f_ctrs_msc_add(0, "mscpool:subscr:new");
8948 f_ctrs_msc_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008949 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008950}
8951
8952/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
8953 * osmo-bsc.cfg). */
8954/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8955 * just as well using only RSL. */
8956testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
8957
8958 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8959 f_sleep(1.0);
8960
8961 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
8962 * this is not using round-robin. */
8963 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8964
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008965 f_ctrs_msc_init();
8966
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008967 var MSC_ConnHdlr vc_conn1;
8968 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8969 pars1.mscpool.rsl_idx := 0;
8970 /* An NRI of the second MSC's range (256-511) */
8971 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(256))));
8972 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8973 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008974 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008975
8976 var MSC_ConnHdlr vc_conn2;
8977 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8978 pars2.mscpool.rsl_idx := 1;
8979 /* An NRI of the second MSC's range (256-511) */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008980 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(260)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008981 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8982 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008983 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008984
8985 var MSC_ConnHdlr vc_conn3;
8986 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8987 pars3.mscpool.rsl_idx := 2;
8988 /* An NRI of the second MSC's range (256-511) */
8989 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(511)), '00F110'O));
8990 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8991 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008992 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008993 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008994}
8995
8996/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
8997 * while a round-robin remains unaffected by that. */
8998/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8999 * just as well using only RSL. */
9000testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
9001
9002 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9003 f_sleep(1.0);
9004
9005 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
9006 * this is not using round-robin. */
9007 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
9008
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009009 f_ctrs_msc_init();
9010
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009011 var MSC_ConnHdlr vc_conn1;
9012 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 2);
9013 pars1.mscpool.rsl_idx := 0;
9014 /* An NRI of the third MSC's range (512-767) */
9015 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(512))));
9016 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9017 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009018 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009019
9020 var MSC_ConnHdlr vc_conn2;
9021 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9022 pars2.mscpool.rsl_idx := 1;
9023 /* An NRI of the third MSC's range (512-767) */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009024 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(678)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009025 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9026 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009027 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009028
9029 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
9030 var MSC_ConnHdlr vc_conn3;
9031 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
9032 pars3.mscpool.rsl_idx := 2;
9033 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000013'H)), '00F110'O));
9034 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9035 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009036 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009037 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009038}
9039
9040/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
9041/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
9042 * just as well using only RSL. */
9043testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
9044
9045 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9046 f_sleep(1.0);
9047
9048 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
9049 * instead, and hits msc 0. */
9050 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9051
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009052 f_ctrs_msc_init();
9053
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009054 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-bsc.cfg */
9055 var MSC_ConnHdlr vc_conn1;
9056 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9057 pars1.mscpool.rsl_idx := 0;
9058 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(260)), '99F999'O));
9059 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9060 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009061 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009062
9063 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
9064 var MSC_ConnHdlr vc_conn2;
9065 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9066 pars2.mscpool.rsl_idx := 1;
9067 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(555)), '00F110'O));
9068 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9069 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009070 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009071 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009072}
9073
9074/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
9075 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9076private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
9077 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9078 //cid_list := { cIl_allInBSS := ''O };
9079 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9080 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9081 var BSSAP_N_UNITDATA_req paging;
9082 var hexstring imsi := '001010000000123'H;
9083
9084 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9085
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009086 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009087 valueof(ts_BSSMAP_Paging(imsi, cid_list, omit, bssmap_chneed))));
9088 BSSAP.send(paging);
9089
9090 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9091 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9092 * channel number is picked here. */
9093 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9094 f_rslem_register(0, new_chan_nr);
9095 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(imsi)));
9096 f_rslem_unregister(0, new_chan_nr);
9097
9098 /* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
9099 * causes this Paging Response to go to the first MSC (bssap_idx := 0). */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009100 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV(imsi)) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009101 f_sleep(1.0);
9102}
9103testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
9104 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9105 f_sleep(1.0);
9106
9107 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9108 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9109 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
9110
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009111 f_ctrs_msc_init();
9112
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009113 var MSC_ConnHdlr vc_conn1;
9114 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9115 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009116 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9117 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009118 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
9119 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009120 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009121 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009122}
9123
9124/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
9125 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9126private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
9127 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9128 //cid_list := { cIl_allInBSS := ''O };
9129 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9130 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9131 var integer nri_v := 300; /* <-- second MSC's NRI */
Harald Weltebf397612021-01-14 20:39:46 +01009132 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009133 var BSSAP_N_UNITDATA_req paging;
9134
9135 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9136
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009137 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009138 valueof(ts_BSSMAP_Paging('001010000000011'H, cid_list, tmsi, bssmap_chneed))));
9139 BSSAP.send(paging);
9140
9141 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9142 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9143 * channel number is picked here. */
9144 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9145 f_rslem_register(0, new_chan_nr);
9146 RSL.receive(tr_RSL_PAGING_CMD(t_MI_TMSI(tmsi)));
9147 f_rslem_unregister(0, new_chan_nr);
9148
9149 /* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
9150 * third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
9151 * the first MSC (bssap_idx := 0). */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009152 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_TMSI_NRI_LV(nri_v)) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009153 f_sleep(1.0);
9154}
9155testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
9156 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9157 f_sleep(1.0);
9158
9159 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9160 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9161 f_vty_transceive(BSCVTY, "mscpool roundrobin next 2");
9162
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009163 f_ctrs_msc_init();
9164
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009165 var MSC_ConnHdlr vc_conn1;
9166 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9167 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009168 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9169 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009170 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
9171 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009172 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009173 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009174}
9175
9176/* For round-robin, skip an MSC that has 'no allow-attach' set. */
9177/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
9178 * just as well using only RSL. */
9179testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
9180
9181 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9182 f_sleep(1.0);
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});
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009185
9186 /* 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 var MSC_ConnHdlr vc_conn1;
9193 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9194 pars1.mscpool.rsl_idx := 0;
9195 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9196 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9197 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009198 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009199
9200 var MSC_ConnHdlr vc_conn2;
9201 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9202 pars2.mscpool.rsl_idx := 1;
9203 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9204 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9205 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009206 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009207
9208 var MSC_ConnHdlr vc_conn3;
9209 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
9210 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009211 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009212 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9213 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009214 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009215 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009216}
9217
9218/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
9219 * TMSI NRI. */
9220testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
9221
9222 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9223 f_sleep(1.0);
9224
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009225 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9226 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
9227
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009228 /* Control which MSC gets chosen next by the round-robin, otherwise
9229 * would be randomly affected by which other tests ran before this. */
9230 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9231
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009232 f_ctrs_msc_init();
9233
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009234 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
9235 var MSC_ConnHdlr vc_conn1;
9236 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
9237 pars1.mscpool.rsl_idx := 0;
9238 /* An NRI of the second MSC's range (256-511) */
9239 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_TMSI_NRI_LV(260))));
9240 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9241 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009242 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009243
9244 var MSC_ConnHdlr vc_conn2;
9245 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9246 pars2.mscpool.rsl_idx := 1;
9247 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9248 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9249 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009250 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009251
9252 var MSC_ConnHdlr vc_conn3;
9253 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 2);
9254 pars3.mscpool.rsl_idx := 2;
9255 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000003'H))));
9256 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9257 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009258 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009259 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009260}
9261
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009262/* When an MSC point-code gets an SCCP N-PCSTATE saying it is unreachable, immediately mark the MSC as unusable. */
9263testcase TC_mscpool_sccp_n_pcstate_detaches_msc() runs on test_CT {
9264
9265 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
9266 f_sleep(1.0);
9267
9268 /* Control which MSC gets chosen next by the round-robin, otherwise
9269 * would be randomly affected by which other tests ran before this. */
9270 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9271
9272 f_ctrs_msc_init();
9273
9274 var MSC_ConnHdlr vc_conn1;
9275 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9276 pars1.mscpool.rsl_idx := 0;
9277 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9278 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9279 vc_conn1.done;
9280 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9281
9282 var MSC_ConnHdlr vc_conn2;
9283 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
9284 pars2.mscpool.rsl_idx := 1;
9285 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9286 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9287 vc_conn2.done;
9288 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9289
9290 f_logp(BSCVTY, "disconnecting msc0");
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009291 f_bssap_idx_disconnect(0);
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009292
9293 /* Now round-robin would wrap to the first MSC, but since the first MSC is disconnected, it wraps around to msc
9294 * 2 again. */
9295 var MSC_ConnHdlr vc_conn3;
9296 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
9297 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009298 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009299 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9300 vc_conn3.done;
9301 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9302 f_shutdown_helper();
9303}
9304
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009305/* When an MSC point-code gets an SCCP N-PCSTATE saying it is now reachable, immediately trigger RESET and bring up the
9306 * MSC. */
9307testcase TC_mscpool_sccp_n_pcstate_attaches_msc() runs on test_CT {
9308
9309 f_init(nr_bts := 3, handler_mode := true, nr_msc := 1);
9310 f_sleep(1.0);
9311
9312 /* Control which MSC gets chosen next by the round-robin, otherwise
9313 * would be randomly affected by which other tests ran before this. */
9314 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9315
9316 f_ctrs_msc_init();
9317
9318 /* There is only one MSC, round robin stays on msc0 */
9319 var MSC_ConnHdlr vc_conn1;
9320 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9321 pars1.mscpool.rsl_idx := 0;
9322 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('0010100230000001'H)), '00F110'O));
9323 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9324 vc_conn1.done;
9325 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9326
9327 var MSC_ConnHdlr vc_conn2;
9328 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9329 pars2.mscpool.rsl_idx := 1;
9330 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010023000002'H))));
9331 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9332 vc_conn2.done;
9333 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9334
9335 f_logp(BSCVTY, "connecting msc1");
9336 f_vty_msc_allow_attach(BSCVTY, { true, true });
9337 f_bssap_idx_init(1);
9338 f_sleep(1.0);
9339
9340 /* This time round-robin wraps to the second MSC, because it is now online. */
9341 var MSC_ConnHdlr vc_conn4;
9342 var TestHdlrParams pars4 := f_gen_test_hdlr_pars(bssap_idx := 1);
9343 pars4.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009344 pars4.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010023000003'H)));
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009345 vc_conn4 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars4);
9346 vc_conn4.done;
9347 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9348
9349 f_shutdown_helper();
9350}
9351
Philipp Maier783681c2020-07-16 16:47:06 +02009352/* Allow/Deny emergency calls globally via VTY */
9353private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
9354 f_vty_enter_cfg_msc(BSCVTY, 0);
9355 if (allow) {
9356 f_vty_transceive(BSCVTY, "allow-emergency allow");
9357 } else {
9358 f_vty_transceive(BSCVTY, "allow-emergency deny");
9359 }
9360 f_vty_transceive(BSCVTY, "exit");
9361 f_vty_transceive(BSCVTY, "exit");
9362}
9363
9364/* Allow/Deny emergency calls per BTS via VTY */
9365private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
9366 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9367 if (allow) {
9368 f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
9369 } else {
9370 f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
9371 }
9372 f_vty_transceive(BSCVTY, "exit");
9373 f_vty_transceive(BSCVTY, "exit");
Neels Hofmeyrb6ed80c2020-10-12 22:52:39 +00009374 f_vty_transceive(BSCVTY, "exit");
Philipp Maier783681c2020-07-16 16:47:06 +02009375}
9376
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02009377/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
9378private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
9379 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9380 if (allow) {
9381 f_vty_transceive(BSCVTY, "srvcc fast-return allow");
9382 } else {
9383 f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
9384 }
9385 f_vty_transceive(BSCVTY, "exit");
9386 f_vty_transceive(BSCVTY, "exit");
9387 f_vty_transceive(BSCVTY, "exit");
9388}
9389
Pau Espin Pedrol14475352021-07-22 15:48:16 +02009390/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
9391private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
9392 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9393 if (allow) {
9394 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
9395 } else {
9396 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
9397 }
9398 f_vty_transceive(BSCVTY, "exit");
9399 f_vty_transceive(BSCVTY, "exit");
9400 f_vty_transceive(BSCVTY, "exit");
9401}
9402
Pau Espin Pedrol35609792023-01-03 16:56:59 +01009403/* Begin assignment procedure and send an EMERGENCY SETUP (RR) */
Philipp Maier783681c2020-07-16 16:47:06 +02009404private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
9405 var PDU_ML3_MS_NW emerg_setup;
9406 var octetstring emerg_setup_enc;
9407 var RSL_Message emerg_setup_data_ind;
9408
9409 f_establish_fully(omit, omit);
9410
9411 emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
9412 emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
9413 emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
9414
9415 RSL.send(emerg_setup_data_ind);
9416}
9417
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009418/* expect EmergencySetup on BSSAP after calling f_assignment_emerg_setup() */
9419private function f_assignment_emerg_setup_exp_bssap()
9420runs on MSC_ConnHdlr {
Philipp Maier783681c2020-07-16 16:47:06 +02009421 var PDU_BSSAP emerg_setup_data_ind_bssap;
9422 var PDU_ML3_MS_NW emerg_setup;
9423 timer T := 3.0;
9424
Philipp Maier783681c2020-07-16 16:47:06 +02009425 T.start;
9426 alt {
9427 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
9428 emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
9429 if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
9430 setverdict(fail, "no emergency setup");
9431 }
9432 }
9433 [] BSSAP.receive {
9434 setverdict(fail, "unexpected BSSAP message!");
9435 }
9436 [] T.timeout {
9437 setverdict(fail, "timout waiting for EMERGENCY SETUP!");
9438 }
9439 }
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009440}
9441
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009442private function f_assignment_emerg_setup_voice()
9443runs on MSC_ConnHdlr {
9444 /* Go on with voice call assignment */
9445 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
9446 var PDU_BSSAP ass_cmd := f_gen_ass_req();
9447
9448 /* Below speechOrDataIndicator and codecList are copied from an emergency call captured during tests.
9449 * They seem a bit weird (AMR-WB, and the order differ between speechId_DataIndicator and the codecList), but
9450 * seems a good idea to see how osmo-bsc reacts to this. */
9451 ass_cmd.pdu.bssmap.assignmentRequest.channelType := {
9452 elementIdentifier := '0B'O, /* overwritten */
9453 lengthIndicator := 0, /* overwritten */
9454 speechOrDataIndicator := '0001'B, /* speech */
9455 spare1_4 := '0000'B,
9456 channelRateAndType := ChRate_TCHForH_Fpref,
9457 speechId_DataIndicator := 'c2918105'O
9458 };
9459 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({
9460 ts_CodecHR, ts_CodecAMR_WB, ts_CodecEFR, ts_CodecFR}));
9461
9462 f_rslem_dchan_queue_enable();
9463
9464 var ExpectCriteria mgcpcrit := {
9465 connid := omit,
9466 endpoint := omit,
9467 transid := omit
9468 };
9469 f_create_mgcp_expect(mgcpcrit);
9470
9471 BSSAP.send(ass_cmd);
9472
9473 var AssignmentState st := valueof(ts_AssignmentStateInit);
Oliver Smithce2dd692023-04-17 10:25:50 +02009474 st.rtp_stream := true;
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009475 st.is_assignment := false;
9476 alt {
9477 [] as_modify(st);
9478 [] as_Media();
9479 [st.modify_done] BSSAP.receive(exp_compl) {
9480 setverdict(pass);
9481 }
9482 }
9483
9484 /* Voice call carries on ... */
9485 f_sleep(2.0);
9486}
9487
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009488/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
9489 * CALLS are permitted by the BSC config. */
9490private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
9491
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009492 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
9493 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
9494 * another lchan. */
9495 g_pars.ra := f_rnd_ra_emerg();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009496 f_assignment_emerg_setup();
9497 f_assignment_emerg_setup_exp_bssap();
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009498 f_assignment_emerg_setup_voice();
Philipp Maier783681c2020-07-16 16:47:06 +02009499
9500 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009501 f_perform_clear();
Philipp Maier783681c2020-07-16 16:47:06 +02009502}
9503
9504/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
9505 * forbidden by the BSC config. */
9506private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
9507 var PDU_BSSAP emerg_setup_data_ind_bssap;
9508 timer T := 3.0;
9509
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009510 f_assignment_emerg_setup();
Philipp Maier783681c2020-07-16 16:47:06 +02009511
9512 T.start;
9513 alt {
9514 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
9515 setverdict(pass);
9516 }
9517 [] RSL.receive {
9518 setverdict(fail, "unexpected RSL message!");
9519 }
9520 [] T.timeout {
9521 setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
9522 }
9523 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009524 BSSAP.receive(tr_BSSMAP_ClearRequest);
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01009525 f_perform_clear_no_rr_rel();
Philipp Maier783681c2020-07-16 16:47:06 +02009526}
9527
9528/* EMERGENCY CALL situation #1, allowed globally and by BTS */
9529testcase TC_assignment_emerg_setup_allow() runs on test_CT {
9530 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9531 var MSC_ConnHdlr vc_conn;
9532
9533 f_init(1, true);
9534 f_sleep(1.0);
9535
9536 f_vty_allow_emerg_msc(true);
9537 f_vty_allow_emerg_bts(true, 0);
9538 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9539 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009540 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009541}
9542
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +01009543/* Test MO emergency call using MobileIdentity=IMEI (possible for emergency
9544 * calls from phones without SIM card).
9545 * 3GPP TS 24.008 section 10.5.1.4, OS#5849 */
9546testcase TC_assignment_emerg_setup_allow_imei() runs on test_CT {
9547 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9548 var MSC_ConnHdlr vc_conn;
9549
9550 /* Remove IMSI set by f_gen_test_hdlr_pars(), then IMEI will be used to place the call */
9551 pars.imsi := omit;
9552
9553 f_init(1, true);
9554 f_sleep(1.0);
9555
9556 f_vty_allow_emerg_msc(true);
9557 f_vty_allow_emerg_bts(true, 0);
9558 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9559 vc_conn.done;
9560 f_shutdown_helper();
9561}
9562
Philipp Maier783681c2020-07-16 16:47:06 +02009563/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
9564testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
9565 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9566 var MSC_ConnHdlr vc_conn;
9567
9568 f_init(1, true);
9569 f_sleep(1.0);
9570
9571 f_vty_allow_emerg_msc(false);
9572 f_vty_allow_emerg_bts(true, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009573 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx): */
9574 pars.ra := f_rnd_ra_emerg();
Philipp Maier783681c2020-07-16 16:47:06 +02009575 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9576 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009577 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009578}
9579
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009580/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS.
9581 * The RACH req (and hence CHAN RQD) indicate other than emergency call.
9582 * Hence BSC only learns about it being an emergency call later during call setup.
9583 * If interested in the ra="emergency call" + deny bts policy case,
9584 * see TC_chan_rqd_emerg_deny.
9585 */
Philipp Maier783681c2020-07-16 16:47:06 +02009586testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
9587 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9588 var MSC_ConnHdlr vc_conn;
9589
9590 /* Note: This simulates a spec violation by the MS, correct MS
9591 * implementations would not try to establish an emergency call because
9592 * the system information tells in advance that emergency calls are
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009593 * not allowed */
Philipp Maier783681c2020-07-16 16:47:06 +02009594
9595 f_init(1, true);
9596 f_sleep(1.0);
9597
9598 f_vty_allow_emerg_msc(true);
9599 f_vty_allow_emerg_bts(false, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009600 /* Note: Here we implicitly leave default g_pars.ra which is different than "emergency call" */
Philipp Maier783681c2020-07-16 16:47:06 +02009601 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9602 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009603 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009604}
9605
Philipp Maier82812002020-08-13 18:48:27 +02009606/* Test what happens when an emergency call arrives while all TCH channels are
9607 * busy, the BSC is expected to terminate one call in favor of the incoming
9608 * emergency call */
9609testcase TC_emerg_premption() runs on test_CT {
9610 var ASP_RSL_Unitdata rsl_ud;
9611 var integer i;
9612 var integer chreq_total, chreq_nochan;
9613 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009614 var octetstring l3_payload := gen_l3_valid_payload();
Philipp Maier82812002020-08-13 18:48:27 +02009615
9616 f_init(1);
9617 f_sleep(1.0);
9618
9619 f_vty_allow_emerg_msc(true);
9620 f_vty_allow_emerg_bts(true, 0);
9621
9622 /* Fill up all channels on the BTS */
9623 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
9624 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
9625 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 +02009626 f_chreq_act_ack('33'O, i);
Philipp Maier82812002020-08-13 18:48:27 +02009627 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009628 IPA_RSL[0][0].clear;
Philipp Maier82812002020-08-13 18:48:27 +02009629 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
9630 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
9631
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009632 /* Send EST IND for the first TCH, so we get to test the RR release cause */
9633 var RslChannelNr first_tch := valueof(t_RslChanNr_Bm(1));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009634 f_ipa_tx(ts_RSL_EST_IND(first_tch, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009635
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009636 /* Accept BSSAP conn, so we get to test the Clear Request cause */
9637 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009638 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009639 var integer sccp_conn_id := rx_c_ind.connectionId;
9640 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
9641
Philipp Maier82812002020-08-13 18:48:27 +02009642 /* Send Channel request for emegergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009643 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier82812002020-08-13 18:48:27 +02009644
9645 /* Expect the BSC to release one (the first) TCH/F on the BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009646 f_expect_chan_rel(first_tch, expect_rr_chan_rel := true, expect_rll_rel_req := false,
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009647 expect_rr_cause := GSM48_RR_CAUSE_PREMPTIVE_REL);
Philipp Maier82812002020-08-13 18:48:27 +02009648
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009649 /* Also expect a BSSMAP Clear Request with PREEMPTION */
9650 var BSSAP_N_DATA_ind rx_clear_req;
9651 const myBSSMAP_Cause preemption := GSM0808_CAUSE_PREEMPTION;
9652 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_clear_req;
9653 log("XXX ", rx_clear_req);
9654 if (rx_clear_req.userData.pdu.bssmap.clearRequest.cause.causeValue != int2bit(enum2int(preemption), 7)) {
9655 setverdict(fail, "BSSMAP Clear Request: expected cause PREEMPTION");
9656 }
9657
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009658 /* Expect the BSC to send activate/assign the channel for the emergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009659 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009660 if (first_tch != rx_rsl.ies[0].body.chan_nr) {
9661 setverdict(fail, "different TCH lchan activated than expected");
9662 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009663 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(first_tch, 33));
9664 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Philipp Maier104f4c02020-09-11 18:12:18 +02009665
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009666 /* complete the BSSMAP Clear to satisfy the conn leak check */
9667 BSSAP.send(ts_BSSAP_DATA_req(sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(preemption))));
9668 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearComplete)) {
9669 BSSAP.send(ts_BSSAP_DISC_req(sccp_conn_id, 0));
9670 }
9671
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009672 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009673}
9674
9675/* Hopping parameters per a timeslot */
Vadim Yanitskiybc6654a2020-09-13 01:27:40 +07009676private type record length(0..64) of GsmArfcn ArfcnList;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009677private type record FHParamsTs {
9678 boolean enabled,
9679 uint6_t hsn,
9680 uint6_t maio,
9681 ArfcnList ma
9682};
9683
9684/* Hopping parameters per a transceiver */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009685private type record FHParamsTrx {
Philipp Maier798d8952021-10-19 14:43:19 +02009686 GsmBandArfcn arfcn,
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009687 FHParamsTs ts[8]
9688};
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009689
9690/* Randomly generate the hopping parameters for the given timeslot numbers */
9691private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
9692runs on test_CT return FHParamsTrx {
9693 var FHParamsTrx fhp;
9694
Philipp Maier798d8952021-10-19 14:43:19 +02009695 /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
9696 * fall in the GSM900 band. */
9697 fhp.arfcn.arfcn := f_rnd_int(3);
9698 fhp.arfcn.pcs := false;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009699
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009700 for (var integer tn := 0; tn < 8; tn := tn + 1) {
9701 if (not match(tn, tr_tn)) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009702 fhp.ts[tn].enabled := false;
9703 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009704 continue;
9705 }
9706
9707 /* Random HSN / MAIO values: 0..63 */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009708 fhp.ts[tn].hsn := f_rnd_int(64);
9709 fhp.ts[tn].maio := f_rnd_int(64);
9710 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009711
9712 /* Random Mobile Allocation (hopping channels) */
9713 var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
9714 var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
9715 for (var integer i := 1; i <= ma_len; i := i + 1) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009716 fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009717 }
9718
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009719 fhp.ts[tn].enabled := true;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009720 }
9721
9722 log("f_TC_fh_params_gen(): ", fhp);
9723 return fhp;
9724}
9725
9726/* Make sure that the given Channel Description IE matches the hopping configuration */
9727private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
9728{
9729 var template (present) ChannelDescription tr_cd;
9730 var template (present) MaioHsn tr_maio_hsn;
9731 var uint3_t tn := cd.chan_nr.tn;
9732
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009733 if (fhp.ts[tn].enabled) {
9734 tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009735 tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
9736 } else {
Philipp Maier798d8952021-10-19 14:43:19 +02009737 tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009738 }
9739
9740 if (not match(cd, tr_cd)) {
9741 setverdict(fail, "Channel Description IE does not match: ",
9742 cd, " vs expected ", tr_cd);
9743 }
9744}
9745
9746/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
9747private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
9748 in MobileAllocationLV ma)
9749{
9750 var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
9751
9752 if (not match(ma, tr_ma)) {
9753 setverdict(fail, "Mobile Allocation IE does not match (tn := ",
9754 tn, "): ", ma, " vs expected: ", tr_ma);
9755 } else {
9756 setverdict(pass);
9757 }
9758}
9759
9760private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
9761 in MobileAllocationLV ma)
9762return template MobileAllocationLV {
9763 /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009764 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009765 return { len := 0, ma := ''B };
9766 }
9767
9768 var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
9769 var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
9770 var bitstring ma_mask := ''B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009771
9772 /* Compose the full bit-mask (all channels, up to 1024 entries) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009773 for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
9774 for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
9775 if (full_mask[fhp.ts[i].ma[j]] == '1'B)
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009776 { continue; }
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009777 full_mask[fhp.ts[i].ma[j]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009778 }
9779 }
9780
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009781 /* Take ARFCN of the TRX itself into account */
Philipp Maier798d8952021-10-19 14:43:19 +02009782 full_mask[fhp.arfcn.arfcn] := '1'B;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009783
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009784 /* Compose a bit-mask for the given timeslot number */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009785 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9786 slot_mask[fhp.ts[tn].ma[i]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009787 }
9788
9789 /* Finally, compose the Mobile Allocation bit-mask */
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009790 for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009791 if (full_mask[i] != '1'B)
9792 { continue; }
9793
9794 /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
9795 if (slot_mask[i] == '1'B) {
9796 ma_mask := ma_mask & '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009797 } else {
9798 ma_mask := ma_mask & '0'B;
9799 }
9800 }
9801
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009802 /* ARFCN 0 (if present) goes to the last position of the bit-mask */
9803 if (full_mask[0] == '1'B) {
9804 /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
9805 if (slot_mask[0] == '1'B) {
9806 ma_mask := ma_mask & '1'B;
9807 } else {
9808 ma_mask := ma_mask & '0'B;
9809 }
9810 }
9811
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009812 /* Ensure that ma_mask is octet-aligned */
Vadim Yanitskiy2aa02522020-09-06 14:05:23 +07009813 var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009814 ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
9815
9816 return { len := ma_mask_len, ma := ma_mask };
9817}
9818
Philipp Maier798d8952021-10-19 14:43:19 +02009819/* Configure the appropriate band for a given arfcn, exc */
9820private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
9821{
9822 var charstring band;
9823 var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
9824
9825 select (arfcn_) {
9826 case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
9827 case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
9828 case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
9829 case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
9830 case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
9831 case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
9832 case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
9833 case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
9834 case else { return; }
9835 }
9836
9837 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9838 f_vty_transceive(BSCVTY, "band " & band);
9839 f_vty_transceive(BSCVTY, "end");
9840}
9841
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009842/* Configure the hopping parameters in accordance with the given record */
9843private function f_TC_fh_params_set(in FHParamsTrx fhp,
9844 uint8_t bts_nr := 0,
9845 uint8_t trx_nr := 0)
9846runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009847
9848 f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
9849
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009850 /* Enter the configuration node for the given BTS/TRX numbers */
9851 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9852
Philipp Maier798d8952021-10-19 14:43:19 +02009853 f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009854
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009855 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009856 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9857
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009858 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009859 f_vty_transceive(BSCVTY, "hopping enabled 0");
9860 f_vty_transceive(BSCVTY, "exit"); /* go back */
9861 continue;
9862 }
9863
9864 /* Configure HSN / MAIO values */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009865 f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
9866 f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009867
9868 /* Configure the Mobile Allocation (hopping channels) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009869 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9870 f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009871 }
9872
9873 f_vty_transceive(BSCVTY, "hopping enabled 1");
9874 f_vty_transceive(BSCVTY, "exit"); /* go back */
9875 }
9876
9877 f_vty_transceive(BSCVTY, "end");
9878}
9879
9880/* Disable frequency hopping on all timeslots */
9881private function f_TC_fh_params_unset(in FHParamsTrx fhp,
9882 uint8_t bts_nr := 0,
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009883 uint8_t trx_nr := 0,
Philipp Maier798d8952021-10-19 14:43:19 +02009884 GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009885runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009886
9887 f_TC_set_band_by_arfcn(bts_nr, arfcn);
9888
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009889 /* Enter the configuration node for the given BTS/TRX numbers */
9890 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9891
Philipp Maier798d8952021-10-19 14:43:19 +02009892 f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009893
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009894 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009895 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9896
9897 /* Delete all ARFCNs from the Mobile Allocation (if any) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009898 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9899 f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009900 }
9901
9902 f_vty_transceive(BSCVTY, "hopping enabled 0");
9903 f_vty_transceive(BSCVTY, "exit"); /* go back */
9904 }
9905
9906 f_vty_transceive(BSCVTY, "end");
9907 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9908}
9909
9910/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
9911 * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
9912testcase TC_fh_params_chan_activ() runs on test_CT {
9913 var FHParamsTrx fhp := f_TC_fh_params_gen();
9914 var RSL_Message rsl_msg;
9915 var RSL_IE_Body ie;
9916
9917 f_init_vty();
9918
9919 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9920 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9921
9922 f_init(1);
9923
9924 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9925 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009926 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9927 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009928
9929 /* Make sure that Channel Identification IE is present */
9930 if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
9931 setverdict(fail, "RSL Channel Identification IE is absent");
9932 continue;
9933 }
9934
9935 /* Make sure that hopping parameters (HSN/MAIO) match */
9936 f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
9937
9938 /* "Mobile Allocation shall be included but empty" - let's check this */
9939 if (ie.chan_ident.ma.v.len != 0) {
9940 setverdict(fail, "Mobile Allocation IE is not empty: ",
9941 ie.chan_ident.ma, ", despite it shall be");
9942 continue;
9943 }
9944 }
9945
9946 /* Disable frequency hopping */
9947 f_TC_fh_params_unset(fhp);
9948
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009949 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009950}
9951
9952/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
9953testcase TC_fh_params_imm_ass() runs on test_CT {
9954 var FHParamsTrx fhp := f_TC_fh_params_gen();
9955 var RSL_Message rsl_msg;
9956 var RSL_IE_Body ie;
9957
9958 f_init_vty();
9959
9960 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9961 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9962
9963 f_init(1);
9964
9965 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9966 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009967 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9968 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009969
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009970 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9971 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009972
9973 /* Make sure that Full Immediate Assign Info IE is present */
9974 if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
9975 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
9976 continue;
9977 }
9978
9979 /* Decode the actual Immediate Assignment message */
9980 var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
9981 if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
9982 setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
9983 continue;
9984 }
9985
9986 /* Make sure that hopping parameters (HSN/MAIO) match */
9987 f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
9988
9989 /* Make sure that the Mobile Allocation IE matches */
9990 f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
9991 rr_msg.payload.imm_ass.mobile_allocation);
9992 }
9993
9994 /* Disable frequency hopping */
9995 f_TC_fh_params_unset(fhp);
Philipp Maier82812002020-08-13 18:48:27 +02009996
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009997 f_shutdown_helper();
Philipp Maier82812002020-08-13 18:48:27 +02009998}
9999
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010000/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
10001testcase TC_fh_params_assignment_cmd() runs on test_CT {
10002 var FHParamsTrx fhp := f_TC_fh_params_gen();
10003 var RSL_Message rsl_msg;
10004 var RSL_IE_Body ie;
10005
10006 f_init_vty();
10007
10008 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
10009 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10010
10011 f_init(1);
10012
10013 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020010014 vc_MGCP[0].stop;
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010015
10016 var template PDU_BSSAP ass_cmd := f_gen_ass_req();
10017 ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
10018
10019 /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
10020 * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
10021 for (var integer i := 0; i < 3; i := i + 1) {
10022 /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010010023 var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010024
10025 /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
10026 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010027 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010028
10029 /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010030 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
10031 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010032
10033 /* Make sure that L3 Information IE is present */
10034 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
10035 setverdict(fail, "RSL L3 Information IE is absent");
10036 continue;
10037 }
10038
10039 /* Decode the L3 message and make sure it is (RR) Assignment Command */
10040 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
10041 if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
10042 setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
10043 continue;
10044 }
10045
10046 /* Make sure that hopping parameters (HSN/MAIO) match */
10047 var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
10048 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10049
10050 /* Make sure that Cell Channel Description IE is present if FH is enabled */
10051 if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
Vadim Yanitskiy38d069d2020-09-02 17:18:57 +070010052 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010053 continue;
10054 }
10055
10056 /* Make sure that the Mobile Allocation IE matches (if present) */
10057 var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
10058 if (chan_desc.h and ma_present) {
10059 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10060 l3_msg.payload.ass_cmd.mobile_allocation.v);
10061 } else if (chan_desc.h and not ma_present) {
10062 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10063 continue;
10064 } else if (not chan_desc.h and ma_present) {
10065 setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
10066 continue;
10067 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010068
10069 f_perform_clear_test_ct(dt);
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010070 }
10071
10072 /* Give the IUT some time to release all channels */
10073 f_sleep(3.0);
10074
10075 /* Disable frequency hopping */
10076 f_TC_fh_params_unset(fhp);
10077
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010078 f_shutdown_helper();
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010079}
10080
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010081/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
10082private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
10083runs on test_CT {
10084 var RSL_Message rsl_msg;
10085 var RSL_IE_Body ie;
10086 var DchanTuple dt;
10087
10088 /* Establish a dedicated channel, so we can trigger handover */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010010089 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyc18ff472021-11-18 20:15:37 +030010090 f_sleep(0.5);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010091
10092 /* Trigger handover from BTS0 to BTS1 */
10093 f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
10094 f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
10095
10096 /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010097 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx := {1, 0});
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010098
10099 /* ACKnowledge channel activation and expect (RR) Handover Command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010100 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33), idx := {1, 0});
10101 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010102
10103 /* Make sure that L3 Information IE is present */
10104 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
10105 setverdict(fail, "RSL L3 Information IE is absent");
10106 return;
10107 }
10108
10109 /* Decode the L3 message and make sure it is (RR) Handover Command */
10110 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
10111 if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
10112 setverdict(fail, "Failed to match Handover Command: ", l3_msg);
10113 return;
10114 }
10115
10116 /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
10117 var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
10118 if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
10119 setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
10120 return;
10121 }
10122
10123 /* Make sure that hopping parameters (HSN/MAIO) match */
10124 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10125
10126 /* Make sure that Cell Channel Description IE is present */
10127 if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
10128 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
10129 return;
10130 }
10131
10132 /* Make sure that the Mobile Allocation (after time) IE is present and matches */
10133 var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
10134 if (ma_present) {
10135 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10136 l3_msg.payload.ho_cmd.mobile_allocation.v);
10137 } else {
10138 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10139 return;
10140 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010141
10142 f_perform_clear_test_ct(dt);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010143}
10144testcase TC_fh_params_handover_cmd() runs on test_CT {
10145 var FHParamsTrx fhp := f_TC_fh_params_gen();
10146
10147 f_init_vty();
10148
10149 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
10150 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
10151
10152 f_vty_transceive(BSCVTY, "timeslot 0");
10153 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10154 f_vty_transceive(BSCVTY, "exit"); /* go back */
10155
10156 f_vty_transceive(BSCVTY, "timeslot 1");
10157 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
10158 f_vty_transceive(BSCVTY, "end"); /* we're done */
10159
10160 f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
10161 f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
10162
10163 f_init(2);
10164
10165 f_TC_fh_params_handover_cmd(fhp);
10166
10167 /* Disable frequency hopping on BTS1 */
10168 f_TC_fh_params_unset(fhp, 1);
10169
10170 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
10171 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
10172
10173 f_vty_transceive(BSCVTY, "timeslot 0");
10174 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
10175 f_vty_transceive(BSCVTY, "exit"); /* go back */
10176
10177 f_vty_transceive(BSCVTY, "timeslot 1");
10178 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10179 f_vty_transceive(BSCVTY, "end"); /* we're done */
10180
10181 f_shutdown_helper();
10182}
10183
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010184/* Verify the hopping parameters in System Information Type 4 */
10185testcase TC_fh_params_si4_cbch() runs on test_CT {
10186 var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
10187 var ASP_RSL_Unitdata rx_rsl_ud;
10188 timer T := 5.0;
10189
10190 f_init_vty();
10191
10192 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
10193 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10194
10195 f_vty_transceive(BSCVTY, "timeslot 0");
10196 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10197 f_vty_transceive(BSCVTY, "exit"); /* go back */
10198
10199 f_vty_transceive(BSCVTY, "timeslot 1");
10200 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
10201 f_vty_transceive(BSCVTY, "end"); /* we're done */
10202
10203 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
10204 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10205
10206 f_init(1);
10207
10208 T.start;
10209 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010210 [] 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 +070010211 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
10212 var SystemInformation si := dec_SystemInformation(ie.other.payload);
10213
10214 /* Make sure that what we decoded is System Information Type 4 */
10215 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
10216 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
10217 repeat;
10218 }
10219
10220 /* Make sure that CBCH Channel Description IE is present */
10221 if (not ispresent(si.payload.si4.cbch_chan_desc)) {
10222 setverdict(fail, "CBCH Channel Description IE is absent");
10223 break;
10224 }
10225
10226 /* Finally, check the hopping parameters (HSN, MAIO) */
10227 var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
10228 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10229
10230 /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
10231 * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
10232 if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
10233 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10234 break;
10235 } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
10236 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10237 si.payload.si4.cbch_mobile_alloc.v);
10238 }
10239 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010240 [] IPA_RSL[0][0].receive { repeat; }
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010241 [] T.timeout {
10242 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
10243 }
10244 }
10245
10246 /* Disable frequency hopping */
10247 f_TC_fh_params_unset(fhp);
10248
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010249 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010250 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10251
10252 f_vty_transceive(BSCVTY, "timeslot 0");
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010253 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010254 f_vty_transceive(BSCVTY, "exit"); /* go back */
10255
10256 f_vty_transceive(BSCVTY, "timeslot 1");
10257 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10258 f_vty_transceive(BSCVTY, "end"); /* we're done */
10259
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010260 f_shutdown_helper();
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010261}
10262
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010263template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
10264 := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
10265
10266private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
10267 template (present) BSSLAP_PDU expect_bsslap)
10268{
10269 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
10270 if (not match(bsslap, expect_bsslap)) {
10271 log("EXPECTING BSSLAP: ", expect_bsslap);
10272 log("GOT BSSLAP: ", bsslap);
10273 setverdict(fail, "BSSLAP is not as expected");
10274 mtc.stop;
10275 }
10276 setverdict(pass);
10277}
10278
10279/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
10280const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
10281
10282private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
10283 var PDU_BSSAP_LE rx_bsslap;
10284 BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
10285 f_match_bsslap(rx_bsslap, expect_rx_bsslap);
10286}
10287
10288/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10289 * Request on Lb interface. Either with or without the SMLC doing a BSSLAP TA Request. */
10290private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
10291 f_sleep(1.0);
10292
10293 f_establish_fully(omit, omit);
10294 f_bssap_le_register_imsi(g_pars.imsi, omit);
10295
10296 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10297 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10298
10299 var PDU_BSSAP_LE plr;
10300 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10301
10302 if (not do_ta_request) {
10303 /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
10304 var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
10305 if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
10306 log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
10307 log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
10308 setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
10309 mtc.stop;
10310 }
10311 var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
10312 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
10313 if (not match(bsslap, expect_ta_layer3)) {
10314 log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
10315 log("GOT BSSLAP: ", bsslap);
10316 setverdict(fail, "BSSLAP is not as expected");
10317 mtc.stop;
10318 }
10319 /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
10320 * has no need to request the TA from the BSC and directly responds. */
10321 } else {
10322 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10323 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10324 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10325 }
10326
10327 /* SMLC got the TA from the BSC, now responds with geo information data. */
10328 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10329 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10330 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10331
10332 /* The LCS was using an active A-interface conn. It should still remain active after this. */
10333 f_mo_l3_transceive();
10334
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010335 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010336
10337 f_sleep(2.0);
10338 setverdict(pass);
10339}
10340
10341/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10342 * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
10343private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
10344 f_lcs_loc_req_for_active_ms(false);
10345}
10346testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
10347 var MSC_ConnHdlr vc_conn;
10348 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10349
10350 f_init(1, true);
10351 f_sleep(1.0);
10352 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
10353 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010354 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010355}
10356
10357/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10358 * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
10359private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
10360 f_lcs_loc_req_for_active_ms(true);
10361}
10362testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
10363 var MSC_ConnHdlr vc_conn;
10364 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10365
10366 f_init(1, true);
10367 f_sleep(1.0);
10368 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
10369 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010370 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010371}
10372
10373/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
10374 * conn without an active lchan. */
10375private function f_clear_A_conn() runs on MSC_ConnHdlr
10376{
10377 var BssmapCause cause := 0;
10378 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10379 BSSAP.receive(tr_BSSMAP_ClearComplete);
10380 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10381
10382 timer no_more_bssap := 5.0;
10383 no_more_bssap.start;
10384 alt {
10385 [] no_more_bssap.timeout { break; }
10386 [] BSSAP.receive(tr_BSSAP_BSSMAP) {
10387 setverdict(fail, "Expected no more BSSAP after Clear Complete");
10388 mtc.stop;
10389 }
10390 }
10391 setverdict(pass);
10392}
10393
10394/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
10395 * for LCS, for cases where there is only an A conn without an active lchan. */
10396private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
10397{
10398 f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
10399
10400 /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
10401 * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
10402 * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
10403 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10404 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10405 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10406
10407 /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
10408 f_clear_A_conn();
10409 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10410 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10411}
10412
10413/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10414 * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
10415 */
10416private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
10417 f_sleep(1.0);
10418
10419 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10420 f_bssap_le_register_imsi(g_pars.imsi, omit);
10421
10422 /* Register to receive the Paging Command */
10423 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10424 g_chan_nr := new_chan_nr;
10425 f_rslem_register(0, g_chan_nr);
10426
10427 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10428 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10429 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10430 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10431
10432 var PDU_BSSAP_LE plr;
10433 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10434
10435 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10436 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10437
10438 /* OsmoBSC needs to Page */
10439 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
10440 f_logp(BSCVTY, "got Paging Command");
10441
10442 /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
10443 * the MSC, and releases the lchan directly. */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +020010444 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 +020010445 f_expect_lchan_rel(RSL, RSL_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010446
10447 /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
10448
10449 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10450
10451 /* SMLC got the TA from the BSC, now responds with geo information data. */
10452 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10453 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10454
10455 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10456
10457 /* The lchan is gone, the A-interface conn was created for the LCS only.
10458 * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
10459 f_verify_active_A_conn_and_clear();
10460
10461 f_sleep(2.0);
10462 setverdict(pass);
10463}
10464testcase TC_lcs_loc_req_for_idle_ms() runs on test_CT {
10465 var MSC_ConnHdlr vc_conn;
10466 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10467
10468 f_init(1, true);
10469 f_sleep(1.0);
10470
10471 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10472 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10473
10474 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
10475 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010476 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010477}
10478
10479/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
10480 */
10481private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
10482 f_sleep(1.0);
10483
10484 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10485 f_bssap_le_register_imsi(g_pars.imsi, omit);
10486
10487 /* provoke an abort by omitting both IMSI and IMEI */
10488 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10489 valueof(ts_BSSMAP_Perform_Location_Request(omit,
10490 ts_CellId_CGI('262'H, '42'H, 23, 42)))));
10491 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10492
10493 /* BSC tells MSC about failure */
10494 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10495 locationEstimate := omit, positioningData := omit,
10496 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
10497
10498 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10499 f_verify_active_A_conn_and_clear();
10500
10501 f_sleep(2.0);
10502 setverdict(pass);
10503}
10504testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
10505 var MSC_ConnHdlr vc_conn;
10506 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10507
10508 f_init(1, true);
10509 f_sleep(1.0);
10510
10511 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10512 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10513
10514 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
10515 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010516 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010517}
10518
10519/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10520 * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
10521private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
10522 f_sleep(1.0);
10523
10524 f_establish_fully(omit, omit);
10525 f_bssap_le_register_imsi(g_pars.imsi, omit);
10526
10527 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10528 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10529
10530 var PDU_BSSAP_LE plr;
10531 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10532
10533 if (do_ta) {
10534 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10535 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10536 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10537 }
10538
10539 /* SMLC fails to respond, BSC runs into timeout */
10540 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
10541 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10542
10543 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10544 locationEstimate := omit, positioningData := omit,
10545 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
10546
10547 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10548 f_verify_active_A_conn_and_clear();
10549
10550 f_sleep(2.0);
10551 setverdict(pass);
10552}
10553
10554/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10555 * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
10556private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
10557 f_lcs_loc_req_for_active_ms_le_timeout(false);
10558}
10559
10560testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
10561 var MSC_ConnHdlr vc_conn;
10562 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10563
10564 f_init(1, true);
10565 f_sleep(1.0);
10566 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
10567 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010568 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010569}
10570
10571/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10572 * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
10573private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
10574 f_lcs_loc_req_for_active_ms_le_timeout(true);
10575}
10576
10577testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
10578 var MSC_ConnHdlr vc_conn;
10579 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10580
10581 f_init(1, true);
10582 f_sleep(1.0);
10583 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
10584 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010585 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010586}
10587
10588/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
10589private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
10590 f_sleep(1.0);
10591
10592 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10593 f_bssap_le_register_imsi(g_pars.imsi, omit);
10594
10595 /* Register to receive the Paging Command */
10596 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10597 g_chan_nr := new_chan_nr;
10598 f_rslem_register(0, g_chan_nr);
10599
10600 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10601 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10602 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10603 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10604
10605 var PDU_BSSAP_LE plr;
10606 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10607
10608 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10609 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10610
10611 /* OsmoBSC needs to Page */
10612 var PDU_BSSAP_LE rx_bsslap;
10613 alt {
10614 [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
10615 f_logp(BSCVTY, "got Paging Command");
10616 repeat;
10617 }
10618 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10619 /* MS does not respond to Paging, TA Req runs into timeout. */
10620 f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
10621 }
10622 }
10623
10624 /* SMLC responds with failure */
10625 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10626 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10627
10628 /* BSC tells MSC about failure */
10629 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10630 locationEstimate := omit, positioningData := omit,
10631 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
10632
10633 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10634 f_verify_active_A_conn_and_clear();
10635
10636 f_sleep(2.0);
10637 setverdict(pass);
10638}
10639testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
10640 var MSC_ConnHdlr vc_conn;
10641 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10642
10643 f_init(1, true);
10644 f_sleep(1.0);
10645
10646 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10647 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10648
10649 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
10650 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010651 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010652}
10653
10654/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
10655 * over. */
10656private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10657 f_sleep(1.0);
10658
10659 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10660 f_bssap_le_register_imsi(g_pars.imsi, omit);
10661
10662 /* Register to receive the Paging Command */
10663 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10664 g_chan_nr := new_chan_nr;
10665 f_rslem_register(0, g_chan_nr);
10666
10667 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10668 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10669 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10670 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10671
10672 var PDU_BSSAP_LE plr;
10673 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10674
10675 /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
10676 * and establish Layer 3. It should use the existing A-interface conn. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010677 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 +020010678 do_clear := false, expect_bssmap_l3 := true);
10679
10680 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10681 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10682
10683 /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
10684 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10685
10686 /* SMLC got the TA from the BSC, now responds with geo information data. */
10687 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10688 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10689 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10690
10691 /* The lchan should still exist, it was from a CM Service Request. */
10692 f_mo_l3_transceive();
10693
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010694 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010695
10696 f_sleep(2.0);
10697 setverdict(pass);
10698}
10699testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
10700 var MSC_ConnHdlr vc_conn;
10701 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10702
10703 f_init(1, true);
10704 f_sleep(1.0);
10705
10706 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10707 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10708
10709 vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
10710 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010711 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010712}
10713
10714/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
10715 * the new lchan after handover. */
10716private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10717 f_sleep(1.0);
10718
10719 f_establish_fully(omit, omit);
10720 f_bssap_le_register_imsi(g_pars.imsi, omit);
10721
10722 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10723 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10724
10725 var PDU_BSSAP_LE plr;
10726 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10727
10728 /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
10729 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
10730
10731 var HandoverState hs := {
10732 rr_ho_cmpl_seen := false,
10733 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +020010734 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010735 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010736 };
10737 /* issue hand-over command on VTY */
10738 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
10739 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
10740 f_rslem_suspend(RSL1_PROC);
10741
10742 /* From the MGW perspective, a handover is is characterized by
10743 * performing one MDCX operation with the MGW. So we expect to see
10744 * one more MDCX during handover. */
10745 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
10746
10747 alt {
10748 [] as_handover(hs);
10749 }
10750
10751 var PDU_BSSAP_LE rx_bsslap;
10752
10753 interleave {
10754 /* Expect the BSC to inform the MSC about the handover */
10755 [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
10756
10757 /* Expect the BSC to inform the SMLC about the handover */
10758 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10759 f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
10760 }
10761 }
10762
10763 /* SMLC now responds with geo information data. */
10764 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10765 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10766 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10767
10768 /* lchan still active */
10769 f_mo_l3_transceive(RSL1);
10770
10771 /* MSC decides it is done now. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010772 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010773
10774 f_sleep(2.0);
10775 setverdict(pass);
10776}
10777testcase TC_ho_during_lcs_loc_req() runs on test_CT {
10778 var MSC_ConnHdlr vc_conn;
10779 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10780
10781 f_init(2, true);
10782 f_sleep(1.0);
10783 vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
10784 vc_conn.done;
Oliver Smith39f53072022-10-27 14:44:04 +020010785 f_shutdown_helper(ho := true);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010786}
10787
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010788private function f_tc_emerg_call_and_lcs_loc_req(charstring id) runs on MSC_ConnHdlr
10789{
10790 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
10791 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
10792 * another lchan. */
Pau Espin Pedrol1809bce2023-01-03 16:54:41 +010010793 g_pars.ra := f_rnd_ra_emerg();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010794 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010795 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010796
10797 /* Here would usually be a CC Call Proceeding from the MSC, but what does the BSC care about DTAP. */
10798
10799 /* Do a Location Request in-between the CC call setup */
10800 f_bssap_le_register_imsi(g_pars.imsi, omit);
10801 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10802 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10803 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10804 /* SMLC got the TA from the BSC, now responds with geo information data. */
10805 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10806 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10807 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10808
Pau Espin Pedrol14076d32023-01-03 17:07:59 +010010809 f_assignment_emerg_setup_voice();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010810
10811 setverdict(pass);
10812 f_perform_clear();
10813}
10814
10815testcase TC_emerg_call_and_lcs_loc_req() runs on test_CT {
10816 var MSC_ConnHdlr vc_conn;
10817 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10818
10819 f_init(1, true);
10820 f_sleep(1.0);
10821 f_vty_allow_emerg_msc(true);
10822 f_vty_allow_emerg_bts(true, 0);
10823 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req), pars);
10824 vc_conn.done;
10825 f_shutdown_helper();
10826}
10827
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010828private altstep no_bssmap_clear_req() runs on MSC_ConnHdlr {
10829 [] BSSAP.receive(tr_BSSMAP_ClearRequest) {
10830 setverdict(fail, "unexpected BSSMAP Clear Request");
10831 mtc.stop;
10832 }
10833}
10834
10835private type enumerated RslRel {
10836 RSLREL_REL_IND,
10837 RSLREL_CONN_FAIL
10838};
10839
10840private function f_emerg_call_and_lcs_loc_req_early_lchan_release(RslRel rsl_rel) runs on MSC_ConnHdlr
10841{
10842 g_pars.ra := f_rnd_ra_emerg();
10843 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010844 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010845
10846 /* Start a Location Request to locate the emergency */
10847 f_bssap_le_register_imsi(g_pars.imsi, omit);
10848 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10849 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10850 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10851
10852 /* 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
10853 * do a Clear Command when the Location Response arrives. */
10854 activate(no_bssmap_clear_req());
10855
10856 /* the lchan gets interrupted while the Location Request has no response */
10857 select (rsl_rel) {
10858 case (RSLREL_REL_IND) {
10859 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
10860 f_expect_lchan_rel(RSL, RSL_PROC);
10861 }
10862 case (RSLREL_CONN_FAIL) {
10863 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
10864 }
10865 case else {
10866 setverdict(fail, "Unknown RslRel type");
10867 mtc.stop;
10868 }
10869 }
10870
10871 /* Still expect the Location Response to find its way to the MSC. */
10872 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10873 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10874 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10875
10876 setverdict(pass);
10877
10878 select (rsl_rel) {
10879 case (RSLREL_REL_IND) {
10880 f_perform_clear_no_lchan();
10881 }
10882 case (RSLREL_CONN_FAIL) {
10883 f_perform_clear();
10884 }
10885 }
10886}
10887
10888private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind(charstring id) runs on MSC_ConnHdlr
10889{
10890 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_REL_IND);
10891}
10892
10893testcase TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() runs on test_CT {
10894 var MSC_ConnHdlr vc_conn;
10895 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10896
10897 f_init(1, true);
10898 f_sleep(1.0);
10899 f_vty_allow_emerg_msc(true);
10900 f_vty_allow_emerg_bts(true, 0);
10901 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind), pars);
10902 vc_conn.done;
10903 f_shutdown_helper();
10904}
10905
10906private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail(charstring id) runs on MSC_ConnHdlr
10907{
10908 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_CONN_FAIL);
10909}
10910
10911testcase TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() runs on test_CT {
10912 var MSC_ConnHdlr vc_conn;
10913 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10914
10915 f_init(1, true);
10916 f_sleep(1.0);
10917 f_vty_allow_emerg_msc(true);
10918 f_vty_allow_emerg_bts(true, 0);
10919 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail), pars);
10920 vc_conn.done;
10921 f_shutdown_helper();
10922}
10923
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010924/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
10925private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
10926 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10927
10928 /* Also disable attach for the single connected MSC */
10929 f_vty_msc_allow_attach(BSCVTY, { false });
10930
10931 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) ));
10932 f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
10933
10934 /* No MSC is found, expecting a proper release on RSL */
10935 interleave {
10936 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
10937 f_logp(BSCVTY, "Got RSL RR Release");
10938 }
10939 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10940 f_logp(BSCVTY, "Got RSL Deact SACCH");
10941 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010942 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010943 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
10944 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010945 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010946 }
10947 }
10948 setverdict(pass);
10949}
10950testcase TC_no_msc() runs on test_CT {
10951
10952 f_init(1, true);
10953 f_sleep(1.0);
10954 var MSC_ConnHdlr vc_conn;
10955 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10956
10957 f_ctrs_bsc_init(counternames_bsc_mscpool);
10958
10959 vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
10960 vc_conn.done;
10961
10962 f_ctrs_bsc_add("mscpool:subscr:no_msc");
10963 f_ctrs_bsc_verify();
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010964 f_shutdown_helper();
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010965}
10966
Harald Welte0ea2d5e2018-04-07 21:40:29 +020010967/* Dyn PDCH todo:
10968 * activate OSMO as TCH/F
10969 * activate OSMO as TCH/H
10970 * does the BSC-located PCU socket get the updated INFO?
10971 * what if no PCU is connected at the time?
10972 * is the info correct on delayed PCU (re)connect?
10973 */
Harald Welte94e0c342018-04-07 11:33:23 +020010974
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010975private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +020010976 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020010977 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010978
10979 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
10980 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10981 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
10982 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
10983 g_pars.ass_codec_list.codecElements[0];
10984 if (isvalue(g_pars.expect_mr_s0_s7)) {
10985 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
10986 g_pars.expect_mr_s0_s7;
10987 }
10988 }
10989 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
10990 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
10991 log("expecting ASS COMPL like this: ", exp_compl);
10992
10993 f_establish_fully(ass_cmd, exp_compl);
10994
Neels Hofmeyr8746b0d2021-06-01 17:25:39 +020010995 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 +000010996
10997 var RSL_Message rsl;
10998
10999 timer T := 5.0;
11000 T.start;
11001 alt {
11002 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
11003 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
11004 log("Rx L3 from net: ", l3);
11005 if (ischosen(l3.msgs.rrm.channelModeModify)) {
11006 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
11007 mtc.stop;
11008 }
11009 }
11010 [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
11011 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
11012 mtc.stop;
11013 }
11014 [] T.timeout {
11015 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
11016 setverdict(pass);
11017 }
11018 }
11019 T.stop;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011020
11021 f_perform_clear();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011022}
11023
11024/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
11025 * osmo-bsc. */
11026testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
11027 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11028 var MSC_ConnHdlr vc_conn;
11029
11030 f_init(1, true);
11031 f_sleep(1.0);
11032
11033 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11034 vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
11035 vc_conn.done;
11036 f_shutdown_helper();
11037}
11038
11039/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
11040 */
11041testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
11042 f_init_vty();
11043
11044 f_init(1, false);
11045 f_sleep(1.0);
11046
11047 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
11048
11049 var ASP_RSL_Unitdata rx_rsl_ud;
11050 timer T := 5.0;
11051
11052 T.start;
11053 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011054 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011055 if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
11056 T.stop;
11057 setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
11058 mtc.stop;
11059 }
11060 repeat;
11061 }
11062 [] T.timeout {
11063 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
11064 setverdict(pass);
11065 }
11066 }
11067}
11068
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011069private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
11070 /* First fully set up a speech lchan */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011071 f_assignment_codec(id, do_perform_clear := false);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011072
11073 /* Trigger re-assignment to another lchan */
11074 var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
11075
11076 /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
11077 * one MDCX on MGCP. */
11078 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
11079
11080 /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
11081 * as the old lchan used. */
11082 g_media.bts.ipa_crcx_seen := false;
11083 g_media.bts.ipa_mdcx_seen := false;
11084
11085 /* Send different BTS side RTP port number for the new lchan */
11086 g_media.bts.bts.port_nr := 4223;
11087
11088 f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
11089
11090 /* Trigger re-assignment. */
11091 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
11092
11093 timer T := 5.0;
11094 T.start;
11095 alt {
11096 [] as_assignment(assignment_st);
11097 [] as_Media();
11098 [] T.timeout {
11099 break;
11100 }
11101 }
11102
11103 if (not assignment_st.assignment_done) {
11104 setverdict(fail, "Assignment did not complete");
11105 mtc.stop;
11106 }
11107
11108 f_check_mgcp_expectations()
11109 setverdict(pass);
11110
11111 f_sleep(2.0);
11112 log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
11113
11114 /* Instruct BSC to clear channel */
11115 var BssmapCause cause := 0;
11116 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
11117 interleave {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011118 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
11119 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020011120 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011121 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020011122 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011123 }
11124 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
11125 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11126 }
11127 }
Neels Hofmeyr40a45d12021-09-23 22:57:12 +020011128 f_expect_dlcx_conns();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011129
11130 f_sleep(0.5);
11131}
11132
11133testcase TC_reassignment_fr() runs on test_CT {
11134 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11135 var MSC_ConnHdlr vc_conn;
11136
11137 f_init(1, true);
11138 f_sleep(1.0);
11139
Neels Hofmeyrac432fa2021-11-02 16:45:56 +010011140 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011141
11142 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11143 vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
11144 vc_conn.done;
11145
11146 /* from f_establish_fully() */
11147 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
11148 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
11149 /* from re-assignment */
11150 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
11151 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
11152 f_ctrs_bsc_and_bts_verify();
11153 f_shutdown_helper();
11154}
11155
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011156const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
11157const charstring REEST_CLEAR := "REEST_CLEAR";
11158const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
11159
11160/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
11161 * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
11162 * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
11163 * the MSC as the CM Re-Establishment is handled.
11164 *
11165 * MS bts0 bts1 bsc msc test-component
11166 * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
11167 * | | _1 wait a bit, to settle down
11168 * |<-x x--| | _1 "lose connection"
11169 * | | REEST_LOST_CONNECTION
11170 * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
11171 * | | REEST_CLEAR
11172 * | |<-0---| _1 Clear Command on first A-conn
11173 * | |--0-->| _1 Clear Complete
11174 * | |<----------------->| | _1 Release first channel
11175 * | | REEST_CLEAR_DONE
11176 * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
11177 * |<-----------------|<-------|<-1---| _2 Clear Command, Release
11178 *
11179 */
11180private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
11181 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
11182 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11183
11184 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11185 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11186
11187 f_establish_fully(ass_cmd, exp_compl);
11188
11189 /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
11190 * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
11191 * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
11192 f_sleep(2.0);
11193 COORD.send(REEST_LOST_CONNECTION);
11194
11195 alt {
11196 [] COORD.receive(REEST_CLEAR);
11197 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
11198 setverdict(fail, "Unexpected channel release");
11199 mtc.stop;
11200 }
11201 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
11202 setverdict(fail, "Unexpected channel release");
11203 mtc.stop;
11204 }
11205 }
11206 f_perform_clear()
Neels Hofmeyr969abd02021-09-23 22:24:08 +020011207 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011208 COORD.send(REEST_CLEAR_DONE);
11209}
11210
11211private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
11212 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
11213
11214 /* The MS lost the connection on the first channel, now establishes another one */
11215 COORD.receive(REEST_LOST_CONNECTION);
11216
11217 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
11218 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
11219 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
11220
11221 f_create_bssmap_exp(l3_enc);
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011222 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 +020011223 BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
11224
11225 /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
11226 COORD.send(REEST_CLEAR);
11227 COORD.receive(REEST_CLEAR_DONE);
11228
11229 f_sleep(2.0);
11230
11231 /* Answer the CM Re-Establishment with an Assignment Command. */
11232 var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
11233 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11234 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11235 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11236
11237 var AssignmentState st := valueof(ts_AssignmentStateInit);
Oliver Smithce2dd692023-04-17 10:25:50 +020011238 st.rtp_stream := true;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011239 st.is_assignment := true;
11240
11241 var ExpectCriteria mgcpcrit := {
11242 connid := omit,
11243 endpoint := omit,
11244 transid := omit
11245 };
11246 f_create_mgcp_expect(mgcpcrit);
11247
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011248 f_rslem_dchan_queue_enable(RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011249
11250 BSSAP.send(ass_cmd);
11251
11252 var PDU_BSSAP bssap;
11253
11254 alt {
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011255 [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
11256 [] as_Media_ipacc(RSL1, RSL2);
11257 [] as_Media_mgw();
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011258 [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
11259 break;
11260 }
11261 }
11262
11263 f_sleep(3.0);
11264
11265 f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011266 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011267}
11268
11269testcase TC_cm_reestablishment() runs on test_CT {
11270 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
11271 var MSC_ConnHdlr vc_conn1;
11272
11273 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
11274 var MSC_ConnHdlr vc_conn2;
11275 pars2.imsi := pars1.imsi;
11276 pars2.media_nr := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011277 pars2.expect_tsc := c_BtsParams[1].tsc;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011278
11279 f_init(2, true, guard_timeout := 40.0);
11280 f_sleep(1.0);
11281
11282 vc_conn1 := f_start_handler_create(pars1);
11283 vc_conn2 := f_start_handler_create(pars2);
11284 connect(vc_conn1:COORD, vc_conn2:COORD);
11285 f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
11286 f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
11287 vc_conn1.done;
11288 vc_conn2.done;
11289
11290 f_shutdown_helper();
11291}
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011292
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011293function f_exp_ipa_rx_nonfatal(template (present) RSL_Message t_rx,
11294 boolean ignore_other_rx := true,
11295 BtsTrxIdx idx := {0, 0},
11296 float Tval := 2.0)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011297runs on test_CT return template (omit) RSL_Message {
11298 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011299 timer T := Tval;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011300
11301 T.start;
11302 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011303 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011304 T.stop;
11305 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011306 [ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
11307 [not ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011308 log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
11309 T.stop;
11310 return omit;
11311 }
11312 [] T.timeout {
11313 return omit;
11314 }
11315 }
11316 return rx_rsl_ud.rsl;
11317}
11318
11319private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
11320 f_vty_enter_cfg_bts(pt, bts_nr);
11321 f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
11322 f_vty_transceive(pt, "exit");
11323 f_vty_transceive(pt, "exit");
11324 f_vty_transceive(pt, "exit");
11325}
11326
11327private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +030011328 template (present) RslChannelNr chan_nr := ?,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011329 template (present) uint12_t arfcn := ?,
11330 template (present) uint3_t tsc := ?)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011331{
11332 var RSL_IE_Body full_imm_ass_info;
11333 if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
11334 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
11335 mtc.stop;
11336 }
11337
11338 var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
11339 var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
11340 fn := fn,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011341 ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011342 page_mode := ?);
11343 if (not match(rr_imm_ass, expect_imm_ass)) {
11344 log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
11345 setverdict(fail, "Failed to match Immediate Assignment");
11346 mtc.stop;
11347 }
11348}
11349
11350testcase TC_imm_ass_post_chan_ack() runs on test_CT {
11351 var RSL_Message chan_act;
11352 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011353 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011354
11355 f_init(1, false);
11356 f_sleep(1.0);
11357
11358 /* (should be the default anyway, just to make things clear) */
11359 f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
11360
11361 /* RA containing reason=LU */
11362 var GsmFrameNumber fn := 2342;
11363 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011364 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011365
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011366 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011367
11368 /* First send the Chan Act ACK */
11369 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011370 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011371 var RSL_IE_Body chan_ident_ie;
11372 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11373 setverdict(fail, "RSL Channel Identification IE is absent");
11374 mtc.stop;
11375 }
11376
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011377 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011378
11379 /* Then expect the Immediate Assignment, after we ACKed the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011380 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011381
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011382 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11383 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011384
11385 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011386 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011387
11388 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011389 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011390 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011391 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11392
11393 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011394 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011395 f_shutdown_helper();
11396}
11397
11398testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
11399 var RSL_Message chan_act;
11400 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011401 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011402
11403 f_init(1, false);
11404 f_sleep(1.0);
11405
11406 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11407
11408 /* RA containing reason=LU */
11409 var GsmFrameNumber fn := 2342;
11410 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011411 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011412
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011413 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011414 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011415 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011416 var RSL_IE_Body chan_ident_ie;
11417 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11418 setverdict(fail, "RSL Channel Identification IE is absent");
11419 mtc.stop;
11420 }
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011421
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011422 /* (set bts 0 cfg back to default) */
11423 f_vty_set_imm_ass(BSCVTY);
11424
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011425 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011426 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011427 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11428 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011429
11430 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011431 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011432
11433 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011434 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011435
11436 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011437 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011438 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011439 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11440
11441 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011442 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011443 f_shutdown_helper();
11444}
11445
Neels Hofmeyr23158742021-09-07 19:08:07 +020011446testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
11447 var RSL_Message chan_act;
11448 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011449 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr23158742021-09-07 19:08:07 +020011450
11451 f_init(1, false);
11452 f_sleep(1.0);
11453
11454 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11455
11456 /* RA containing reason=LU */
11457 var GsmFrameNumber fn := 2342;
11458 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011459 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011460
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011461 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011462 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011463 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr23158742021-09-07 19:08:07 +020011464 var RSL_IE_Body chan_ident_ie;
11465 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11466 setverdict(fail, "RSL Channel Identification IE is absent");
11467 mtc.stop;
11468 }
11469
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011470 /* (set bts 0 cfg back to default) */
11471 f_vty_set_imm_ass(BSCVTY);
11472
Neels Hofmeyr23158742021-09-07 19:08:07 +020011473 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011474 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011475 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11476 chan_ident_ie.chan_ident.ch_desc.v.tsc);
11477
11478 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011479 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011480
11481 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011482 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011483
11484 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011485 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011486 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr23158742021-09-07 19:08:07 +020011487 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11488
11489 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011490 f_perform_clear_test_ct(dt);
Neels Hofmeyr23158742021-09-07 19:08:07 +020011491 f_shutdown_helper();
11492}
11493
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011494testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
11495 /* change Timeslot 6 before f_init() starts RSL */
11496 f_init_vty();
11497 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11498 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11499
11500 f_init(1, false);
11501 f_sleep(1.0);
11502
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011503 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011504 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11505 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011506 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11507 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011508
11509 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11510 f_ts_set_chcomb(0, 0, 6, "PDCH");
11511
11512 /* block all static timeslots so that the dyn TS will be used */
11513 f_disable_all_tch_f();
11514 f_disable_all_tch_h();
11515 f_disable_all_sdcch();
11516
11517 var RSL_Message chan_act;
11518 var RSL_Message imm_ass;
11519
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011520 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11521
11522 /* RA containing reason=LU */
11523 var GsmFrameNumber fn := 2342;
11524 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011525 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011526
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011527 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011528 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
11529 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011530
11531 /* Now activation as SDCCH8 */
11532 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011533 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011534
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011535 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011536 var RSL_IE_Body chan_ident_ie;
11537 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11538 setverdict(fail, "RSL Channel Identification IE is absent");
11539 mtc.stop;
11540 }
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011541
11542 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011543 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011544 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11545 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011546
11547 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011548 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011549
11550 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011551 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011552
11553 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011554 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011555 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011556 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11557
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011558 /* (set bts 0 cfg back to default) */
11559 f_vty_set_imm_ass(BSCVTY);
11560
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011561 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011562 f_perform_clear_test_ct(dt);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011563 f_shutdown_helper();
11564}
11565
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011566testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
11567 /* change Timeslot 6 before f_init() starts RSL */
11568 f_init_vty();
11569 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11570 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11571
11572 f_init(1, false);
11573 f_sleep(1.0);
11574
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011575 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011576 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11577 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011578 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11579 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011580
11581 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11582 f_ts_set_chcomb(0, 0, 6, "PDCH");
11583
11584 /* block all static timeslots so that the dyn TS will be used */
11585 f_disable_all_tch_f();
11586 f_disable_all_tch_h();
11587 f_disable_all_sdcch();
11588
11589 var RSL_Message chan_act;
11590 var RSL_Message imm_ass;
11591
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011592 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11593
11594 /* RA containing reason=LU */
11595 var GsmFrameNumber fn := 2342;
11596 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011597 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011598
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011599 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011600 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011601
11602 /* And already the Immediate Assignment even before the PDCH Deact ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011603 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011604
11605 /* continue the Osmo style PDCH Deact (usual chan rel) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011606 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011607
11608 /* Now activation as SDCCH8 */
11609 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011610 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011611
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011612 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011613 var RSL_IE_Body chan_ident_ie;
11614 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11615 setverdict(fail, "RSL Channel Identification IE is absent");
11616 mtc.stop;
11617 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011618 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011619
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011620 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11621 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011622
11623 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011624 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011625
11626 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011627 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011628 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011629 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11630
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011631 /* (set bts 0 cfg back to default) */
11632 f_vty_set_imm_ass(BSCVTY);
11633
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011634 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011635 f_perform_clear_test_ct(dt);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011636 f_shutdown_helper();
11637}
11638
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011639/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
11640testcase TC_ctrl_trx_rf_locked() runs on test_CT {
11641 var MSC_ConnHdlr vc_conn;
11642
11643 f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
11644 f_sleep(1.0);
11645
11646 /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
11647 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11648 "0,0,operational,unlocked,on,rsl-up;" &
11649 "1,0,operational,unlocked,on,rsl-up;" &
11650 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011651 "2,1,operational,unlocked,on,rsl-down;" &
11652 "2,2,operational,unlocked,on,rsl-down;" &
11653 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011654 "3,0,inoperational,locked,on,rsl-down;");
11655
11656 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock BTS 1 TRX 0");
11657 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11658 /* give it a moment to settle the FSM status */
11659 f_sleep(1.0);
11660
11661 /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
11662 * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
11663 * of "off"? But that's for a future patch if at all. */
11664 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11665 "0,0,operational,unlocked,on,rsl-up;" &
11666 "1,0,operational,locked,on,rsl-up;" &
11667 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011668 "2,1,operational,unlocked,on,rsl-down;" &
11669 "2,2,operational,unlocked,on,rsl-down;" &
11670 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011671 "3,0,inoperational,locked,on,rsl-down;");
11672
11673 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
11674 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11675 f_sleep(1.0);
11676 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11677 "0,0,operational,unlocked,on,rsl-up;" &
11678 "1,0,operational,locked,on,rsl-up;" &
11679 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011680 "2,1,operational,unlocked,on,rsl-down;" &
11681 "2,2,operational,unlocked,on,rsl-down;" &
11682 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011683 "3,0,inoperational,locked,on,rsl-down;");
11684
11685 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
11686 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
11687 f_sleep(1.0);
11688 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11689 "0,0,operational,unlocked,on,rsl-up;" &
11690 "1,0,operational,unlocked,on,rsl-up;" &
11691 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011692 "2,1,operational,unlocked,on,rsl-down;" &
11693 "2,2,operational,unlocked,on,rsl-down;" &
11694 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011695 "3,0,inoperational,locked,on,rsl-down;");
11696
11697 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
11698 f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
11699 f_sleep(1.0);
11700 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11701 "0,0,operational,unlocked,on,rsl-up;" &
11702 "1,0,operational,unlocked,on,rsl-up;" &
11703 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011704 "2,1,operational,unlocked,on,rsl-down;" &
11705 "2,2,operational,unlocked,on,rsl-down;" &
11706 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011707 "3,0,inoperational,locked,on,rsl-down;");
11708
11709 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
11710 f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
11711 f_sleep(1.0);
11712 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11713 "0,0,operational,unlocked,on,rsl-up;" &
11714 "1,0,operational,unlocked,on,rsl-up;" &
11715 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011716 "2,1,operational,unlocked,on,rsl-down;" &
11717 "2,2,operational,unlocked,on,rsl-down;" &
11718 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011719 "3,0,inoperational,locked,on,rsl-down;");
11720
11721 f_shutdown_helper();
11722}
11723
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011724const CounterNameVals counternames_cm_serv_rej := {
11725 { "cm_serv_rej", 0 },
11726 { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
11727 { "cm_serv_rej:illegal_ms", 0 },
11728 { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
11729 { "cm_serv_rej:imei_not_accepted", 0 },
11730 { "cm_serv_rej:illegal_me", 0 },
11731 { "cm_serv_rej:plmn_not_allowed", 0 },
11732 { "cm_serv_rej:loc_not_allowed", 0 },
11733 { "cm_serv_rej:roaming_not_allowed", 0 },
11734 { "cm_serv_rej:network_failure", 0 },
11735 { "cm_serv_rej:synch_failure", 0 },
11736 { "cm_serv_rej:congestion", 0 },
11737 { "cm_serv_rej:srv_opt_not_supported", 0 },
11738 { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
11739 { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
11740 { "cm_serv_rej:call_can_not_be_identified", 0 },
11741 { "cm_serv_rej:incorrect_message", 0 },
11742 { "cm_serv_rej:invalid_mandantory_inf", 0 },
11743 { "cm_serv_rej:msg_type_not_implemented", 0 },
11744 { "cm_serv_rej:msg_type_not_compatible", 0 },
11745 { "cm_serv_rej:inf_eleme_not_implemented", 0 },
11746 { "cm_serv_rej:condtional_ie_error", 0 },
11747 { "cm_serv_rej:msg_not_compatible", 0 },
11748 { "cm_serv_rej:protocol_error", 0 },
11749 { "cm_serv_rej:retry_in_new_cell", 0 }
11750};
11751
11752private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
11753{
11754 f_create_chan_and_exp();
Vadim Yanitskiya7fc5a62021-12-04 20:10:08 +030011755 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011756 BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011757 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_CM_SERV_REJ));
11758 f_perform_clear();
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011759 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011760}
11761testcase TC_cm_serv_rej() runs on test_CT {
11762 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11763 var MSC_ConnHdlr vc_conn;
11764
11765 f_init(1, true);
11766 f_sleep(1.0);
11767
11768 f_ctrs_bts_init(1, counternames_cm_serv_rej);
11769
11770 vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
11771 vc_conn.done;
11772
11773 f_ctrs_bts_add(0, "cm_serv_rej", 1);
11774 f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
11775 f_ctrs_bts_verify();
11776
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011777 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011778 f_shutdown_helper();
11779}
11780
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011781/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
11782 * Activ Ack (SYS#5627). */
11783private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
11784 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Vadim Yanitskiyf0310e32021-10-26 00:30:59 +030011785
11786 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11787 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011788
11789 var BSSMAP_FIELD_CodecType codecType;
11790 codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
11791
11792 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
11793
11794 /* First establish a signalling lchan */
11795 f_create_chan_and_exp();
11796 f_rslem_dchan_queue_enable();
11797
11798 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011799
11800 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
Oliver Smith735b47c2023-02-15 16:03:54 +010011801 activate(as_Media_mgw());
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011802
11803 var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
11804 f_rslem_register(0, chan_nr);
11805
11806 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
11807 BSSAP.send(ass_cmd);
11808
11809
11810 /* Wait for the Channel Activ for the TCH channel */
11811 var ASP_RSL_Unitdata rx_rsl_ud;
11812 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
11813
11814 /* make the original SDCCH disappear */
11815 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
11816
11817 /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
11818 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
11819
11820 interleave {
11821 [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
11822 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
11823 }
11824
11825 BSSAP.send(ts_BSSMAP_ClearCommand(0));
11826 BSSAP.receive(tr_BSSMAP_ClearComplete);
11827 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11828
11829 var MgcpCommand mgcp;
Vadim Yanitskiy6be4cf42022-06-04 21:25:47 +060011830 var MGCP_RecvFrom mrf;
11831 var template MgcpMessage msg_dlcx := { command := tr_DLCX };
11832 alt {
11833 [g_pars.aoip] MGCP.receive(tr_DLCX) -> value mgcp {
11834 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
11835 }
11836 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
11837 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
11838 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
11839 }));
11840 }
11841 }
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011842
11843 f_sleep(0.5);
11844}
11845testcase TC_lost_sdcch_during_assignment() runs on test_CT {
11846 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11847 var MSC_ConnHdlr vc_conn;
11848
Oliver Smith735b47c2023-02-15 16:03:54 +010011849 pars.fail_on_dlcx := false;
11850
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011851 f_init(1, true);
11852 f_sleep(1.0);
11853
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011854 vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
11855 vc_conn.done;
11856
11857 f_shutdown_helper();
11858}
11859
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011860const CounterNameVals counternames_bsc_bts_all_available_allocated := {
11861 { "all_allocated:sdcch", 0 },
11862 { "all_allocated:static_sdcch", 0 },
11863 { "all_allocated:tch", 0 },
11864 { "all_allocated:static_tch", 0 }
11865}
11866
11867private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
11868{
11869 /* Make sure counters settle first */
11870 f_sleep(1.0);
11871
11872 /* Take a baseline of counters */
11873 f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
11874
11875 /* Elapse some time so that we see changes in counters, hopefully where expected */
11876 f_sleep(2.0);
11877
11878 /* Get new counters */
11879 var charstring_list all_changed := {};
11880 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
11881 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
11882
11883 /* Compare with expectations */
11884 var charstring_list all_expect_changed := {};
11885 for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
11886 all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
11887 }
11888 f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
11889}
11890
11891testcase TC_ratectr_all_available_allocated() runs on test_CT {
11892 var ASP_RSL_Unitdata rsl_ud;
11893 var integer i;
11894 var integer chreq_total, chreq_nochan;
11895
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011896 f_init(1, guard_timeout := 60.0);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011897 f_sleep(1.0);
11898
11899 /* Exhaust all dedicated SDCCH lchans.
11900 /* GSM 44.018 Table 9.1.8.2:
11901 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11902 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011903 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011904 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011905 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 +020011906 }
11907
11908 /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
11909 * level.
11910 * All SDCCH are now occupied. */
11911 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11912
11913 /* Also fill up all remaining (TCH) channels */
11914 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011915 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 +020011916 }
11917
11918 /* All TCH are now also occupied */
11919 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11920 "all_allocated:tch", "all_allocated:static_tch"});
11921
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011922 /* Clean up SDCCH lchans */
11923 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11924 f_perform_clear_test_ct(chan_cleanup[i]);
11925 }
11926
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011927 f_shutdown_helper();
11928}
11929
11930testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
11931 var ASP_RSL_Unitdata rsl_ud;
11932 var integer i;
11933 var integer chreq_total, chreq_nochan;
11934
11935 f_init_vty();
11936 f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
11937 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11938 /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
11939
11940 f_init(1, guard_timeout := 60.0);
11941 f_sleep(1.0);
11942
11943 /* The dyn TS wants to activate PDCH mode, ACK that. */
11944 var RslChannelNr chan_nr;
11945 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011946 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11947 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011948
11949 /* Exhaust all dedicated SDCCH lchans.
11950 /* GSM 44.018 Table 9.1.8.2:
11951 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11952 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011953 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011954 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011955 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 +020011956 }
11957
11958 /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
11959 * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
11960 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
11961
11962 /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
11963 * Will release them later, so remember all the DchanTuples. */
11964 var DchanTuples dyn_sddch := {};
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011965 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 +020011966
11967 /* Also occupy the seven other SDCCH of the dyn TS */
11968 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011969 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 +020011970 }
11971
11972 /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
11973 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11974
11975 /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
11976 for (i := 0; i < 5; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011977 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 +020011978 }
11979
11980 /* All TCH lchans are now also occupied, both static and dynamic */
11981 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11982 "all_allocated:tch", "all_allocated:static_tch"});
11983
11984 /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
11985 * incrementing. */
11986 var BssmapCause cause := 0;
11987 var DchanTuple dt := dyn_sddch[0];
11988 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011989 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011990
11991 /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
11992 * count as occupied, so those still both increment. */
11993 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
11994 "all_allocated:tch", "all_allocated:static_tch"});
11995
11996 /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
11997 for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
11998 dt := dyn_sddch[i];
11999 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060012000 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012001 }
12002
12003 /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
12004 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060012005 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
12006 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012007
12008 /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
12009 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
12010
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010012011 /* Clean up SDCCH lchans */
12012 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
12013 f_perform_clear_test_ct(chan_cleanup[i]);
12014 }
12015
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012016 /* clean up config */
12017 f_ts_reset_chcomb(0);
12018
12019 f_shutdown_helper();
12020}
12021
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012022private function f_TC_chan_alloc_algo(DchanTuple dt, BtsTrxIdx idx)
12023runs on test_CT {
12024 /* MSC sends an Assignment Request */
12025 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12026 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12027 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12028 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
12029
12030 /* Expect the BSC to allocate a TCH channel on the given BTS/TRX */
12031 var RSL_Message rsl_chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
12032 /* Send CHAN ACT NACK, so that the requested TCH channel becomes BORKEN */
12033 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(rsl_chan_act.ies[0].body.chan_nr, RSL_ERR_EQUIPMENT_FAIL), idx);
12034 /* Expect to receive an Assignment Failure */
12035 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail));
12036}
12037
12038testcase TC_chan_alloc_algo_ascending() runs on test_CT {
12039 /* We need to access BTS2, which has 4 TRXs */
12040 f_init(nr_bts := 3);
12041
12042 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012043 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012044
12045 f_vty_enter_cfg_bts(BSCVTY, 2);
12046 f_vty_transceive(BSCVTY, "channel allocator ascending");
12047 f_vty_transceive(BSCVTY, "end");
12048
12049 /* Expect the BSC to allocate 4 x TCH/F channels on BTS2/TRX0 */
12050 for (var integer i := 0; i < 4; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012051 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012052 f_TC_chan_alloc_algo(dt, {2, 0});
12053 f_perform_clear_test_ct(dt);
12054 }
12055
12056 /* At this point all 4 x TCH/F channels are BORKEN, but they will be
12057 * resurrected upon the A-bis/OML link re-establishment. */
12058 f_shutdown_helper();
12059}
12060
12061testcase TC_chan_alloc_algo_descending() runs on test_CT {
12062 /* We need to access BTS2, which has 4 TRXs */
12063 f_init(nr_bts := 3);
12064
12065 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012066 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012067
12068 f_vty_enter_cfg_bts(BSCVTY, 2);
12069 f_vty_transceive(BSCVTY, "channel allocator descending");
12070 f_vty_transceive(BSCVTY, "end");
12071
12072 /* Expect the BSC to allocate 5 x TCH/F channels on BTS2/TRX3 */
12073 for (var integer i := 0; i < 5; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012074 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012075 f_TC_chan_alloc_algo(dt, {2, 3});
12076 f_perform_clear_test_ct(dt);
12077 }
12078
12079 /* At this point all 5 x TCH/F channels are BORKEN, but they will be
12080 * resurrected upon the A-bis/OML link re-establishment. */
12081 f_shutdown_helper();
12082}
12083
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012084testcase TC_chan_alloc_algo_ass_dynamic() runs on test_CT {
12085 const BtsTrxIdx TRX0 := {2, 0};
12086 const BtsTrxIdx TRX3 := {2, 3};
12087
12088 /* We need to access BTS2, which has 4 TRXs */
12089 f_init(nr_bts := 3);
12090
12091 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012092 vc_MGCP[0].stop;
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012093
12094 f_vty_enter_cfg_bts(BSCVTY, 2);
12095 f_vty_transceive(BSCVTY, "channel allocator mode assignment dynamic");
12096 f_vty_transceive(BSCVTY, "channel allocator dynamic-param ul-rxlev thresh 50 avg-num 2");
12097 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 0");
12098 f_vty_transceive(BSCVTY, "end");
12099
12100 var DchanTuple dt;
12101
12102 f_logp(BSCVTY, "Case a) Unknown Uplink RxLev, fall-back to ascending");
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_TC_chan_alloc_algo(dt, TRX0);
12105 f_perform_clear_test_ct(dt);
12106
12107 f_logp(BSCVTY, "Case b) Not enough RxLev samples, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012108 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012109 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12110 ts_RSL_IE_UplinkMeas(30, 0),
12111 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012112 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012113 f_TC_chan_alloc_algo(dt, TRX0);
12114 f_perform_clear_test_ct(dt);
12115
12116 f_logp(BSCVTY, "Case c) Uplink RxLev below the threshold, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012117 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012118 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12119 ts_RSL_IE_UplinkMeas(45, 0),
12120 ts_RSL_IE_BS_Power(0)), TRX0);
12121 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12122 ts_RSL_IE_UplinkMeas(48, 0),
12123 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012124 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012125 f_TC_chan_alloc_algo(dt, TRX0);
12126 f_perform_clear_test_ct(dt);
12127
12128 f_logp(BSCVTY, "Case d) Uplink RxLev above the threshold, use descending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012129 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012130 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12131 ts_RSL_IE_UplinkMeas(50, 0),
12132 ts_RSL_IE_BS_Power(0)), TRX0);
12133 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12134 ts_RSL_IE_UplinkMeas(58, 0),
12135 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012136 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012137 f_TC_chan_alloc_algo(dt, TRX3);
12138 f_perform_clear_test_ct(dt);
12139
12140 f_vty_enter_cfg_bts(BSCVTY, 2);
12141 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 90");
12142 f_vty_transceive(BSCVTY, "end");
12143
12144 f_logp(BSCVTY, "Case e) Uplink RxLev above the threshold, but C0 load is not");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012145 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012146 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12147 ts_RSL_IE_UplinkMeas(50, 0),
12148 ts_RSL_IE_BS_Power(0)), TRX0);
12149 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12150 ts_RSL_IE_UplinkMeas(58, 0),
12151 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012152 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012153 f_TC_chan_alloc_algo(dt, TRX0);
12154 f_perform_clear_test_ct(dt);
12155
12156 f_vty_enter_cfg_bts(BSCVTY, 2);
12157 f_vty_transceive(BSCVTY, "channel allocator ascending");
12158 f_vty_transceive(BSCVTY, "end");
12159
12160 /* At this point some TCH/F channels are BORKEN, but they will be
12161 * resurrected upon the A-bis/OML link re-establishment. */
12162 f_shutdown_helper();
12163}
12164
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012165private function f_vty_mgw_enable(integer mgw_nr := 1) runs on test_CT {
12166 var rof_charstring cmds := {
12167 "remote-ip " & mp_test_ip,
12168 "remote-port " & int2str(2427 + mgw_nr)
12169 };
12170 f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
12171 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " reconnect")
12172}
12173private function f_vty_mgw_disable(integer mgw_nr := 1) runs on test_CT {
12174 f_vty_config3(BSCVTY, {"network"}, { "no mgw " &int2str(mgw_nr) });
12175}
12176private function f_vty_mgw_block(integer mgw_nr := 1, boolean blocked := true) runs on test_CT {
12177 var charstring arg;
12178 if (blocked) {
12179 arg := "block";
12180 } else {
12181 arg := "unblock";
12182 }
12183 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " " & arg);
12184}
Pau Espin Pedrolbd598422023-06-15 17:29:09 +020012185private 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 {
12186 var charstring arg;
12187 var rof_charstring cmds := {
12188 "keepalive request-interval " & int2str(req_intval),
12189 "keepalive request-endpoint " & req_endp,
12190 "keepalive timeout " & int2str(rx_timeout)
12191 };
12192 f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
12193}
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012194private const charstring COORD_CMD_ESTABLISHED := "COORD_CMD_ESTABLISHED";
12195private function f_TC_mgwpool_call_seq_1(charstring id) runs on MSC_ConnHdlr {
12196 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12197 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12198 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12199 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12200
12201 f_establish_fully(ass_cmd, exp_compl);
12202 COORD.send(COORD_CMD_ESTABLISHED);
12203
12204 COORD.receive(COORD_CMD_ESTABLISHED);
12205 f_perform_clear()
12206 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12207}
12208private function f_TC_mgwpool_call_seq_2(charstring id) runs on MSC_ConnHdlr {
12209 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12210 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12211 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12212 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12213
12214
12215 COORD.receive(COORD_CMD_ESTABLISHED);
12216 f_establish_fully(ass_cmd, exp_compl);
12217 COORD.send(COORD_CMD_ESTABLISHED);
12218
12219 f_perform_clear()
12220 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12221}
12222/* Test load is spread around 2 available MGWs */
12223testcase TC_mgwpool_all_used() runs on test_CT {
12224 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12225 var MSC_ConnHdlr vc_conn1;
12226 pars1.mgwpool_idx := 0;
12227
12228 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12229 var MSC_ConnHdlr vc_conn2;
12230 pars2.mgwpool_idx := 1;
12231
12232 f_init(1, true, nr_mgw := 2);
12233 f_sleep(1.0);
12234
12235 f_vty_mgw_enable(1);
12236
12237 vc_conn1 := f_start_handler_create(pars1);
12238 vc_conn2 := f_start_handler_create(pars2);
12239 connect(vc_conn1:COORD, vc_conn2:COORD);
12240 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12241 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12242 vc_conn1.done;
12243 vc_conn2.done;
12244
12245 f_vty_mgw_disable(1);
12246
12247 f_shutdown_helper();
12248}
12249
12250/* Test blocked MGW in the pool are not selected */
12251testcase TC_mgwpool_blocked_not_used() runs on test_CT {
12252 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12253 var MSC_ConnHdlr vc_conn1;
12254 pars1.mgwpool_idx := 0;
12255
12256 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12257 var MSC_ConnHdlr vc_conn2;
12258 pars2.mgwpool_idx := 0; /* expect it in the first one, since the second will be blocked */
12259 pars2.media_nr := 2;
12260
12261 f_init(1, true, nr_mgw := 2);
12262 f_sleep(1.0);
12263
12264 f_vty_mgw_enable(1);
12265 f_vty_mgw_block(1, true);
12266
12267 vc_conn1 := f_start_handler_create(pars1);
12268 vc_conn2 := f_start_handler_create(pars2);
12269 connect(vc_conn1:COORD, vc_conn2:COORD);
12270 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12271 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12272 vc_conn1.done;
12273 vc_conn2.done;
12274
12275 f_vty_mgw_disable(1);
12276
12277 f_shutdown_helper();
12278}
12279
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012280/* Test BTS pinning to an MGW is applied */
12281testcase TC_mgwpool_pin_bts() runs on test_CT {
12282 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12283 var MSC_ConnHdlr vc_conn1;
12284 pars1.mgwpool_idx := 0;
12285
12286 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12287 var MSC_ConnHdlr vc_conn2;
12288 pars2.mgwpool_idx := 0; /* expect it in the first one, since the BTS is pinned to the first MGW */
12289 pars2.media_nr := 2;
12290
12291 f_init(1, true, nr_mgw := 2);
12292 f_sleep(1.0);
12293
12294 f_vty_mgw_enable(1);
12295 f_vty_cfg_bts(BSCVTY, 0, { "mgw pool-target 0" });
12296
12297 vc_conn1 := f_start_handler_create(pars1);
12298 vc_conn2 := f_start_handler_create(pars2);
12299 connect(vc_conn1:COORD, vc_conn2:COORD);
12300 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12301 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12302 vc_conn1.done;
12303 vc_conn2.done;
12304
12305 f_vty_cfg_bts(BSCVTY, 0, { "no mgw pool-target" } );
Vadim Yanitskiy389d7e02022-10-25 17:44:05 +070012306 f_vty_mgw_disable(1);
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012307
12308 f_shutdown_helper();
12309}
12310
Pau Espin Pedrolbd598422023-06-15 17:29:09 +020012311/* Test keepalive procedure on the MGW */
12312private function f_TC_mgwpool_keepalive_mgw0(charstring id) runs on MSC_ConnHdlr {
12313 /* Make sure the MGW is considered DOWN by the keepalive. See "timeout"
12314 * param in TC_mgwpool_keepalive. */
12315 f_sleep(3.0);
12316
12317 COORD.send(COORD_CMD_ESTABLISHED);
12318
12319 /* Wait for signal that call was established successfully over the other MSC/MGW: */
12320 COORD.receive(COORD_CMD_ESTABLISHED);
12321}
12322private function f_TC_mgwpool_keepalive_mgw1(charstring id) runs on MSC_ConnHdlr {
12323 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12324 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12325 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12326 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12327
12328 /* Wait for other MSC/MGW component to tell us the timeout is done and
12329 * we can start the call, which will be assigned to use because the other
12330 * MGW will be seen as DOWN. */
12331 COORD.receive(COORD_CMD_ESTABLISHED);
12332 f_establish_fully(ass_cmd, exp_compl);
12333 /* signal that call was established successfully over the other MSC/MGW: */
12334 COORD.send(COORD_CMD_ESTABLISHED);
12335
12336 f_perform_clear()
12337 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12338}
12339testcase TC_mgwpool_keepalive_down_not_used() runs on test_CT {
12340 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12341 var MSC_ConnHdlr vc_conn1;
12342 pars1.mgwpool_idx := 0;
12343
12344 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12345 var MSC_ConnHdlr vc_conn2;
12346 pars2.mgwpool_idx := 1; /* expect it in the second one, since the first will be considered DOWN */
12347 pars2.media_nr := 2;
12348
12349 f_init(1, true, nr_mgw := 2);
12350 f_sleep(1.0);
12351
Vadim Yanitskiycf25a3a2023-06-20 17:27:18 +070012352 f_vty_mgw_cfg_keepalive(0, req_intval := 1, req_endp := "null", rx_timeout := 3);
Pau Espin Pedrolbd598422023-06-15 17:29:09 +020012353 f_vty_mgw_enable(1);
12354 f_vty_mgw_block(1, false);
Pau Espin Pedrolbd598422023-06-15 17:29:09 +020012355
12356 vc_conn1 := f_start_handler_create(pars1);
12357 vc_conn2 := f_start_handler_create(pars2);
12358 connect(vc_conn1:COORD, vc_conn2:COORD);
12359 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_keepalive_mgw0), pars1);
12360 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_keepalive_mgw1), pars2);
12361 vc_conn1.done;
12362 vc_conn2.done;
12363
12364 f_vty_mgw_disable(1);
12365 /* disable keepalive (default status): */
12366 f_vty_mgw_cfg_keepalive(0, req_intval := 0, req_endp := "null", rx_timeout := 0);
12367
12368 f_shutdown_helper();
12369}
12370
Oliver Smithc9a5f532022-10-21 11:32:23 +020012371private function f_tc_ho_meas_rep_multi_band(charstring id) runs on MSC_ConnHdlr {
12372 g_pars := f_gen_test_hdlr_pars();
12373 var PDU_BSSAP ass_req := f_gen_ass_req();
12374 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12375 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12376 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12377 f_establish_fully(ass_req, exp_compl);
12378
12379 /* Send a measurement report with bad rxlev except on 3rd entry. The
12380 * measurement report is divided into two sub lists, as described in
12381 * 3GPP TS 04.08 § 10.5.2.20. */
12382 var NcellReports neighbor_rep := {
12383 /* Sub list 1: same band */
Oliver Smitha6773042022-10-24 12:56:30 +020012384 { rxlev := 0, bcch_freq := 0, bsic := 12 }, /* ARFCN 800, band 1800, LAC 98 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012385 /* Sub list 2: different band */
Oliver Smitha6773042022-10-24 12:56:30 +020012386 { rxlev := 0, bcch_freq := 1, bsic := 13 }, /* ARFCN 200, band 850, LAC 97 */
12387 { rxlev := 40, bcch_freq := 2, bsic := 14 }, /* ARFCN 1000, band 900, LAC 99 */
12388 { rxlev := 0, bcch_freq := 3, bsic := 11 } /* ARFCN 0, band 900, LAC 96 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012389 };
12390 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
12391 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
12392 l3_mr, 0));
12393
12394 /* Expect a handover to the third entry. If the BSC parsed the report
Oliver Smitha6773042022-10-24 12:56:30 +020012395 * correctly, the third entry has LAC 99. */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012396 var template BSSMAP_FIELD_CellIdentificationList cid_list := {
Oliver Smitha6773042022-10-24 12:56:30 +020012397 cIl_LAC := { ts_BSSMAP_CI_LAC(99) }
Oliver Smithc9a5f532022-10-21 11:32:23 +020012398 };
12399 alt {
12400 [] BSSAP.receive(tr_BSSMAP_HandoverRequired(cid_list := cid_list)) {
12401 setverdict(pass);
12402 }
12403 [] BSSAP.receive(tr_BSSMAP_HandoverRequired()) {
12404 setverdict(fail, "Handover has unexpected LAC in Cell Identification List. The BSC probably"
12405 & " didn't parse the multi-band measurement report correctly.");
12406 }
12407 }
12408
12409 f_ho_out_of_this_bsc(skip_meas_rep := true);
12410}
12411testcase TC_ho_meas_rep_multi_band() runs on test_CT {
12412 /* Verify that the BSC parses the measurement report correctly when
12413 * neighbors in multiple bands are configured (OS#5717). See
12414 * gsm_arfcn2band_rc() in libosmocore src/gsm/gsm_utils.c for the
12415 * ARFCN -> band mapping. The MS is connected to band 1800. */
12416 var MSC_ConnHdlr vc_conn;
12417
12418 f_init_vty();
12419 f_bts_0_cfg(BSCVTY,
12420 {"neighbor-list mode automatic",
12421 "handover 1",
12422 "handover algorithm 2",
12423 "handover2 window rxlev averaging 1",
12424 "no neighbors",
12425 "neighbor lac 99 arfcn 1000 bsic any", /* band 900 */
12426 "neighbor lac 98 arfcn 800 bsic any", /* band 1800 */
12427 "neighbor lac 97 arfcn 200 bsic any", /* band 850 */
Oliver Smitha6773042022-10-24 12:56:30 +020012428 "neighbor lac 96 arfcn 0 bsic any"}); /* band 900 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012429 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
12430
12431 f_init(1, true);
12432 f_sleep(1.0);
12433
12434 f_ctrs_bsc_and_bts_handover_init();
12435
12436 vc_conn := f_start_handler(refers(f_tc_ho_meas_rep_multi_band));
12437 vc_conn.done;
12438
12439 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
12440 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
12441 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
12442 f_ctrs_bsc_and_bts_add(0, "handover:completed");
12443 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
12444 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
12445 f_ctrs_bsc_and_bts_verify();
12446 f_shutdown_helper(ho := true);
12447}
12448
Harald Welte28d943e2017-11-25 15:00:50 +010012449control {
Harald Welte898113b2018-01-31 18:32:21 +010012450 /* CTRL interface testing */
Harald Welte4003d112017-12-09 22:35:39 +010012451 execute( TC_ctrl_msc_connection_status() );
Stefan Sperlingb041b3d2018-01-03 17:14:55 +010012452 execute( TC_ctrl_msc0_connection_status() );
Neels Hofmeyrf65ce872021-09-23 18:40:10 +020012453 /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
12454 * these in the AoIP test suite. */
12455 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12456 execute( TC_stat_num_msc_connected_1() );
12457 execute( TC_stat_num_msc_connected_2() );
12458 execute( TC_stat_num_msc_connected_3() );
12459 }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020012460 execute( TC_stat_num_bts_connected_1() );
12461 execute( TC_stat_num_bts_connected_2() );
12462 execute( TC_stat_num_bts_connected_3() );
Harald Welte96c94412017-12-09 03:12:45 +010012463 execute( TC_ctrl() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012464 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +020012465 execute( TC_ctrl_location() );
12466 }
Harald Welte898113b2018-01-31 18:32:21 +010012467
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012468 execute( TC_si_default() );
Neels Hofmeyr66aeba42020-07-06 02:21:21 +020012469 execute( TC_si2quater_2_earfcns() );
12470 execute( TC_si2quater_3_earfcns() );
12471 execute( TC_si2quater_4_earfcns() );
12472 execute( TC_si2quater_5_earfcns() );
12473 execute( TC_si2quater_6_earfcns() );
Neels Hofmeyrad132f22020-07-08 02:20:16 +020012474 execute( TC_si2quater_12_earfcns() );
12475 execute( TC_si2quater_23_earfcns() );
12476 execute( TC_si2quater_32_earfcns() );
12477 execute( TC_si2quater_33_earfcns() );
12478 execute( TC_si2quater_42_earfcns() );
12479 execute( TC_si2quater_48_earfcns() );
12480 execute( TC_si2quater_49_earfcns() );
Pau Espin Pedrol85a84432020-07-20 18:45:03 +020012481 execute( TC_si_acc_rotate() );
Alexander Couzens4ad3a352020-09-10 22:29:12 +020012482 execute( TC_si_acc_ramp_rotate() );
Oliver Smith45a6dd32023-09-27 10:52:50 +020012483 execute( TC_si2_ncc_permitted() ); /* TODO: test in SI6 too */
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012484
Harald Welte898113b2018-01-31 18:32:21 +010012485 /* RSL DCHAN Channel ACtivation / Deactivation */
Harald Welteae026692017-12-09 01:03:01 +010012486 execute( TC_chan_act_noreply() );
Harald Welte4003d112017-12-09 22:35:39 +010012487 execute( TC_chan_act_counter() );
Harald Welteae026692017-12-09 01:03:01 +010012488 execute( TC_chan_act_ack_noest() );
Philipp Maier9c60a622020-07-09 15:08:46 +020012489 execute( TC_chan_act_ack_noest_emerg() );
Philipp Maier606f07d2020-08-12 17:21:58 +020012490 execute( TC_chan_rqd_emerg_deny() );
Harald Welteae026692017-12-09 01:03:01 +010012491 execute( TC_chan_act_ack_est_ind_noreply() );
12492 execute( TC_chan_act_ack_est_ind_refused() );
Harald Welte618ef642017-12-14 14:58:20 +010012493 execute( TC_chan_act_nack() );
Harald Welte799c97b2017-12-14 17:50:30 +010012494 execute( TC_chan_exhaustion() );
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +070012495 execute( TC_chan_deact_silence() );
Harald Welte4003d112017-12-09 22:35:39 +010012496 execute( TC_chan_rel_rll_rel_ind() );
12497 execute( TC_chan_rel_conn_fail() );
12498 execute( TC_chan_rel_hard_clear() );
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +020012499 execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
12500 execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
Harald Welte99787102019-02-04 10:41:36 +010012501 execute( TC_chan_rel_hard_clear_csfb() );
Harald Welted8c36cd2017-12-09 23:05:31 +010012502 execute( TC_chan_rel_hard_rlsd() );
Harald Welte550daf92018-06-11 19:22:13 +020012503 execute( TC_chan_rel_hard_rlsd_ms_dead() );
Harald Welte85804d42017-12-10 14:11:58 +010012504 execute( TC_chan_rel_a_reset() );
Pau Espin Pedrolc675b612020-01-09 19:55:40 +010012505 execute( TC_chan_rel_sccp_tiar_timeout() );
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +020012506 execute( TC_chan_rel_rr_cause() );
Harald Welte6f521d82017-12-11 19:52:02 +010012507
Harald Weltecfe2c962017-12-15 12:09:32 +010012508 execute( TC_outbound_connect() );
Harald Welte898113b2018-01-31 18:32:21 +010012509
12510 /* Assignment related */
Harald Welte16a4adf2017-12-14 18:54:01 +010012511 execute( TC_assignment_cic_only() );
Harald Welte235ebf12017-12-15 14:18:16 +010012512 execute( TC_assignment_csd() );
12513 execute( TC_assignment_ctm() );
12514 execute( TC_assignment_sign() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012515 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12516 execute( TC_assignment_aoip_tla_v6() );
12517 }
Harald Welte235ebf12017-12-15 14:18:16 +010012518 execute( TC_assignment_fr_a5_0() );
12519 execute( TC_assignment_fr_a5_1() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012520 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte8f67d1d2018-05-25 20:38:42 +020012521 execute( TC_assignment_fr_a5_1_codec_missing() );
12522 }
Harald Welte235ebf12017-12-15 14:18:16 +010012523 execute( TC_assignment_fr_a5_3() );
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +020012524 execute( TC_assignment_fr_a5_4() );
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +020012525 execute( TC_assignment_fr_a5_4_fail() );
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +020012526 execute( TC_assignment_fr_a5_not_sup() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012527 execute( TC_ciph_mode_a5_0() );
12528 execute( TC_ciph_mode_a5_1() );
Oliver Smith50b98122021-07-09 15:00:28 +020012529 execute( TC_ciph_mode_a5_2_0() );
Oliver Smith1dff88d2021-07-09 08:45:51 +020012530 execute( TC_ciph_mode_a5_2_1() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012531 execute( TC_ciph_mode_a5_3() );
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +020012532 execute( TC_ciph_mode_a5_4() );
Harald Welte16a4adf2017-12-14 18:54:01 +010012533
Harald Welte60aa5762018-03-21 19:33:13 +010012534 execute( TC_assignment_codec_fr() );
Neels Hofmeyr559d5d02021-04-16 16:50:49 +020012535 execute( TC_assignment_codec_fr_by_mode_modify() );
Harald Welte60aa5762018-03-21 19:33:13 +010012536 execute( TC_assignment_codec_hr() );
12537 execute( TC_assignment_codec_efr() );
12538 execute( TC_assignment_codec_amr_f() );
12539 execute( TC_assignment_codec_amr_h() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012540
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012541 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier8a581d22019-03-26 18:32:48 +010012542 execute( TC_assignment_codec_amr_f_S1() );
12543 execute( TC_assignment_codec_amr_h_S1() );
12544 execute( TC_assignment_codec_amr_f_S124() );
12545 execute( TC_assignment_codec_amr_h_S124() );
12546 execute( TC_assignment_codec_amr_f_S0() );
12547 execute( TC_assignment_codec_amr_f_S02() );
12548 execute( TC_assignment_codec_amr_f_S024() );
12549 execute( TC_assignment_codec_amr_f_S0247() );
12550 execute( TC_assignment_codec_amr_h_S0() );
12551 execute( TC_assignment_codec_amr_h_S02() );
12552 execute( TC_assignment_codec_amr_h_S024() );
12553 execute( TC_assignment_codec_amr_h_S0247() );
12554 execute( TC_assignment_codec_amr_f_S01234567() );
12555 execute( TC_assignment_codec_amr_f_S0234567() );
12556 execute( TC_assignment_codec_amr_f_zero() );
12557 execute( TC_assignment_codec_amr_f_unsupp() );
12558 execute( TC_assignment_codec_amr_h_S7() );
Neels Hofmeyr21863562020-11-26 00:34:33 +000012559 execute( TC_assignment_codec_amr_f_start_mode_auto() );
12560 execute( TC_assignment_codec_amr_h_start_mode_auto() );
Neels Hofmeyr3eb94562020-11-26 02:40:26 +000012561 execute( TC_assignment_codec_amr_f_start_mode_4() );
12562 execute( TC_assignment_codec_amr_h_start_mode_4() );
Neels Hofmeyr454d7922020-11-26 02:24:57 +000012563 execute( TC_assignment_codec_amr_startmode_cruft() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012564 }
Harald Welte60aa5762018-03-21 19:33:13 +010012565
Philipp Maierac09bfc2019-01-08 13:41:39 +010012566 execute( TC_assignment_codec_fr_exhausted_req_hr() );
12567 execute( TC_assignment_codec_fr_exhausted_req_fr() );
12568 execute( TC_assignment_codec_fr_exhausted_req_fr_hr() );
12569 execute( TC_assignment_codec_fr_exhausted_req_hr_fr() );
12570 execute( TC_assignment_codec_hr_exhausted_req_fr() );
12571 execute( TC_assignment_codec_hr_exhausted_req_hr() );
12572 execute( TC_assignment_codec_hr_exhausted_req_hr_fr() );
12573 execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
12574 execute( TC_assignment_codec_req_hr_fr() );
12575 execute( TC_assignment_codec_req_fr_hr() );
Pau Espin Pedrol14475352021-07-22 15:48:16 +020012576 execute( TC_assignment_sdcch_exhausted_req_signalling() );
12577 execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
12578 execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
Philipp Maierac09bfc2019-01-08 13:41:39 +010012579
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +020012580 execute( TC_assignment_codec_hr_osmux_on() );
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +020012581 execute( TC_assignment_osmux() );
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020012582 execute( TC_assignment_osmux_cn() );
12583 execute( TC_assignment_osmux_bts() );
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +020012584
Harald Welte898113b2018-01-31 18:32:21 +010012585 /* RLL Establish Indication on inactive DCHAN / SAPI */
Harald Welte5cd20ed2017-12-13 21:03:20 +010012586 execute( TC_rll_est_ind_inact_lchan() );
12587 execute( TC_rll_est_ind_inval_sapi1() );
12588 execute( TC_rll_est_ind_inval_sapi3() );
12589 execute( TC_rll_est_ind_inval_sacch() );
12590
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +070012591 /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
12592 execute( TC_tch_dlci_link_id_sapi() );
12593
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012594 /* SAPI N Reject triggered by RLL establishment failures */
12595 execute( TC_rll_rel_ind_sapi_n_reject() );
12596 execute( TC_rll_err_ind_sapi_n_reject() );
12597 execute( TC_rll_timeout_sapi_n_reject() );
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +070012598 execute( TC_rll_sapi_n_reject_dlci_cc() );
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012599
Harald Welte898113b2018-01-31 18:32:21 +010012600 /* Paging related tests */
Harald Welte6f521d82017-12-11 19:52:02 +010012601 execute( TC_paging_imsi_nochan() );
12602 execute( TC_paging_tmsi_nochan() );
12603 execute( TC_paging_tmsi_any() );
12604 execute( TC_paging_tmsi_sdcch() );
12605 execute( TC_paging_tmsi_tch_f() );
12606 execute( TC_paging_tmsi_tch_hf() );
12607 execute( TC_paging_imsi_nochan_cgi() );
12608 execute( TC_paging_imsi_nochan_lac_ci() );
12609 execute( TC_paging_imsi_nochan_ci() );
12610 execute( TC_paging_imsi_nochan_lai() );
12611 execute( TC_paging_imsi_nochan_lac() );
12612 execute( TC_paging_imsi_nochan_all() );
Harald Welte751d3eb2018-01-31 15:51:06 +010012613 execute( TC_paging_imsi_nochan_plmn_lac_rnc() );
12614 execute( TC_paging_imsi_nochan_rnc() );
12615 execute( TC_paging_imsi_nochan_lac_rnc() );
12616 execute( TC_paging_imsi_nochan_lacs() );
12617 execute( TC_paging_imsi_nochan_lacs_empty() );
Stefan Sperling049a86e2018-03-20 15:51:00 +010012618 execute( TC_paging_imsi_nochan_cgi_unknown_cid() );
Harald Welte10985002017-12-12 09:29:15 +010012619 execute( TC_paging_imsi_a_reset() );
Harald Weltee65d40e2017-12-13 00:09:06 +010012620 execute( TC_paging_imsi_load() );
Philipp Maier779a7922018-02-16 11:00:37 +010012621 execute( TC_paging_counter() );
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +010012622 execute( TC_paging_resp_unsol() );
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +020012623 execute( TC_paging_500req() );
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +020012624 execute( TC_paging_450req_no_paging_load_ind() );
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +010012625 execute( TC_paging_imsi_nochan_ci_resp_invalid_mi() );
Harald Welte4e9b9cc2017-12-14 18:31:02 +010012626
12627 execute( TC_rsl_drop_counter() );
Stefan Sperling830dc9d2018-02-12 21:08:28 +010012628 execute( TC_rsl_unknown_unit_id() );
12629
12630 execute( TC_oml_unknown_unit_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012631
12632 execute( TC_classmark() );
Harald Welteeddf0e92020-06-21 19:42:15 +020012633 execute( TC_common_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012634 execute( TC_unsol_ass_fail() );
Harald Welteea99a002018-01-31 20:46:43 +010012635 execute( TC_unsol_ass_compl() );
Harald Weltefbf9b5e2018-01-31 20:41:23 +010012636 execute( TC_unsol_ho_fail() );
Harald Weltee3bd6582018-01-31 22:51:25 +010012637 execute( TC_err_82_short_msg() );
Harald Weltee9e02e42018-01-31 23:36:25 +010012638 execute( TC_err_84_unknown_msg() );
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012639
Harald Welte261af4b2018-02-12 21:20:39 +010012640 execute( TC_ho_int() );
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +020012641 execute( TC_ho_int_a5_0() );
12642 execute( TC_ho_int_a5_1() );
12643 execute( TC_ho_int_a5_3() );
12644 execute( TC_ho_int_a5_4() );
Neels Hofmeyr5f144212020-11-03 15:41:58 +000012645 execute( TC_ho_int_radio_link_failure() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012646
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012647 /* TC_ho_out_of_this_bsc is run last, see comment below */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +020012648 execute( TC_ho_out_fail_no_msc_response() );
12649 execute( TC_ho_out_fail_rr_ho_failure() );
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +020012650 execute( TC_ho_out_fail_no_result_after_ho_cmd() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012651
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012652 execute( TC_ho_into_this_bsc() );
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +020012653 execute( TC_ho_into_this_bsc_a5_0() );
12654 execute( TC_ho_into_this_bsc_a5_1() );
12655 execute( TC_ho_into_this_bsc_a5_3() );
12656 execute( TC_ho_into_this_bsc_a5_4() );
Neels Hofmeyr93182e02022-02-17 21:59:07 +010012657 execute( TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() );
12658 execute( TC_ho_into_this_bsc_a5_1_3() );
Neels Hofmeyr907b23b2022-02-17 21:58:47 +010012659 execute( TC_ho_into_this_bsc_a5_mismatch() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012660 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12661 execute( TC_ho_into_this_bsc_tla_v6() );
12662 }
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +020012663 execute( TC_srvcc_eutran_to_geran() );
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +030012664 execute( TC_srvcc_eutran_to_geran_a5_3() );
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +010012665 execute( TC_srvcc_eutran_to_geran_src_sai() );
Pau Espin Pedrol35801c32021-04-19 13:03:20 +020012666 execute( TC_srvcc_eutran_to_geran_ho_out() );
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +020012667 execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
12668 execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012669 execute( TC_ho_in_fail_msc_clears() );
12670 execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
12671 execute( TC_ho_in_fail_no_detect() );
12672 execute( TC_ho_in_fail_no_detect2() );
Oliver Smith7a8594a2023-02-13 14:30:49 +010012673 execute( TC_ho_in_fail_mgw_mdcx_timeout() );
Oliver Smith4eed06f2023-02-15 15:43:19 +010012674 execute( TC_ho_in_fail_ipa_crcx_timeout() );
Neels Hofmeyra23f3b12022-03-02 19:57:12 +010012675 execute( TC_ho_into_this_bsc_sccp_cr_without_bssap() );
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012676
Neels Hofmeyr91401012019-07-11 00:42:35 +020012677 execute( TC_ho_neighbor_config_1() );
12678 execute( TC_ho_neighbor_config_2() );
12679 execute( TC_ho_neighbor_config_3() );
12680 execute( TC_ho_neighbor_config_4() );
12681 execute( TC_ho_neighbor_config_5() );
12682 execute( TC_ho_neighbor_config_6() );
12683 execute( TC_ho_neighbor_config_7() );
12684
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012685 execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() );
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010012686 execute( TC_bssmap_clear_does_not_cause_bssmap_reset() );
Neels Hofmeyrfd445c32018-03-09 15:39:31 +010012687 execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() );
Harald Welte94e0c342018-04-07 11:33:23 +020012688
12689 execute( TC_dyn_pdch_ipa_act_deact() );
12690 execute( TC_dyn_pdch_ipa_act_nack() );
12691 execute( TC_dyn_pdch_osmo_act_deact() );
12692 execute( TC_dyn_pdch_osmo_act_nack() );
Pau Espin Pedrol37a4c152021-11-16 19:02:23 +010012693 execute( TC_dyn_ts_sdcch8_act_deact() );
12694 execute( TC_dyn_ts_sdcch8_all_subslots_used() );
12695 execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
12696 execute( TC_dyn_ts_sdcch8_act_nack() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012697
Stefan Sperling0796a822018-10-05 13:01:39 +020012698 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +020012699 execute( TC_chopped_ipa_payload() );
Stefan Sperling0796a822018-10-05 13:01:39 +020012700
Pau Espin Pedrol8f773632019-11-05 11:46:53 +010012701 /* Power control related */
12702 execute( TC_assignment_verify_ms_power_params_ie() );
Vadim Yanitskiy4b233042021-06-30 00:58:43 +020012703 execute( TC_c0_power_red_mode() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012704
12705 /* MSC pooling */
12706 /* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
12707 * RESET->RESET-ACK is unconditionally negotiated for all configured MSCs, they always all appear as connected
12708 * to osmo-bsc. The MSC pooling tests however require disconnecting selected MSCs, and hence don't work out as
12709 * intended on SCCPlite. So for now, run these only for SCCP/M3UA. */
12710 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12711 execute( TC_mscpool_L3Compl_on_1_msc() );
12712 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
12713 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
12714 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
12715 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
12716 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
12717 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
12718 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
12719 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
12720 execute( TC_mscpool_paging_and_response_imsi() );
12721 execute( TC_mscpool_paging_and_response_tmsi() );
12722 execute( TC_mscpool_no_allow_attach_round_robin() );
12723 execute( TC_mscpool_no_allow_attach_valid_nri() );
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +020012724
12725 execute( TC_mscpool_sccp_n_pcstate_detaches_msc() );
Neels Hofmeyr38632aa2023-04-05 03:50:51 +020012726 execute( TC_mscpool_sccp_n_pcstate_attaches_msc() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012727 }
12728
Harald Welte99f3ca02018-06-14 13:40:29 +020012729 execute( TC_early_conn_fail() );
12730 execute( TC_late_conn_fail() );
Oliver Smithaf03bef2021-08-24 15:34:51 +020012731 execute( TC_stats_conn_fail() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012732
Philipp Maier783681c2020-07-16 16:47:06 +020012733 /* Emergency call handling (deny / allow) */
12734 execute( TC_assignment_emerg_setup_allow() );
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +010012735 execute( TC_assignment_emerg_setup_allow_imei() );
Philipp Maier783681c2020-07-16 16:47:06 +020012736 execute( TC_assignment_emerg_setup_deny_msc() );
12737 execute( TC_assignment_emerg_setup_deny_bts() );
Philipp Maier82812002020-08-13 18:48:27 +020012738 execute( TC_emerg_premption() );
12739
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +070012740 /* Frequency hopping parameters handling */
12741 execute( TC_fh_params_chan_activ() );
12742 execute( TC_fh_params_imm_ass() );
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070012743 execute( TC_fh_params_assignment_cmd() );
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070012744 execute( TC_fh_params_handover_cmd() );
Vadim Yanitskiyca974032020-09-01 07:20:39 +070012745 execute( TC_fh_params_si4_cbch() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012746
12747 if (mp_enable_lcs_tests) {
12748 execute( TC_lcs_loc_req_for_active_ms() );
12749 execute( TC_lcs_loc_req_for_active_ms_ta_req() );
12750 execute( TC_lcs_loc_req_for_idle_ms() );
12751 execute( TC_lcs_loc_req_no_subscriber() );
12752 execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
12753 execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
12754 execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
12755 execute( TC_cm_service_during_lcs_loc_req() );
12756 execute( TC_ho_during_lcs_loc_req() );
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020012757 execute( TC_emerg_call_and_lcs_loc_req() );
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020012758 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() );
12759 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012760 }
Neels Hofmeyrbf037052020-10-28 22:52:02 +000012761
12762 execute( TC_no_msc() );
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000012763
12764 execute( TC_refuse_chan_act_to_vamos() );
12765 execute( TC_refuse_mode_modif_to_vamos() );
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000012766
12767 execute( TC_reassignment_fr() );
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020012768
12769 execute( TC_cm_reestablishment() );
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020012770
12771 execute( TC_imm_ass_post_chan_ack() );
12772 execute( TC_imm_ass_pre_chan_ack() );
Neels Hofmeyr23158742021-09-07 19:08:07 +020012773 execute( TC_imm_ass_pre_ts_ack() );
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020012774 execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020012775 execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020012776
12777 execute( TC_ctrl_trx_rf_locked() );
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012778
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012779 execute( TC_ratectr_all_available_allocated() );
12780 execute( TC_ratectr_all_available_allocated_dyn() );
12781
Neels Hofmeyrb7581872021-11-07 14:02:49 +010012782 execute( TC_cm_serv_rej() );
12783
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012784 execute( TC_lost_sdcch_during_assignment() );
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012785
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012786 /* Channel allocator */
12787 execute( TC_chan_alloc_algo_ascending() );
12788 execute( TC_chan_alloc_algo_descending() );
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012789 execute( TC_chan_alloc_algo_ass_dynamic() );
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012790
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012791 /* MGW pool */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +010012792 execute( TC_mgwpool_all_used() );
12793 execute( TC_mgwpool_blocked_not_used() );
12794 execute( TC_mgwpool_pin_bts() );
Pau Espin Pedrolbd598422023-06-15 17:29:09 +020012795 execute( TC_mgwpool_keepalive_down_not_used() );
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012796
Oliver Smithc9a5f532022-10-21 11:32:23 +020012797 execute( TC_ho_meas_rep_multi_band() );
12798
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012799 /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
12800 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
12801 execute( TC_ho_out_of_this_bsc() );
Harald Welte28d943e2017-11-25 15:00:50 +010012802}
12803
12804}