blob: ebcd576b0606a5e9a9d2823f583881c3db4e4113 [file] [log] [blame]
Harald Welte28d943e2017-11-25 15:00:50 +01001module BSC_Tests {
2
Harald Welte21b46bd2017-12-17 19:46:32 +01003/* Integration Tests for OsmoBSC
Harald Weltea0630032018-03-20 21:09:55 +01004 * (C) 2017-2018 by Harald Welte <laforge@gnumonks.org>
Harald Welte21b46bd2017-12-17 19:46:32 +01005 * All rights reserved.
6 *
7 * Released under the terms of GNU General Public License, Version 2 or
8 * (at your option) any later version.
9 *
Harald Welte34b5a952019-05-27 11:54:11 +020010 * SPDX-License-Identifier: GPL-2.0-or-later
11 *
Harald Welte21b46bd2017-12-17 19:46:32 +010012 * This test suite tests OsmoBSC while emulating both multiple BTS + MS as
13 * well as the MSC. See README for more details.
14 *
15 * There are test cases that run in so-called 'handler mode' and test cases
16 * that run directly on top of the BSSAP and RSL CodecPorts. The "handler mode"
17 * tests abstract the multiplexing/demultiplexing of multiple SCCP connections
18 * and/or RSL channels and are hence suitable for higher-level test cases, while
19 * the "raw" tests directly on top of the CodecPorts are more suitable for lower-
20 * level testing.
21 */
22
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +020023friend module BSC_Tests_VAMOS;
Vadim Yanitskiy5eb06a32022-06-23 18:39:46 +070024friend module BSC_Tests_CBSP;
Vadim Yanitskiy3cc065b2023-01-06 21:35:12 +070025friend module BSC_Tests_LCLS;
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +020026
Neels Hofmeyr4f118412020-06-04 15:25:10 +020027import from Misc_Helpers all;
Harald Welte4003d112017-12-09 22:35:39 +010028import from General_Types all;
Harald Welte28d943e2017-11-25 15:00:50 +010029import from Osmocom_Types all;
Harald Welteae026692017-12-09 01:03:01 +010030import from GSM_Types all;
Harald Welte28d943e2017-11-25 15:00:50 +010031import from IPL4asp_Types all;
32
Harald Welte6f521d82017-12-11 19:52:02 +010033import from BSSAP_Types all;
Harald Welte6811d102019-04-14 22:23:14 +020034import from RAN_Adapter all;
Harald Welte47cd0e32020-08-21 12:39:11 +020035import from BSSAP_LE_Adapter all;
36import from BSSAP_LE_CodecPort all;
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020037import from BSSAP_LE_Types all;
38import from BSSLAP_Types all;
Harald Welteae026692017-12-09 01:03:01 +010039import from BSSAP_CodecPort all;
40import from BSSMAP_Templates all;
Harald Welte28d943e2017-11-25 15:00:50 +010041import from IPA_Emulation all;
Stefan Sperling830dc9d2018-02-12 21:08:28 +010042import from IPA_CodecPort all;
Harald Welteae026692017-12-09 01:03:01 +010043import from IPA_Types all;
Stefan Sperling0796a822018-10-05 13:01:39 +020044import from IPA_Testing all;
Harald Welteae026692017-12-09 01:03:01 +010045import from RSL_Types all;
Harald Welte624f9632017-12-16 19:26:04 +010046import from RSL_Emulation all;
Daniel Willmann191e0d92018-01-17 12:44:35 +010047import from MGCP_Emulation all;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010048import from MGCP_Templates all;
49import from MGCP_Types all;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +020050import from MGCP_CodecPort all;
Harald Welte28d943e2017-11-25 15:00:50 +010051
Harald Welte96c94412017-12-09 03:12:45 +010052import from Osmocom_CTRL_Functions all;
Harald Weltea5d2ab22017-12-09 14:21:42 +010053import from Osmocom_CTRL_Types all;
Harald Welteffe55fc2018-01-17 22:39:54 +010054import from Osmocom_CTRL_Adapter all;
Harald Welte96c94412017-12-09 03:12:45 +010055
Daniel Willmannebdecc02020-08-12 15:30:17 +020056import from StatsD_Types all;
57import from StatsD_CodecPort all;
58import from StatsD_CodecPort_CtrlFunct all;
59import from StatsD_Checker all;
60
Harald Weltebc03c762018-02-12 18:09:38 +010061import from Osmocom_VTY_Functions all;
62import from TELNETasp_PortType all;
63
Harald Welte6f521d82017-12-11 19:52:02 +010064import from MobileL3_CommonIE_Types all;
Harald Weltee3bd6582018-01-31 22:51:25 +010065import from MobileL3_Types all;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010066import from MobileL3_RRM_Types all;
Harald Welte6f521d82017-12-11 19:52:02 +010067import from L3_Templates all;
68import from GSM_RR_Types all;
69
Stefan Sperlingc307e682018-06-14 15:15:46 +020070import from SCCP_Templates all;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010071import from BSSMAP_Templates all;
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020072import from BSSMAP_LE_Templates all;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010073
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010074import from SCCPasp_Types all;
75
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020076import from GSM_SystemInformation all;
77import from GSM_RestOctets all;
Neels Hofmeyrad132f22020-07-08 02:20:16 +020078import from TCCConversion_Functions all;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020079
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060080const integer NUM_TRX := 4;
Harald Welte5d1a2202017-12-13 19:51:29 +010081const integer NUM_BTS := 3;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020082const integer NUM_BTS_CFG := 4; /* we have 4 BTS in the osmo-bsc.cfg (for inter-BSC HO tests) but use only 3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060083const integer NUM_TRX_CFG := 1; /* we support up to 4 TRX per BTS, but have only 1 TRX per BTS in osmo-bsc.cfg */
Neels Hofmeyrf246a922020-05-13 02:27:10 +020084const integer NUM_MSC := 3;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020085const integer NUM_MGW := 2;
Harald Welteae026692017-12-09 01:03:01 +010086const float T3101_MAX := 12.0;
Harald Welte28d943e2017-11-25 15:00:50 +010087
Harald Welte799c97b2017-12-14 17:50:30 +010088/* make sure to sync this with the osmo-bts.cfg you're using */
Philipp Maiercb6cc482018-03-26 13:08:00 +020089const integer NUM_TCHH_PER_BTS := 2;
90const integer NUM_TCHF_PER_BTS := 4;
Neels Hofmeyr74083c22020-07-29 00:43:01 +020091const integer NUM_SDCCH_PER_BTS := 3;
Harald Welte799c97b2017-12-14 17:50:30 +010092
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060093friend type record BtsTrxIdx {
94 uint8_t bts,
95 uint8_t trx
96}
97
98private type record BtsParams {
99 integer trx_num,
100 integer tsc
101}
102
Neels Hofmeyrbf720202021-10-02 12:58:24 +0200103/* Default Training Sequence Code expected for bts[i]:
104 * BTS 0 has BSIC 10 (and no explicit timeslot training_sequence_code config), so expecting TSC = (BSIC & 7) = 2.
105 * BTS 1 has BSIC 11, TSC = (BSIC & 7) = 3.
106 * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
107 * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
108 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600109private const BtsParams c_BtsParams[NUM_BTS_CFG] := {
110 /* BTS0 */ { trx_num := 1, tsc := 2 },
111 /* BTS1 */ { trx_num := 1, tsc := 3 },
Vadim Yanitskiy7a3d2932022-05-29 20:37:46 +0600112 /* BTS2 */ { trx_num := 4, tsc := 4 },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600113 /* BTS3 */ { trx_num := 1, tsc := 4 }
Neels Hofmeyrbf720202021-10-02 12:58:24 +0200114}
Harald Welte4003d112017-12-09 22:35:39 +0100115
Vadim Yanitskiy59494702022-09-14 15:29:04 +0700116private const RSL_IE_Body c_mr_conf_5_90 :=
Pau Espin Pedrolf7634dc2022-09-02 17:56:00 +0200117 valueof(RSL_IE_Body:{multirate_cfg := ts_RSL_MultirateCfg(true, 0, '00000100'B /* 5,90k */)});
118
Harald Welte21b46bd2017-12-17 19:46:32 +0100119/* per-BTS state which we keep */
Harald Welte96c94412017-12-09 03:12:45 +0100120type record BTS_State {
Harald Welte21b46bd2017-12-17 19:46:32 +0100121 /* component reference to the IPA_Client component used for RSL */
Harald Weltea5d2ab22017-12-09 14:21:42 +0100122 IPA_Client rsl
Harald Welte96c94412017-12-09 03:12:45 +0100123}
124
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200125/* Default list of counters for an 'msc' entity. */
126const CounterNameVals counternames_msc_mscpool := {
127 { "mscpool:subscr:new", 0 },
128 { "mscpool:subscr:known", 0 },
129 { "mscpool:subscr:reattach", 0 },
130 { "mscpool:subscr:attach_lost", 0 },
131 { "mscpool:subscr:paged", 0 }
132};
133
Neels Hofmeyrbf037052020-10-28 22:52:02 +0000134/* List of global mscpool counters, not related to a specific 'msc' entity. */
135const CounterNameVals counternames_bsc_mscpool := {
136 { "mscpool:subscr:no_msc", 0 }
137};
138
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000139/* Default list of counters for 'bsc' and 'bts' entities. */
140const CounterNameVals counternames_bsc_bts_handover := {
141 { "assignment:attempted", 0 },
142 { "assignment:completed", 0 },
143 { "assignment:stopped", 0 },
144 { "assignment:no_channel", 0 },
145 { "assignment:timeout", 0 },
146 { "assignment:failed", 0 },
147 { "assignment:error", 0 },
148
149 { "handover:attempted", 0 },
150 { "handover:completed", 0 },
151 { "handover:stopped", 0 },
152 { "handover:no_channel", 0 },
153 { "handover:timeout", 0 },
154 { "handover:failed", 0 },
155 { "handover:error", 0 },
156
157 { "intra_cell_ho:attempted", 0 },
158 { "intra_cell_ho:completed", 0 },
159 { "intra_cell_ho:stopped", 0 },
160 { "intra_cell_ho:no_channel", 0 },
161 { "intra_cell_ho:timeout", 0 },
162 { "intra_cell_ho:failed", 0 },
163 { "intra_cell_ho:error", 0 },
164
165 { "intra_bsc_ho:attempted", 0 },
166 { "intra_bsc_ho:completed", 0 },
167 { "intra_bsc_ho:stopped", 0 },
168 { "intra_bsc_ho:no_channel", 0 },
169 { "intra_bsc_ho:timeout", 0 },
170 { "intra_bsc_ho:failed", 0 },
171 { "intra_bsc_ho:error", 0 },
172
173 { "interbsc_ho_out:attempted", 0 },
174 { "interbsc_ho_out:completed", 0 },
175 { "interbsc_ho_out:stopped", 0 },
176 { "interbsc_ho_out:timeout", 0 },
177 { "interbsc_ho_out:failed", 0 },
178 { "interbsc_ho_out:error", 0 },
179
180 { "interbsc_ho_in:attempted", 0 },
181 { "interbsc_ho_in:completed", 0 },
182 { "interbsc_ho_in:stopped", 0 },
183 { "interbsc_ho_in:no_channel", 0 },
184 { "interbsc_ho_in:timeout", 0 },
185 { "interbsc_ho_in:failed", 0 },
186 { "interbsc_ho_in:error", 0 }
187};
188
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100189const CounterNameVals counternames_bts_handover := {
190 { "incoming_intra_bsc_ho:attempted", 0 },
191 { "incoming_intra_bsc_ho:completed", 0 },
192 { "incoming_intra_bsc_ho:stopped", 0 },
193 { "incoming_intra_bsc_ho:no_channel", 0 },
194 { "incoming_intra_bsc_ho:timeout", 0 },
195 { "incoming_intra_bsc_ho:failed", 0 },
196 { "incoming_intra_bsc_ho:error", 0 }
197};
198
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200199/* Set of all System Information received during one RSL port's startup.
200 * Note that some System Information may be sent on RSL, but lacking actual SI data, to indicate that the BTS should not
201 * broadcast that SI type. That will be reflected as 'omit' here.
202 */
203type record SystemInformationConfig {
204 SystemInformationType1 si1 optional,
205 SystemInformationType2 si2 optional,
206 SystemInformationType2bis si2bis optional,
207 SystemInformationType2ter si2ter optional,
Neels Hofmeyrad132f22020-07-08 02:20:16 +0200208 SI2quaterRestOctetsList si2quater optional,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200209 SystemInformationType3 si3 optional,
210 SystemInformationType4 si4 optional,
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100211 SystemInformationType13 si13 optional,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200212 SystemInformationType5 si5 optional,
213 SystemInformationType5bis si5bis optional,
214 SystemInformationType5ter si5ter optional,
215 SystemInformationType6 si6 optional
216};
217
218const SystemInformationConfig SystemInformationConfig_omit := {
219 si1 := omit,
220 si2 := omit,
221 si2bis := omit,
222 si2ter := omit,
223 si2quater := omit,
224 si3 := omit,
225 si4 := omit,
226 si13 := omit,
227 si5 := omit,
228 si5bis := omit,
229 si5ter := omit,
230 si6 := omit
231};
232
233/* tr_EUTRAN_CellDesc with defaults used in BSC_Tests.ttcn */
234template EUTRAN_CellDesc tr_EUTRAN_CellDesc_default(template (present) uint16_t e_arfcn := ?,
235 template uint3_t meas_bw := 3)
236:= tr_EUTRAN_CellDesc(e_arfcn := e_arfcn,
237 meas_bw_presence := '1'B,
238 meas_bw := meas_bw);
239
240/* tr_EUTRAN_NeighbourCells with defaults used in BSC_Tests.ttcn */
Harald Welte65e419a2020-08-21 12:38:33 +0200241template EUTRAN_NeighbourCells tr_EUTRAN_NeighbourCells_default(template (present) EUTRAN_CellDescs cell_desc_list := { tr_EUTRAN_CellDesc_default },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200242 template uint3_t prio := 3,
243 template (present) uint5_t thresh_high := 20,
244 template uint5_t thresh_low := 10,
245 template uint5_t qrxlevmin := 22)
246:= tr_EUTRAN_NeighbourCells(
247 cell_desc_list := cell_desc_list,
248 prio_presence := '1'B,
249 prio := prio,
250 thresh_high := thresh_high,
251 thresh_low_presence := '1'B,
252 thresh_low := thresh_low,
253 qrxlevmin_presence := '1'B,
254 qrxlevmin := qrxlevmin);
255
256template SystemInformationConfig SystemInformationConfig_default := {
257 si1 := {
258 cell_chan_desc := '8FB38000000000000000000000000000'O,
259 rach_control := {
260 max_retrans := RACH_MAX_RETRANS_7,
261 tx_integer := '1001'B,
262 cell_barr_access := false,
263 re_not_allowed := true,
264 acc := '0000010000000000'B
265 },
266 rest_octets := ?
267 },
268 si2 := {
269 bcch_freq_list := '00000000000000000000000000000000'O,
270 ncc_permitted := '11111111'B,
271 rach_control := {
272 max_retrans := RACH_MAX_RETRANS_7,
273 tx_integer := '1001'B,
274 cell_barr_access := false,
275 re_not_allowed := true,
276 acc := '0000010000000000'B
277 }
278 },
279 si2bis := omit,
280 si2ter := {
281 extd_bcch_freq_list := '8E320000000000000000000000000800'O,
282 rest_octets := ?
283 },
284 si2quater := {
285 tr_SI2quaterRestOctets_EUTRAN( repeated_neigh_cells := { tr_EUTRAN_NeighbourCells_default } )
286 },
287 si3 := {
288 cell_id := 0,
289 lai := {
290 mcc_mnc := '001F01'H,
291 lac := 1
292 },
293 ctrl_chan_desc := {
294 msc_r99 := true,
295 att := true,
296 bs_ag_blks_res := 1,
297 ccch_conf := CCHAN_DESC_1CCCH_COMBINED,
298 si22ind := false,
299 cbq3 := CBQ3_IU_MODE_NOT_SUPPORTED,
300 spare := '00'B,
301 bs_pa_mfrms := 3,
302 t3212 := 30
303 },
304 cell_options := {
305 dn_ind := false,
306 pwrc := false,
307 dtx := MS_SHALL_USE_UL_DTX,
308 radio_link_tout_div4 := 7
309 },
310 cell_sel_par := {
311 cell_resel_hyst_2dB := 2,
312 ms_txpwr_max_cch := 7,
313 acs := '0'B,
314 neci := true,
315 rxlev_access_min := 0
316 },
317 rach_control := {
318 max_retrans := RACH_MAX_RETRANS_7,
319 tx_integer := '1001'B,
320 cell_barr_access := false,
321 re_not_allowed := true,
322 acc := '0000010000000000'B
323 },
324 rest_octets := {
325 sel_params := {
326 presence := '0'B,
327 params := omit
328 },
329 pwr_offset := {
330 presence := '0'B,
331 offset := omit
332 },
333 si_2ter_ind := '1'B,
334 early_cm_ind := '0'B,
335 sched_where := {
336 presence := '0'B,
337 where := omit
338 },
339 gprs_ind := {
340 presence := '1'B,
341 ind := {
342 ra_colour := 0,
343 si13_pos := '0'B
344 }
345 },
346 umts_early_cm_ind := '1'B,
347 si2_quater_ind := {
348 presence := '1'B,
349 ind := '0'B
350 },
351 iu_mode_ind := omit,
352 si21_ind := {
353 presence := '0'B,
354 pos := omit
355 }
356 }
357 },
358 si4 := {
359 lai := {
360 mcc_mnc := '001F01'H,
361 lac := 1
362 },
363 cell_sel_par := {
364 cell_resel_hyst_2dB := 2,
365 ms_txpwr_max_cch := 7,
366 acs := '0'B,
367 neci := true,
368 rxlev_access_min := 0
369 },
370 rach_control := {
371 max_retrans := RACH_MAX_RETRANS_7,
372 tx_integer := '1001'B,
373 cell_barr_access := false,
374 re_not_allowed := true,
375 acc := '0000010000000000'B
376 },
Neels Hofmeyr74083c22020-07-29 00:43:01 +0200377 cbch_chan_desc := {
378 iei := '64'O,
379 v := {
380 chan_nr := {
381 u := {
382 sdcch4 := {
383 tag := '001'B,
384 sub_chan := 2
385 }
386 },
387 tn := 0
388 },
389 tsc := 2,
390 h := false,
391 arfcn := 871,
392 maio_hsn := omit
393 }
394 },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200395 cbch_mobile_alloc := omit,
396 rest_octets := {
397 sel_params := {
398 presence := '0'B,
399 params := omit
400 },
401 pwr_offset := {
402 presence := '0'B,
403 offset := omit
404 },
405 gprs_ind := {
406 presence := '1'B,
407 ind := {
408 ra_colour := 0,
409 si13_pos := '0'B
410 }
411 },
412 s_presence := '0'B,
413 s := omit
414 }
415 },
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100416 si13 := {
417 rest_octets := {
418 presence := '1'B,
419 bcch_change_mark := ?,
420 si_change_field := '0000'B,
421 presence2 := '0'B,
422 si13_change_mark := omit,
423 gprs_ma := omit,
424 zero := '0'B, /* PBCCH not present in cell */
425 rac := 0,
426 spgc_ccch_sup := '0'B,
427 priority_access_thr := '110'B,
428 network_control_order := '00'B,
429 gprs_cell_opts := {
430 nmo := '01'B,
431 t3168 := '011'B,
432 t3192 := '010'B,
433 drx_timer_max := '011'B,
434 access_burst_type := '0'B,
435 control_ack_type := '1'B,
436 bs_cv_max := 15,
437 pan_presence := '1'B,
438 pan_dec := 1,
439 pan_inc := 1,
440 pan_max := '111'B,
441 ext_info_presence := ?,
442 ext_info_length := *,
443 ext_info := *
444 },
445 gprs_pwr_ctrl_params := {
446 alpha := 0,
447 t_avg_w := '10000'B,
448 t_avg_t := '10000'B,
449 pc_meas_chan := '0'B,
450 n_avg_i := '1000'B
451 }
452 }
453 },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200454 si5 := {
455 bcch_freq_list := '10000000000000000000000000000000'O
456 },
457 si5bis := omit,
458 si5ter := {
459 extd_bcch_freq_list := '9E050020000000000000000000000000'O
460 },
461 si6 := {
462 cell_id := 0,
463 lai := {
464 mcc_mnc := '001F01'H,
465 lac := 1
466 },
467 cell_options := {
468 dtx_ext := '1'B,
469 pwrc := false,
470 dtx := '01'B,
471 radio_link_timeout := '0111'B
472 },
473 ncc_permitted := '11111111'B,
Vadim Yanitskiy348b07c2022-03-10 17:11:22 +0300474 rest_octets := {
475 pch_nch_info := ?,
476 vbs_vgcs_options := ?,
477 dtm_support := '0'B,
478 rac := omit,
479 max_lapdm := omit,
480 band_ind := '0'B /* C0 ARFCN indicates 1800 band */
481 }
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200482 }
483 };
484
485
486/* List of all the System Information received on all RSL ports */
487type record of SystemInformationConfig SystemInformationConfig_list;
488
489function f_sysinfo_dec_raw(inout SystemInformationConfig si, RSL_Message rsl)
490{
491 var RSL_IE_Body sysinfo_type_ie;
492 var RSL_IE_SysinfoType si_type;
493 var octetstring data;
494
495 if (f_rsl_find_ie(rsl, RSL_IE_SYSINFO_TYPE, sysinfo_type_ie) == false) {
496 setverdict(fail, "Cannot find RSL_IE_SYSINFO_TYPE");
497 mtc.stop;
498 }
499 si_type := sysinfo_type_ie.sysinfo_type;
500
501 if (rsl.msg_type == RSL_MT_BCCH_INFO) {
502 var RSL_IE_Body bcch_ie;
503 if (f_rsl_find_ie(rsl, RSL_IE_FULL_BCCH_INFO, bcch_ie)) {
504 data := bcch_ie.other.payload;
505 }
506 } else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
507 var RSL_IE_Body l3_ie;
508 if (f_rsl_find_ie(rsl, RSL_IE_L3_INFO, l3_ie)) {
509 data := l3_ie.l3_info.payload;
510 }
511 } else {
512 setverdict(fail, "Don't understand this System Information message");
513 mtc.stop;
514 }
515
516 var boolean handled := false;
517
518 if (rsl.msg_type == RSL_MT_BCCH_INFO) {
519 handled := true;
520
521 if (si_type == RSL_SYSTEM_INFO_1) {
522 if (not isbound(data)) {
523 si.si1 := omit;
524 } else {
525 si.si1 := dec_SystemInformation(data).payload.si1;
526 }
527 } else if (si_type == RSL_SYSTEM_INFO_2) {
528 if (not isbound(data)) {
529 si.si2 := omit;
530 } else {
531 si.si2 := dec_SystemInformation(data).payload.si2;
532 }
533 } else if (si_type == RSL_SYSTEM_INFO_2bis) {
534 if (not isbound(data)) {
535 si.si2bis := omit;
536 } else {
537 si.si2bis := dec_SystemInformation(data).payload.si2bis;
538 }
539 } else if (si_type == RSL_SYSTEM_INFO_2ter) {
540 if (not isbound(data)) {
541 si.si2ter := omit;
542 } else {
543 si.si2ter := dec_SystemInformation(data).payload.si2ter;
544 }
545 } else if (si_type == RSL_SYSTEM_INFO_2quater) {
546 if (not isbound(data)) {
547 si.si2quater := {};
548 } else {
549 var SystemInformationType2quater decoded := dec_SystemInformation(data).payload.si2quater;
550 /* this is a *record* of SI2quaterRestOctets! (multiplexed) */
551 si.si2quater[decoded.rest_octets.si2quater_index] := decoded.rest_octets;
552 }
553 } else if (si_type == RSL_SYSTEM_INFO_3) {
554 if (not isbound(data)) {
555 si.si3 := omit;
556 } else {
557 si.si3 := dec_SystemInformation(data).payload.si3;
558 }
559 } else if (si_type == RSL_SYSTEM_INFO_4) {
560 if (not isbound(data)) {
561 si.si4 := omit;
562 } else {
563 si.si4 := dec_SystemInformation(data).payload.si4;
564 }
565 } else if (si_type == RSL_SYSTEM_INFO_13) {
566 if (not isbound(data)) {
567 si.si13 := omit;
568 } else {
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100569 si.si13 := dec_SystemInformation(data).payload.si13;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200570 }
571 } else {
572 handled := false;
573 }
574 } else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
575 handled := true;
576
577 if (si_type == RSL_SYSTEM_INFO_5) {
578 if (not isbound(data)) {
579 si.si5 := omit;
580 } else {
581 si.si5 := dec_SystemInformation(data).payload.si5;
582 }
583 } else if (si_type == RSL_SYSTEM_INFO_5bis) {
584 if (not isbound(data)) {
585 si.si5bis := omit;
586 } else {
587 si.si5bis := dec_SystemInformation(data).payload.si5bis;
588 }
589 } else if (si_type == RSL_SYSTEM_INFO_5ter) {
590 if (not isbound(data)) {
591 si.si5ter := omit;
592 } else {
593 si.si5ter := dec_SystemInformation(data).payload.si5ter;
594 }
595 } else if (si_type == RSL_SYSTEM_INFO_6) {
596 if (not isbound(data)) {
597 si.si6 := omit;
598 } else {
599 si.si6 := dec_SystemInformation(data).payload.si6;
600 }
601 } else {
602 handled := false;
603 }
604 }
605
606 if (not handled) {
607 setverdict(fail, "Unexpected SI type in ", rsl.msg_type, " message: ", si_type);
608 }
609}
610
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +0100611friend function gen_l3_valid_payload(hexstring imsi := ''H) return octetstring {
612 var octetstring l3_payload;
613 if (lengthof(imsi) == 0) {
614 imsi := f_rnd_imsi('00101'H);
615 }
616 l3_payload := enc_PDU_ML3_MS_NW(valueof(ts_LU_REQ(LU_Type_IMSI_Attach, ts_MI_LV(ts_MI_IMSI(imsi)))));
617 return l3_payload;
618}
619
Harald Weltea4ca4462018-02-09 00:17:14 +0100620type component test_CT extends CTRL_Adapter_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600621 /* Array of per-BTS/TRX state */
622 var BTS_State bts[NUM_BTS][NUM_TRX];
Harald Welte89ab1912018-02-23 18:56:29 +0100623 /* RSL common Channel Port (for RSL_Emulation) */
624 port RSL_CCHAN_PT RSL_CCHAN[NUM_BTS];
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600625 /* array of per-BTS/TRX RSL test ports */
626 port IPA_RSL_PT IPA_RSL[NUM_BTS][NUM_TRX];
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100627 port IPA_CODEC_PT IPA; /* Required for compilation of TC_rsl_unknown_unit_id() */
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +0200628 /* CTRL muxed over IPA in SCCPlite conn BSC<->MSC (or BSC-NAT) */
629 port IPA_CTRL_PT SCCPLITE_IPA_CTRL;
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200630 /* Configure/manage IPA_Emulation per-BTS/TRX port: */
631 port IPA_CFG_PT IPA_CFG_PORT[NUM_BTS][NUM_TRX];
Harald Weltea5d2ab22017-12-09 14:21:42 +0100632
Pau Espin Pedrol3c630532022-10-20 19:00:11 +0200633 var MGCP_Emulation_CT vc_MGCP[NUM_MGW];
634 var integer g_nr_mgw; /* number of vc_MGCP to initialize */
Harald Weltebc03c762018-02-12 18:09:38 +0100635 port TELNETasp_PT BSCVTY;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100636
Daniel Willmannebdecc02020-08-12 15:30:17 +0200637 /* StatsD */
638 var StatsD_Checker_CT vc_STATSD;
639
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200640 var RAN_Adapter g_bssap[NUM_MSC];
Harald Welte47cd0e32020-08-21 12:39:11 +0200641 var BSSAP_LE_Adapter g_bssap_le;
Harald Weltea4ca4462018-02-09 00:17:14 +0100642 /* for old legacy-tests only */
643 port BSSAP_CODEC_PT BSSAP;
Harald Welte47cd0e32020-08-21 12:39:11 +0200644 port BSSAP_LE_CODEC_PT BSSAP_LE;
Harald Weltea4ca4462018-02-09 00:17:14 +0100645
Harald Welte21b46bd2017-12-17 19:46:32 +0100646 /* are we initialized yet */
Harald Welte28d943e2017-11-25 15:00:50 +0100647 var boolean g_initialized := false;
Harald Welte21b46bd2017-12-17 19:46:32 +0100648
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200649 /* Osmux is enabled through VTY */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200650 var boolean g_osmux_enabled_cn := false;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +0200651 var boolean g_osmux_enabled_bts := false;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200652
Pau Espin Pedrolc675b612020-01-09 19:55:40 +0100653 /*Configure T(tias) over VTY, seconds */
654 var integer g_bsc_sccp_timer_ias := 7 * 60;
655 /*Configure T(tiar) over VTY, seconds */
656 var integer g_bsc_sccp_timer_iar := 15 * 60;
657
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +0200658 /* global test case guard timer (actual timeout value is set in f_init()) */
Harald Welteae026692017-12-09 01:03:01 +0100659 timer T_guard := 30.0;
660
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200661 var CounterNameValsList g_ctr_msc;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000662 var CounterNameValsList g_ctr_bsc;
663 var CounterNameValsList g_ctr_bts;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200664
665 /* System Information bytes as received during RSL startup, for each RSL[idx]. */
666 var SystemInformationConfig_list g_system_information := {};
Harald Welte28d943e2017-11-25 15:00:50 +0100667}
668
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200669type record of charstring phys_chan_configs;
Harald Welte28d943e2017-11-25 15:00:50 +0100670modulepar {
Harald Welte21b46bd2017-12-17 19:46:32 +0100671 /* IP address at which the BSC can be reached */
Harald Welte696ddb62017-12-08 14:01:43 +0100672 charstring mp_bsc_ip := "127.0.0.1";
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100673 /* port number to which to establish the IPA OML connections */
674 integer mp_bsc_oml_port := 3002;
Harald Welte21b46bd2017-12-17 19:46:32 +0100675 /* port number to which to establish the IPA RSL connections */
Harald Welte696ddb62017-12-08 14:01:43 +0100676 integer mp_bsc_rsl_port := 3003;
Harald Welte21b46bd2017-12-17 19:46:32 +0100677 /* port number to which to establish the IPA CTRL connection */
Harald Welte96c94412017-12-09 03:12:45 +0100678 integer mp_bsc_ctrl_port := 4249;
Daniel Willmannebdecc02020-08-12 15:30:17 +0200679 /* port number to which to listen for STATSD metrics */
680 integer mp_bsc_statsd_port := 8125;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100681 /* IP address at which the test binds */
682 charstring mp_test_ip := "127.0.0.1";
Harald Weltea4ca4462018-02-09 00:17:14 +0100683
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200684 RAN_Configurations mp_bssap_cfg := {
685 {
686 transport := BSSAP_TRANSPORT_AoIP,
687 sccp_service_type := "mtp3_itu",
688 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
689 own_pc := 185, /* 0.23.1 first MSC emulation */
690 own_ssn := 254,
691 peer_pc := 187, /* 0.23.3 osmo-bsc */
692 peer_ssn := 254,
693 sio := '83'O,
Harald Weltecb0cc432020-06-21 19:42:31 +0200694 rctx := 1
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200695 },
696 {
697 transport := BSSAP_TRANSPORT_AoIP,
698 sccp_service_type := "mtp3_itu",
699 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
700 own_pc := 2, /* 0.0.2 second MSC emulation */
701 own_ssn := 254,
702 peer_pc := 187, /* 0.23.3 osmo-bsc */
703 peer_ssn := 254,
704 sio := '83'O,
705 rctx := 2
706 },
707 {
708 transport := BSSAP_TRANSPORT_AoIP,
709 sccp_service_type := "mtp3_itu",
710 sctp_addr := { 23907, "127.0.0.1", 2905, "127.0.0.1" },
711 own_pc := 3, /* 0.0.3 third MSC emulation */
712 own_ssn := 254,
713 peer_pc := 187, /* 0.23.3 osmo-bsc */
714 peer_ssn := 254,
715 sio := '83'O,
716 rctx := 3
717 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100718 };
Pau Espin Pedrol58cf6822019-05-28 18:11:33 +0200719
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200720 /* Must match per BTS config in osmo-bsc.cfg */
721 phys_chan_configs phys_chan_config := {
722 "CCCH+SDCCH4+CBCH",
723 "TCH/F",
724 "TCH/F",
725 "TCH/F",
726 "TCH/F",
Vadim Yanitskiy343c9eb2021-07-16 18:36:01 +0600727 "TCH/H",
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200728 "PDCH",
729 "PDCH"
730 };
731
Harald Welte47cd0e32020-08-21 12:39:11 +0200732 BSSAP_LE_Configuration mp_bssap_le_cfg := {
733 sccp_service_type := "mtp3_itu",
734 sctp_addr := { 23908, "127.0.0.1", 2905, "127.0.0.1" },
Neels Hofmeyrac086c12020-09-18 23:46:42 +0200735 own_pc := 190, /* 0.23.6 SMLC emulation */
Harald Welte47cd0e32020-08-21 12:39:11 +0200736 own_ssn := 252, /* SMLC side SSN */
737 peer_pc := 187, /* 0.23.3 osmo-bsc */
738 peer_ssn := 250, /* BSC side SSN */
739 sio := '83'O,
740 rctx := 6
741 };
Neels Hofmeyrcfe44062020-10-15 02:28:08 +0200742 boolean mp_enable_lcs_tests := true;
Harald Welte47cd0e32020-08-21 12:39:11 +0200743
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100744 /* Value set in osmo-bsc.cfg "ms max power" */
745 uint8_t mp_exp_ms_power_level := 7;
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600746
747 /* Whether to check for memory leaks */
748 boolean mp_verify_talloc_count := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100749}
750
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200751friend function f_gen_test_hdlr_pars(integer bssap_idx := 0) return TestHdlrParams {
Philipp Maier48604732018-10-09 15:00:37 +0200752
753 var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200754 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier48604732018-10-09 15:00:37 +0200755 pars.aoip := true;
756 } else {
757 pars.aoip := false;
758 }
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100759 pars.exp_ms_power_level := mp_exp_ms_power_level;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200760 pars.mscpool.bssap_idx := bssap_idx;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600761 pars.expect_tsc := c_BtsParams[0].tsc;
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300762 pars.imsi := f_rnd_imsi('00101'H);
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +0100763 pars.imei := f_rnd_imei('00101'H);
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300764
765 log(testcasename(), ": using IMSI ", pars.imsi);
Neels Hofmeyrb5b7a6e2021-06-04 19:03:45 +0200766
Philipp Maier48604732018-10-09 15:00:37 +0200767 return pars;
768}
769
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200770/* Convenience functions for rate counters using g_ctr_msc. */
771
772private function f_ctrs_msc_init(integer mscs_count := NUM_MSC, CounterNameVals counternames := counternames_msc_mscpool) runs on test_CT {
773 g_ctr_msc := f_counter_name_vals_get_n(IPA_CTRL, "msc", mscs_count, counternames);
774 log("initial msc rate counters: ", g_ctr_msc);
775}
776
777private function f_ctrs_msc_add(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr9656e922020-06-30 01:27:01 +0200778 f_counter_name_vals_list_add(g_ctr_msc, msc_nr, countername, val);
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200779}
780
781/* f_ctrs_msc_init();
782 * f_do_thing(on_msc := 0);
783 * f_do_thing(on_msc := 0);
784 * f_do_other(on_msc := 1);
785 * f_ctrs_msc_add(0, "thing", 2);
786 * f_ctrs_msc_add(1, "other");
787 * f_ctrs_msc_verify();
788 */
789private function f_ctrs_msc_verify() runs on test_CT {
790 log("verifying msc rate counters: ", g_ctr_msc);
791 f_counter_name_vals_expect_n(IPA_CTRL, "msc", g_ctr_msc);
792}
793
794/* convenience: f_ctrs_msc_add() and f_ctrs_msc_verify() in one call.
795 * f_ctrs_msc_init();
796 * f_do_thing(on_msc := 0);
797 * f_do_thing(on_msc := 0);
798 * f_do_thing(on_msc := 0);
799 * f_ctrs_msc_expect(0, "thing", 3);
800 */
801private function f_ctrs_msc_expect(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
802 f_ctrs_msc_add(msc_nr, countername, val);
803 f_ctrs_msc_verify();
804}
805
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000806/* Convenience functions for rate counters using g_ctr_bts, always also including g_ctr_bsc. */
807
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100808private function f_ctrs_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000809 g_ctr_bts := f_counter_name_vals_get_n(IPA_CTRL, "bts", bts_count, counternames);
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100810 log("initial bts rate counters: ", g_ctr_bts);
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100811}
812
813function f_ctrs_bsc_and_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
814 f_ctrs_bts_init(bts_count, counternames);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000815 f_ctrs_bsc_init(counternames);
816}
817
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100818private function f_ctrs_bsc_and_bts_handover_init(integer bts_count := NUM_BTS) runs on test_CT {
819 var CounterNameVals bts_names := counternames_bsc_bts_handover & counternames_bts_handover;
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100820 f_ctrs_bts_init(bts_count, bts_names);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100821 f_ctrs_bsc_init(counternames_bsc_bts_handover);
822}
823
824private function f_ctrs_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000825 f_counter_name_vals_list_add(g_ctr_bts, bts_nr, countername, val);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100826}
827
828private function f_ctrs_bsc_and_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
829 f_ctrs_bts_add(bts_nr, countername, val);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000830 f_ctrs_bsc_add(countername, val);
831}
832
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100833function f_ctrs_bts_verify() runs on test_CT {
834 f_counter_name_vals_expect_n(IPA_CTRL, "bts", g_ctr_bts);
835}
836
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000837/* f_ctrs_bsc_and_bts_init();
838 * f_do_thing(on_bts := 0);
839 * f_do_thing(on_bts := 0);
840 * f_do_other(on_bts := 1);
841 * f_ctrs_bsc_and_bts_add(0, "thing", 2);
842 * f_ctrs_bsc_and_bts_add(1, "other");
843 * f_ctrs_bsc_and_bts_verify();
844 */
845private function f_ctrs_bsc_and_bts_verify() runs on test_CT {
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100846 f_ctrs_bts_verify();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000847 f_ctrs_bsc_verify();
848}
849
850/* convenience: f_ctrs_bsc_and_bts_add() and f_ctrs_bsc_and_bts_verify() in one call.
851 * f_ctrs_bsc_and_bts_init();
852 * f_do_thing(on_bts := 0);
853 * f_do_thing(on_bts := 0);
854 * f_do_thing(on_bts := 0);
855 * f_ctrs_bsc_and_bts_expect(0, "thing", 3);
856 */
857private function f_ctrs_bsc_and_bts_expect(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
858 f_ctrs_bsc_and_bts_add(bts_nr, countername, val);
859 f_ctrs_bsc_and_bts_verify();
860}
861
862
863/* Convenience functions for rate counters using g_ctr_bsc. */
864
865private function f_ctrs_bsc_init(CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
866 g_ctr_bsc := f_counter_name_vals_get_n(IPA_CTRL, "bsc", 1, counternames);
867 log("initial bsc rate counters: ", g_ctr_bsc);
868}
869
870private function f_ctrs_bsc_add(charstring countername, integer val := 1) runs on test_CT {
871 f_counter_name_vals_list_add(g_ctr_bsc, 0, countername, val);
872}
873
874/* f_ctrs_bsc_init();
875 * f_do_thing();
876 * f_do_thing();
877 * f_do_other();
878 * f_ctrs_bsc_add("thing", 2);
879 * f_ctrs_bsc_add("other");
880 * f_ctrs_bsc_verify();
881 */
882private function f_ctrs_bsc_verify() runs on test_CT {
883 f_counter_name_vals_expect_n(IPA_CTRL, "bsc", g_ctr_bsc);
884}
885
886/* convenience: f_ctrs_bsc_add() and f_ctrs_bsc_verify() in one call.
887 * f_ctrs_bsc_init();
888 * f_do_thing();
889 * f_ctrs_bsc_expect("thing", 1);
890 */
891private function f_ctrs_bsc_expect(charstring countername, integer val := 1) runs on test_CT {
892 f_ctrs_bsc_add(countername, val);
893 f_ctrs_bsc_verify();
894}
895
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200896
Oliver Smith39f53072022-10-27 14:44:04 +0200897friend function f_shutdown_helper(boolean ho := false) runs on test_CT {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100898 /* Run the subscr and conn leak test only when the VTY is initialized */
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600899 if (BSCVTY.checkstate("Mapped") and mp_verify_talloc_count) {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100900 f_verify_talloc_count(BSCVTY, {"struct bsc_subscr", "struct gsm_subscriber_connection"});
901 }
902
Oliver Smith39f53072022-10-27 14:44:04 +0200903 /* Reset handover related configuration */
904 if (ho) {
905 f_bts_0_cfg(BSCVTY,
906 {"no neighbors",
907 "neighbor-list mode manual-si5",
908 "neighbor-list add arfcn 100",
909 "neighbor-list add arfcn 200",
910 "si5 neighbor-list add arfcn 10",
911 "si5 neighbor-list add arfcn 20",
912 "handover algorithm 1"});
913 }
914
Daniel Willmann637ef6c2018-07-25 10:49:09 +0200915 all component.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100916 setverdict(pass);
Daniel Willmannafce8662018-07-06 23:11:32 +0200917 mtc.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100918}
919
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200920private function f_legacy_bssap_reset(integer bssap_idx := 0) runs on test_CT {
Harald Weltea4ca4462018-02-09 00:17:14 +0100921 var BSSAP_N_UNITDATA_ind ud_ind;
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200922 var boolean reset_received := false;
Harald Weltea4ca4462018-02-09 00:17:14 +0100923 timer T := 5.0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200924 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200925 ts_BSSMAP_Reset(0, g_osmux_enabled_cn)));
Harald Weltea4ca4462018-02-09 00:17:14 +0100926 T.start;
927 alt {
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200928 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[bssap_idx].sccp_addr_own, g_bssap[bssap_idx].sccp_addr_peer,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200929 tr_BSSMAP_ResetAck(g_osmux_enabled_cn))) {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200930 log("BSSMAP: Received RESET-ACK in response to RESET, we're ready to go!");
Harald Weltea4ca4462018-02-09 00:17:14 +0100931 }
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200932 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200933 log("BSSMAP: Respoding to inbound RESET with RESET-ACK");
Harald Weltea4ca4462018-02-09 00:17:14 +0100934 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200935 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200936 reset_received := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100937 repeat;
938 }
939 [] BSSAP.receive { repeat; }
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200940 [] T.timeout {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200941 log("BSSMAP: Timeout waiting for RESET-ACK after sending RESET");
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200942 /* If we received a RESET after ours was sent, it
943 may be a race condition where the other peer beacame
944 available after we sent it, but we are in a desired
945 state anyway, so go forward. */
946 if (not reset_received) {
947 setverdict(fail);
948 }
949 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100950 }
Harald Welte28d943e2017-11-25 15:00:50 +0100951}
952
Harald Welteae026692017-12-09 01:03:01 +0100953type record IPA_Client {
Harald Welte21b46bd2017-12-17 19:46:32 +0100954 /* IPA Emulation component reference */
Harald Welteae026692017-12-09 01:03:01 +0100955 IPA_Emulation_CT vc_IPA,
Harald Welte21b46bd2017-12-17 19:46:32 +0100956 /* Unit-ID and other CCM parameters to use for IPA client emulation */
Harald Welteae026692017-12-09 01:03:01 +0100957 IPA_CCM_Parameters ccm_pars,
Harald Welte21b46bd2017-12-17 19:46:32 +0100958 /* String identifier for this IPA Client */
Harald Welte624f9632017-12-16 19:26:04 +0100959 charstring id,
Harald Welte21b46bd2017-12-17 19:46:32 +0100960 /* Associated RSL Emulation Component (if any). Only used in "Handler mode" */
Harald Welte624f9632017-12-16 19:26:04 +0100961 RSL_Emulation_CT vc_RSL optional
Harald Welte28d943e2017-11-25 15:00:50 +0100962}
963
Harald Welte21b46bd2017-12-17 19:46:32 +0100964/*! Start the IPA/RSL related bits for one IPA_Client.
965 * \param clnt IPA_Client for which to establish
966 * \param bsc_host IP address / hostname of the BSC
967 * \param bsc_port TCP port number of the BSC
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600968 * \param idx BTS/TRX index values
Harald Welte21b46bd2017-12-17 19:46:32 +0100969 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600970function f_ipa_rsl_start(inout IPA_Client clnt, charstring bsc_host, PortNumber bsc_port,
971 BtsTrxIdx idx := {0, 0}, boolean handler_mode := false)
Harald Welte28d943e2017-11-25 15:00:50 +0100972runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +0100973 timer T := 10.0;
974
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600975 clnt.id := "IPA-BTS" & int2str(idx.bts) & "-TRX" & int2str(idx.trx) & "-RSL";
Harald Welte71389132021-12-09 21:58:18 +0100976 clnt.vc_IPA := IPA_Emulation_CT.create(clnt.id & "-IPA") alive;
Harald Welteae026692017-12-09 01:03:01 +0100977 clnt.ccm_pars := c_IPA_default_ccm_pars;
978 clnt.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600979 clnt.ccm_pars.unit_id := int2str(1234 + idx.bts) & "/0/" & int2str(idx.trx);
Harald Welte624f9632017-12-16 19:26:04 +0100980 if (handler_mode) {
Harald Welte71389132021-12-09 21:58:18 +0100981 clnt.vc_RSL := RSL_Emulation_CT.create(clnt.id & "-RSL") alive;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600982 connect(clnt.vc_RSL:CCHAN_PT, self:RSL_CCHAN[idx.bts]);
Harald Welte624f9632017-12-16 19:26:04 +0100983 }
Harald Welteae026692017-12-09 01:03:01 +0100984
985 map(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200986 connect(clnt.vc_IPA:CFG_PORT, self:IPA_CFG_PORT[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100987 if (handler_mode) {
988 connect(clnt.vc_IPA:IPA_RSL_PORT, clnt.vc_RSL:IPA_PT);
989 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600990 connect(clnt.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100991 }
Harald Welteae026692017-12-09 01:03:01 +0100992
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600993 var integer local_port := 10000 + idx.bts * 1000 + idx.trx;
994 clnt.vc_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", local_port, clnt.ccm_pars));
Harald Welte624f9632017-12-16 19:26:04 +0100995 if (handler_mode) {
996 clnt.vc_RSL.start(RSL_Emulation.main());
997 return;
998 }
Harald Welteae026692017-12-09 01:03:01 +0100999
1000 /* wait for IPA RSL link to connect and send ID ACK */
1001 T.start;
1002 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001003 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) {
Harald Welteae026692017-12-09 01:03:01 +01001004 T.stop;
Harald Welteae026692017-12-09 01:03:01 +01001005 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001006 [] IPA_RSL[idx.bts][idx.trx].receive(ASP_IPA_Event:?) { repeat }
1007 [] IPA_RSL[idx.bts][idx.trx].receive { repeat }
Harald Welteae026692017-12-09 01:03:01 +01001008 [] T.timeout {
Harald Welte96c94412017-12-09 03:12:45 +01001009 setverdict(fail, "Timeout RSL waiting for ASP_IPA_EVENT_ID_ACK");
Daniel Willmannafce8662018-07-06 23:11:32 +02001010 mtc.stop;
Harald Welteae026692017-12-09 01:03:01 +01001011 }
1012 }
1013}
1014
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001015function f_ipa_rsl_stop(inout IPA_Client clnt, BtsTrxIdx idx := {0, 0}) runs on test_CT {
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001016 var IPL4asp_Types.Result res := {
1017 errorCode := omit,
1018 connId := omit,
1019 os_error_code := omit,
1020 os_error_text := omit
1021 };
1022
Harald Welte12055472018-03-17 20:10:08 +01001023 if (not isbound(clnt) or not isbound(clnt.vc_IPA)) {
1024 return;
1025 }
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001026
1027 /* Alive components don't finish sockets (TCP FIN) when they are
1028 * stopped. Hence, we need to manually call close() on them to make sure
1029 * the IUT knows about it. */
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001030 f_ipa_cfg_disconnect(IPA_CFG_PORT[idx.bts][idx.trx], res);
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001031
Harald Welte12055472018-03-17 20:10:08 +01001032 clnt.vc_IPA.stop;
1033 if (isbound(clnt.vc_RSL)) {
1034 clnt.vc_RSL.stop;
1035 }
1036}
1037
Harald Welte21b46bd2017-12-17 19:46:32 +01001038/* Wait for the OML connection to be brought up by the external osmo-bts-omldummy */
Harald Weltea5d2ab22017-12-09 14:21:42 +01001039function f_wait_oml(integer bts_nr, charstring status, float secs_max) runs on test_CT {
1040 timer T := secs_max;
1041 T.start;
1042 while (true) {
1043 if (f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-connection-state") == status) {
1044 T.stop;
Harald Weltebd868bd2017-12-10 18:28:40 +01001045 /* the 'degraded' state exists from OML connection time, and we have to wait
1046 * until all MO's are initialized */
1047 T.start(1.0);
1048 T.timeout;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001049 return;
1050 }
Harald Weltef0d6ac62017-12-17 17:02:21 +01001051 f_sleep(0.1);
Harald Weltea5d2ab22017-12-09 14:21:42 +01001052 if (not T.running) {
Max99253902018-11-16 17:57:39 +01001053 setverdict(fail, "Timeout waiting for BTS" & int2str(bts_nr) & " oml-connection-state ", status);
Daniel Willmannafce8662018-07-06 23:11:32 +02001054 mtc.stop;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001055 }
1056 }
1057}
1058
Harald Welte21b46bd2017-12-17 19:46:32 +01001059/* global altstep for global guard timer; also takes care of responding RESET witH RESET-ACK */
Harald Welteae026692017-12-09 01:03:01 +01001060altstep as_Tguard() runs on test_CT {
Harald Welte60e823a2017-12-10 14:10:59 +01001061 var BSSAP_N_UNITDATA_ind ud_ind;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001062 [] T_guard.timeout {
1063 setverdict(fail, "Timeout of T_guard");
Daniel Willmannafce8662018-07-06 23:11:32 +02001064 mtc.stop;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001065 }
Harald Welte60e823a2017-12-10 14:10:59 +01001066 /* always respond with RESET ACK to RESET */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001067 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Harald Welte60e823a2017-12-10 14:10:59 +01001068 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001069 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Harald Welte69c1c262017-12-13 21:02:08 +01001070 repeat;
Harald Welte60e823a2017-12-10 14:10:59 +01001071 }
Harald Welte28d943e2017-11-25 15:00:50 +01001072}
1073
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001074altstep no_bssmap_reset() runs on test_CT {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001075 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001076 setverdict(fail, "unexpected BSSMAP Reset");
Daniel Willmannafce8662018-07-06 23:11:32 +02001077 mtc.stop;
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001078 }
1079}
1080
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001081function f_init_mgcp(integer mgw_nr, charstring id) runs on test_CT {
1082 id := id & "-MGCP-" & int2str(mgw_nr);
Daniel Willmann191e0d92018-01-17 12:44:35 +01001083
1084 var MGCPOps ops := {
1085 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
1086 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
1087 };
1088 var MGCP_conn_parameters mgcp_pars := {
1089 callagent_ip := mp_bsc_ip,
Harald Welte9e4273e2018-01-29 22:01:22 +01001090 callagent_udp_port := -1,
Daniel Willmann191e0d92018-01-17 12:44:35 +01001091 mgw_ip := mp_test_ip,
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001092 mgw_udp_port := 2427 + mgw_nr,
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02001093 /* Enable it for SCCPlite, since we have 2 MGCP sockets towards MGW (UDP one +
Pau Espin Pedrol36eeaf72022-10-20 16:50:31 +02001094 the one with MGCP over IPA forwarded from MSC one) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001095 multi_conn_mode := (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER)
Daniel Willmann191e0d92018-01-17 12:44:35 +01001096 };
1097
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001098 vc_MGCP[mgw_nr] := MGCP_Emulation_CT.create(id) alive;
1099 vc_MGCP[mgw_nr].start(MGCP_Emulation.main(ops, mgcp_pars, id));
Daniel Willmann191e0d92018-01-17 12:44:35 +01001100}
1101
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001102/* Enable or disable (current default) Osmux. When enabling, BSSMAP Reset
1103 * contains extra IE (OsmuxSupport) and osmo-bsc will handle AssignReq with
1104 * OsmuxCID IE.
1105 */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001106private function f_vty_allow_osmux_cn(boolean allow) runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001107 f_vty_enter_cfg_msc(BSCVTY, 0);
1108 if (allow) {
1109 f_vty_transceive(BSCVTY, "osmux on");
1110 } else {
1111 f_vty_transceive(BSCVTY, "osmux off");
1112 }
1113 f_vty_transceive(BSCVTY, "exit");
1114 f_vty_transceive(BSCVTY, "exit");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001115}
1116
Max2253c0b2018-11-06 19:28:05 +01001117function f_init_vty(charstring id := "foo") runs on test_CT {
Harald Welte94e0c342018-04-07 11:33:23 +02001118 if (BSCVTY.checkstate("Mapped")) {
1119 /* skip initialization if already executed once */
1120 return;
1121 }
Harald Weltebc03c762018-02-12 18:09:38 +01001122 map(self:BSCVTY, system:BSCVTY);
1123 f_vty_set_prompts(BSCVTY);
1124 f_vty_transceive(BSCVTY, "enable");
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01001125 f_cs7_inst_0_cfg(BSCVTY, {"sccp-timer ias " & int2str(g_bsc_sccp_timer_ias),
1126 "sccp-timer iar " & int2str(g_bsc_sccp_timer_iar)});
Harald Weltebc03c762018-02-12 18:09:38 +01001127}
1128
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +02001129friend function f_logp(TELNETasp_PT pt, charstring log_msg)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001130{
1131 // log on TTCN3 log output
1132 log(log_msg);
1133 // log in stderr log
Neels Hofmeyr8bdafe52021-12-14 17:25:48 +01001134 if (pt.checkstate("Mapped")) {
1135 f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
1136 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001137}
1138
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001139private function f_sysinfo_seen(integer rsl_idx, RSL_Message rsl) runs on test_CT
1140{
1141 if (rsl_idx >= lengthof(g_system_information)) {
1142 g_system_information[rsl_idx] := SystemInformationConfig_omit
1143 }
1144 f_sysinfo_dec_raw(g_system_information[rsl_idx], rsl);
1145}
1146
1147altstep as_catch_RSL_sysinfo(integer rsl_idx) runs on test_CT {
1148 var ASP_RSL_Unitdata rx_rsl_ud;
1149
1150 /* For handler_mode := false, receiving the RSL bootstrap messages directly on IPA_RSL */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001151 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001152 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1153 repeat;
1154 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001155 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001156 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1157 repeat;
1158 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001159 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001160 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1161 repeat;
1162 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001163 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001164 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1165 repeat;
1166 }
1167
1168 /* For handler_mode := true, receiving the RSL bootstrap messages via RSL_Emulation */
1169 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
1170 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1171 repeat;
1172 }
1173 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
1174 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1175 repeat;
1176 }
1177 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
1178 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1179 repeat;
1180 }
1181 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
1182 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1183 repeat;
1184 }
1185}
1186
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001187/* TODO: use BooleanList from COMMON/src/General_Types.ttcn */
1188private type record of boolean my_BooleanList;
1189
1190private function f_vty_msc_allow_attach(TELNETasp_PT pt, my_BooleanList allow_attach_list)
1191{
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001192 var charstring config := f_vty_transceive_ret(pt, "show running-config");
1193
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001194 for (var integer msc_nr := 0; msc_nr < sizeof(allow_attach_list); msc_nr := msc_nr+1) {
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001195 if (f_strstr(config, "\nmsc " & int2str(msc_nr) & "\n") < 0) {
1196 /* There is no 'msc N' for this msc_nr in the running config, so don't create an empty msc by
1197 * stepping into that config node. */
1198 log("msc ", msc_nr, " is not configured, skipping");
1199 continue;
1200 }
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001201 f_vty_enter_cfg_msc(pt, msc_nr);
1202 if (allow_attach_list[msc_nr]) {
1203 /* strict := false: ignore if osmo-bsc does not support this config option (latest build) */
1204 f_vty_transceive(pt, "allow-attach", strict := false);
1205 } else {
1206 f_vty_transceive(pt, "no allow-attach", strict := false);
1207 }
1208 f_vty_transceive(pt, "exit");
1209 f_vty_transceive(pt, "exit");
1210 }
1211}
1212
Harald Welte21b46bd2017-12-17 19:46:32 +01001213/* global initialization function
1214 * \param nr_bts Number of BTSs we should start/bring up
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001215 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false).
1216 * \param nr_msc Number of virtual MSCs to bring up to connect to osmo-bsc.
1217 */
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001218function f_init(integer nr_bts := NUM_BTS, boolean handler_mode := false,
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001219 integer nr_msc := 1, integer nr_mgw := 1, float guard_timeout := 30.0) runs on test_CT {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001220 var integer bssap_idx;
Harald Welte28d943e2017-11-25 15:00:50 +01001221
Harald Welteae026692017-12-09 01:03:01 +01001222 if (g_initialized) {
1223 return;
Harald Welte28d943e2017-11-25 15:00:50 +01001224 }
Harald Welteae026692017-12-09 01:03:01 +01001225 g_initialized := true;
1226
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +02001227 T_guard.start(guard_timeout);
Daniel Willmanne68f9272018-11-27 15:15:28 +01001228 activate(as_Tguard());
1229
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001230 f_init_vty("VirtMSC");
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001231 f_vty_allow_osmux_cn(g_osmux_enabled_cn);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001232
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001233 var my_BooleanList allow_attach := { false, false, false };
Daniel Willmannebdecc02020-08-12 15:30:17 +02001234 f_init_statsd("VirtMSC", vc_STATSD, mp_test_ip, mp_bsc_statsd_port);
1235
Neels Hofmeyr9db8e0e2021-08-23 20:45:58 +02001236 /* Make sure each MSC's internal state is "DISCONNECTED" at first */
1237 for (bssap_idx := 0; bssap_idx < NUM_MSC; bssap_idx := bssap_idx+1) {
1238 f_vty_transceive(BSCVTY, "msc " & int2str(bssap_idx) & " bssmap reset", strict := false);
1239 }
1240
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001241 for (bssap_idx := 0; bssap_idx < nr_msc; bssap_idx := bssap_idx+1) {
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001242 allow_attach[bssap_idx] := true;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001243 /* Call a function of our 'parent component' RAN_Adapter_CT to start the
1244 * MSC-side BSSAP emulation */
1245 if (handler_mode) {
1246 var RanOps ranops := MSC_RanOps;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001247 ranops.use_osmux := g_osmux_enabled_cn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001248 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", ranops);
1249 connect(self:SCCPLITE_IPA_CTRL, g_bssap[bssap_idx].vc_RAN:CTRL_CLIENT);
1250 f_ran_adapter_start(g_bssap[bssap_idx]);
1251 } else {
1252 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", omit);
1253 connect(self:BSSAP, g_bssap[bssap_idx].vc_SCCP:SCCP_SP_PORT);
1254 f_ran_adapter_start(g_bssap[bssap_idx]);
1255 f_legacy_bssap_reset();
1256 }
Harald Welte67089ee2018-01-17 22:19:03 +01001257 }
Harald Welted5833a82018-05-27 16:52:56 +02001258
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02001259 if (mp_enable_lcs_tests) {
1260 if (handler_mode) {
1261 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", SMLC_BssapLeOps);
1262 } else {
1263 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", omit);
1264 connect(self:BSSAP_LE, g_bssap_le.vc_SCCP:SCCP_SP_PORT);
1265 }
1266 f_bssap_le_adapter_start(g_bssap_le);
Harald Welte47cd0e32020-08-21 12:39:11 +02001267 }
Harald Welte47cd0e32020-08-21 12:39:11 +02001268
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001269 /* start the test with exactly all enabled MSCs allowed to attach */
1270 f_vty_msc_allow_attach(BSCVTY, allow_attach);
1271
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01001272 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Harald Welte28d943e2017-11-25 15:00:50 +01001273
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001274 g_nr_mgw := nr_mgw;
1275 for (var integer i := 0; i < g_nr_mgw; i := i+1) {
1276 f_init_mgcp(i, "VirtMGW");
1277 }
Daniel Willmann191e0d92018-01-17 12:44:35 +01001278
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001279 for (var integer i := 0; i < nr_bts; i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001280 f_init_bts(i, c_BtsParams[i].trx_num, handler_mode);
Harald Welte696ddb62017-12-08 14:01:43 +01001281 }
Neels Hofmeyr9c0f9c82022-01-23 01:20:28 +01001282
1283 /* Emit a marker to appear in the SUT's own logging output */
1284 f_logp(BSCVTY, testcasename() & "() start");
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001285}
Harald Welte696ddb62017-12-08 14:01:43 +01001286
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001287function f_init_bts(integer bts_idx := 0,
1288 integer trx_num := NUM_TRX_CFG,
1289 boolean handler_mode := false)
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001290runs on test_CT {
1291 /* wait until osmo-bts-omldummy has respawned */
1292 f_wait_oml(bts_idx, "degraded", 5.0);
1293
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001294 /* start RSL connection(s) */
1295 for (var integer trx_idx := 0; trx_idx < trx_num; trx_idx := trx_idx + 1) {
1296 f_ipa_rsl_start(bts[bts_idx][trx_idx].rsl,
1297 mp_bsc_ip, mp_bsc_rsl_port,
1298 {bts_idx, trx_idx}, handler_mode);
1299 }
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001300 /* wait until BSC tells us "connected" */
1301 f_wait_oml(bts_idx, "connected", 5.0);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001302
1303 /* Set up BTS with VTY commands: */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01001304 f_vty_enter_cfg_bts(BSCVTY, bts_idx);
1305 if (g_osmux_enabled_bts) {
1306 f_vty_transceive(BSCVTY, "osmux on");
1307 } else {
1308 f_vty_transceive(BSCVTY, "osmux off");
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001309 }
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01001310 f_vty_transceive(BSCVTY, "end");
Harald Welte28d943e2017-11-25 15:00:50 +01001311}
1312
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001313function f_init_bts_and_check_sysinfo(integer bts_idx := 0,
1314 integer trx_num := NUM_TRX_CFG,
1315 boolean handler_mode := false,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001316 template SystemInformationConfig expect_si)
1317runs on test_CT {
1318 var default sysinfo := activate(as_catch_RSL_sysinfo(bts_idx));
1319
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001320 f_init_bts(bts_idx, trx_num, handler_mode);
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001321
1322 /* Give some time to (hopefully/most likely) collect all system informations from RSL startup.
1323 * We could stop as soon as all expected SI are received, but then we might miss SI that we don't expect and
1324 * that might be sent afterwards. So rather give a generous timeout and be quite sure to catch all SI.
1325 */
1326 f_sleep(5.0);
1327 log("RSL ", bts_idx, " SYSTEM INFORMATION: ", g_system_information[bts_idx]);
1328
1329 deactivate(sysinfo);
1330
1331 if (match(g_system_information[bts_idx], expect_si)) {
1332 setverdict(pass);
1333 } else {
1334 log("RSL ", bts_idx, ": EXPECTED SI: ", expect_si);
1335 log("RSL ", bts_idx, ": GOT SI: ", g_system_information[bts_idx]);
1336 setverdict(fail, "received SI does not match expectations");
1337 return;
1338 }
1339}
1340
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001341/* expect to receive a RSL message matching a specified template on a given BTS / TRX */
1342function f_exp_ipa_rx(template (present) RSL_Message t_rx,
1343 BtsTrxIdx idx := {0, 0},
1344 float Tval := 2.0)
Harald Welteae026692017-12-09 01:03:01 +01001345runs on test_CT return RSL_Message {
1346 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001347 timer T := Tval;
Harald Welteae026692017-12-09 01:03:01 +01001348
1349 T.start;
1350 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001351 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Harald Welteae026692017-12-09 01:03:01 +01001352 T.stop;
1353 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001354 [] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
Harald Welteb2917702017-12-10 15:48:52 +01001355 [] T.timeout {
1356 setverdict(fail, "Timeout expecting ", t_rx);
Daniel Willmannafce8662018-07-06 23:11:32 +02001357 mtc.stop;
Harald Welteb2917702017-12-10 15:48:52 +01001358 }
Harald Welteae026692017-12-09 01:03:01 +01001359 }
1360 return rx_rsl_ud.rsl;
1361}
1362
Harald Welte21b46bd2017-12-17 19:46:32 +01001363/* helper function to transmit RSL on a given BTS/stream */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001364function f_ipa_tx(template (value) RSL_Message t_tx,
1365 BtsTrxIdx idx := {0, 0},
1366 IpaStreamId sid := IPAC_PROTO_RSL_TRX0)
Harald Welteae026692017-12-09 01:03:01 +01001367runs on test_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001368 IPA_RSL[idx.bts][idx.trx].send(ts_ASP_RSL_UD(t_tx, sid));
Harald Welteae026692017-12-09 01:03:01 +01001369}
1370
1371
Harald Welte4003d112017-12-09 22:35:39 +01001372/* verify we get a CHAN_ACT after CHAN RQD */
Harald Welteae026692017-12-09 01:03:01 +01001373testcase TC_chan_act_noreply() runs on test_CT {
1374 var BSSAP_N_UNITDATA_ind ud_ind;
Harald Welte930d0a72018-03-22 22:08:40 +01001375 var RSL_Message rsl_unused;
Harald Welte28d943e2017-11-25 15:00:50 +01001376
Harald Welte89d42e82017-12-17 16:42:41 +01001377 f_init(1);
Harald Welte28d943e2017-11-25 15:00:50 +01001378
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001379 f_ipa_tx(ts_RSL_CHAN_RQD('23'O, 23));
1380 rsl_unused := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001381 f_shutdown_helper();
Harald Welte28d943e2017-11-25 15:00:50 +01001382}
1383
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001384const CounterNameVals counternames_bts_chreq := {
1385 { "chreq:total", 0 },
1386 { "chreq:attempted_emerg", 0 },
1387 { "chreq:attempted_call", 0 },
1388 { "chreq:attempted_location_upd", 0 },
1389 { "chreq:attempted_pag", 0 },
1390 { "chreq:attempted_pdch", 0 },
1391 { "chreq:attempted_other", 0 },
1392 { "chreq:attempted_unknown", 0 },
1393 { "chreq:successful", 0 },
1394 { "chreq:successful_emerg", 0 },
1395 { "chreq:successful_call", 0 },
1396 { "chreq:successful_location_upd", 0 },
1397 { "chreq:successful_pag", 0 },
1398 { "chreq:successful_pdch", 0 },
1399 { "chreq:successful_other", 0 },
1400 { "chreq:successful_unknown", 0 },
1401 { "chreq:no_channel", 0 },
1402 { "chreq:max_delay_exceeded", 0 }
1403};
1404
1405/* verify the "chreq:*" counters */
1406private function f_chan_act_counter(OCT1 ra, charstring chreq_ctr_suffix) runs on test_CT
1407{
1408 var GsmFrameNumber fn := 23;
1409
1410 f_logp(BSCVTY, "f_chan_act_counter(" & chreq_ctr_suffix & ")");
1411
1412 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001413 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn));
1414 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001415 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1416
1417 f_ctrs_bts_add(0, "chreq:total");
1418 f_ctrs_bts_add(0, "chreq:attempted_" & chreq_ctr_suffix);
1419 f_ctrs_bts_verify();
1420
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001421 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
1422 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001423
1424 f_ctrs_bts_add(0, "chreq:successful");
1425 f_ctrs_bts_add(0, "chreq:successful_" & chreq_ctr_suffix);
1426 f_ctrs_bts_verify();
1427
1428 /* test is done, release RSL Conn Fail Ind to clean up */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001429 f_ipa_tx(ts_RSL_CONN_FAIL_IND(chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1430 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
1431 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001432 f_sleep(1.0);
1433}
1434
Harald Welte4003d112017-12-09 22:35:39 +01001435testcase TC_chan_act_counter() runs on test_CT {
1436 var BSSAP_N_UNITDATA_ind ud_ind;
1437 var integer chreq_total;
Harald Welte930d0a72018-03-22 22:08:40 +01001438 var RSL_Message rsl_unused;
Harald Welte4003d112017-12-09 22:35:39 +01001439
Harald Welte89d42e82017-12-17 16:42:41 +01001440 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001441
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001442 f_vty_allow_emerg_bts(true, 0);
1443
1444 f_ctrs_bts_init(1, counternames_bts_chreq);
1445
1446 /* emergency call: RA & 0xe0 == 0xa0 --> CHREQ_T_EMERG_CALL */
1447 f_chan_act_counter('a3'O, "emerg");
1448
1449 /* voice TCH/H: RA & 0xf0 == 0x40 --> CHREQ_T_VOICE_CALL_TCH_H */
1450 f_chan_act_counter('43'O, "call");
1451
1452 /* LU: RA & 0xf0 == 0x00 --> CHREQ_T_LOCATION_UPD */
1453 f_chan_act_counter('03'O, "location_upd");
1454
1455 /* Paging: RA & 0xf0 == 0x20 --> CHREQ_T_PAG_R_TCH_F */
1456 f_chan_act_counter('23'O, "pag");
1457 /* Paging: RA & 0xf0 == 0x30 --> CHREQ_T_PAG_R_TCH_FH */
1458 f_chan_act_counter('33'O, "pag");
1459
1460 /* LU: RA & 0xfc == 0x78 --> CHREQ_T_PDCH_TWO_PHASE */
1461 /* no PCU, so PDCH not allowed. Skip this test for now. */
1462 /* f_chan_act_counter('7b'O, "pdch"); */
1463
1464 /* LU: RA & 0xf0 == 0x10 --> CHREQ_T_SDCCH */
1465 f_chan_act_counter('13'O, "other");
Harald Welte4003d112017-12-09 22:35:39 +01001466
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001467 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001468}
1469
Harald Welteae026692017-12-09 01:03:01 +01001470/* CHAN RQD -> CHAN ACT -> CHAN ACT ACK -> RF CHAN REL */
Philipp Maier9c60a622020-07-09 15:08:46 +02001471private function f_TC_chan_act_ack_noest(OCT1 ra := '23'O) runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +01001472 var RSL_Message rx_rsl;
1473
Harald Welteae026692017-12-09 01:03:01 +01001474 /* Send CHAN RQD and wait for allocation; acknowledge it */
Philipp Maier9c60a622020-07-09 15:08:46 +02001475 var RslChannelNr chan_nr := f_chreq_act_ack(ra);
Harald Welteae026692017-12-09 01:03:01 +01001476
1477 /* expect BSC to disable the channel again if there's no RLL EST IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001478 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := T3101_MAX);
Harald Welteae026692017-12-09 01:03:01 +01001479
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001480 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001481}
1482
Philipp Maier9c60a622020-07-09 15:08:46 +02001483/* Normal variant */
1484testcase TC_chan_act_ack_noest() runs on test_CT {
Philipp Maieraf58db22020-08-12 17:24:40 +02001485 f_init(1);
Philipp Maier9c60a622020-07-09 15:08:46 +02001486 f_TC_chan_act_ack_noest();
1487}
1488
1489/* Emergency call variant */
1490testcase TC_chan_act_ack_noest_emerg() runs on test_CT {
1491 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
Philipp Maieraf58db22020-08-12 17:24:40 +02001492 f_init(1);
1493 f_vty_allow_emerg_bts(true, 0);
Philipp Maier9c60a622020-07-09 15:08:46 +02001494 f_TC_chan_act_ack_noest(ra := 'A5'O);
1495}
1496
Philipp Maier606f07d2020-08-12 17:21:58 +02001497/* Emergency call variant, but emergency calls are not allowed */
1498testcase TC_chan_rqd_emerg_deny() runs on test_CT {
1499 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
1500
1501 var RSL_Message rx_rsl;
1502 var GsmRrMessage rr;
1503
1504 f_init(1);
1505 f_vty_allow_emerg_bts(false, 0);
1506
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001507 IPA_RSL[0][0].clear;
1508 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier606f07d2020-08-12 17:21:58 +02001509
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001510 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Philipp Maier606f07d2020-08-12 17:21:58 +02001511 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
1512 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1513 setverdict(pass);
1514 } else {
1515 setverdict(fail, "immediate assignment not rejected");
1516 }
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01001517
1518 f_shutdown_helper();
Philipp Maier606f07d2020-08-12 17:21:58 +02001519}
1520
Harald Welteae026692017-12-09 01:03:01 +01001521/* Test behavior if MSC never answers to CR */
1522testcase TC_chan_act_ack_est_ind_noreply() runs on test_CT {
Harald Weltef77aef62018-01-28 15:35:42 +01001523 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
1524 var IpaStreamId sid := IPAC_PROTO_RSL_TRX0;
Harald Welteae026692017-12-09 01:03:01 +01001525 var RSL_Message rx_rsl;
Harald Weltef77aef62018-01-28 15:35:42 +01001526 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001527 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welteae026692017-12-09 01:03:01 +01001528
Harald Welte89d42e82017-12-17 16:42:41 +01001529 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001530
1531 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001532 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001533
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001534 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welteae026692017-12-09 01:03:01 +01001535
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001536 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload)));
Harald Welteae026692017-12-09 01:03:01 +01001537
1538 /* expect BSC to disable the channel again if there's no response from MSC */
Harald Weltef77aef62018-01-28 15:35:42 +01001539 /* MS waits 20s (T3210) at LU; 10s (T3230) at CM SERV REQ and 5s (T3220) AT detach */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001540 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001541 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001542}
1543
1544/* Test behavior if MSC answers with CREF to CR */
1545testcase TC_chan_act_ack_est_ind_refused() runs on test_CT {
1546 var BSSAP_N_CONNECT_ind rx_c_ind;
1547 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001548 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welteae026692017-12-09 01:03:01 +01001549
Harald Welte89d42e82017-12-17 16:42:41 +01001550 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001551
1552 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001553 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001554
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001555 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welteae026692017-12-09 01:03:01 +01001556
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001557 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Harald Welteae026692017-12-09 01:03:01 +01001558 BSSAP.send(ts_BSSAP_DISC_req(rx_c_ind.connectionId, 0));
1559
1560 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001561 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001562 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001563}
1564
Harald Welte618ef642017-12-14 14:58:20 +01001565/* CHAN RQD -> CHAN ACT -> CHAN ACT NACK -> RF CHAN REL */
1566testcase TC_chan_act_nack() runs on test_CT {
1567 var RSL_Message rx_rsl;
1568 var integer chact_nack;
1569
Harald Welte89d42e82017-12-17 16:42:41 +01001570 f_init(1);
Harald Welte618ef642017-12-14 14:58:20 +01001571
1572 chact_nack := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack");
1573
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001574 f_ipa_tx(ts_RSL_CHAN_RQD('33'O, 33));
1575 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Harald Welte618ef642017-12-14 14:58:20 +01001576 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1577
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001578 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte618ef642017-12-14 14:58:20 +01001579
1580 /* wait for some time to hope the NACK arrives before the CTRL GET below */
1581 f_sleep(0.5);
1582
1583 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack", chact_nack+1);
1584
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001585 f_shutdown_helper();
Harald Welte618ef642017-12-14 14:58:20 +01001586}
1587
Harald Welte799c97b2017-12-14 17:50:30 +01001588/* Test for channel exhaustion due to RACH overload */
1589testcase TC_chan_exhaustion() runs on test_CT {
1590 var ASP_RSL_Unitdata rsl_ud;
1591 var integer i;
1592 var integer chreq_total, chreq_nochan;
1593
Harald Welte89d42e82017-12-17 16:42:41 +01001594 f_init(1);
Harald Welte799c97b2017-12-14 17:50:30 +01001595
1596 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
1597 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
1598
Neels Hofmeyr85fa37f2021-10-06 13:50:38 +02001599 /* GSM 44.018 Table 9.1.8.2:
Pau Espin Pedrolfe200d72018-12-10 12:41:04 +01001600 * RA = '33'O -> Establishment cause = 0011xxxx (MS dual rate capable and asks for "TCH/H or TCH/F").
1601 * With current setup, expect 4xSDCCH + 4xTCH/F + 1xTCH/H to succeed */
Philipp Maiercb6cc482018-03-26 13:08:00 +02001602 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolfe200d72018-12-10 12:41:04 +01001603 var RslChannelNr chan_nr := f_chreq_act_ack('33'O, i);
Harald Welte799c97b2017-12-14 17:50:30 +01001604 }
1605
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001606 IPA_RSL[0][0].clear;
Harald Welte799c97b2017-12-14 17:50:30 +01001607
Harald Weltedd8cbf32018-01-28 12:07:52 +01001608 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001609 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
Harald Welte799c97b2017-12-14 17:50:30 +01001610
1611 /* now expect additional channel activations to fail */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001612 f_ipa_tx(ts_RSL_CHAN_RQD('42'O, 42));
Harald Welte799c97b2017-12-14 17:50:30 +01001613
1614 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001615 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV))) {
Harald Welte799c97b2017-12-14 17:50:30 +01001616 setverdict(fail, "Received CHAN ACT ACK without resources?!?");
1617 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001618 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) -> value rsl_ud {
Harald Welte799c97b2017-12-14 17:50:30 +01001619 var GsmRrMessage rr;
1620 /* match on IMM ASS REJ */
1621 rr := dec_GsmRrMessage(rsl_ud.rsl.ies[1].body.full_imm_ass_info.payload);
1622 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1623 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001624 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS+1);
Harald Welte799c97b2017-12-14 17:50:30 +01001625 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel",
1626 chreq_nochan+1);
1627 setverdict(pass);
1628 } else {
1629 repeat;
1630 }
1631 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001632 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte799c97b2017-12-14 17:50:30 +01001633 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001634 f_shutdown_helper();
Harald Welte799c97b2017-12-14 17:50:30 +01001635}
1636
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001637/* Test channel deactivation due to silence from MS */
1638testcase TC_chan_deact_silence() runs on test_CT {
1639 var RslChannelNr chan_nr;
1640
1641 f_init(1);
1642
1643 /* Request for a dedicated channel */
1644 chan_nr := f_chreq_act_ack('23'O);
1645
1646 /* Wait some time until the channel is released */
1647 f_sleep(2.0);
1648
1649 /* Expect CHANnel RELease */
1650 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001651 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001652 log("Received CHANnel RELease");
1653 setverdict(pass);
1654 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001655 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001656 /* See OS#3709, OsmoBSC should not send Immediate
1657 * Assignment Reject since a dedicated channel was
1658 * already allocated, and Immediate Assignment was
1659 * already sent. */
1660 setverdict(fail, "Unexpected Immediate Assignment!");
1661 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001662 [] IPA_RSL[0][0].receive {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001663 setverdict(fail, "Unexpected RSL message!");
1664 }
1665 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001666 f_shutdown_helper();
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001667}
1668
Harald Weltecfe2c962017-12-15 12:09:32 +01001669/***********************************************************************
1670 * Assignment Testing
1671 ***********************************************************************/
1672
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02001673/* Verify that the BSC refuses any BSSAP connection from the MSC (They are all BSC->MSC direction,
1674 * except for the inter-BSC handover, MT side) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001675testcase TC_outbound_connect(integer bssap_idx := 0) runs on test_CT {
Harald Welte89d42e82017-12-17 16:42:41 +01001676 f_init(1);
Harald Weltecfe2c962017-12-15 12:09:32 +01001677
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001678 BSSAP.send(ts_BSSAP_CONNECT_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
1679 2342, ts_BSSMAP_AssignmentReq));
Harald Weltecfe2c962017-12-15 12:09:32 +01001680 BSSAP.receive(tr_BSSAP_DISC_ind(2342, ?, ?));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001681 f_shutdown_helper();
Harald Weltecfe2c962017-12-15 12:09:32 +01001682}
1683
Harald Welte16a4adf2017-12-14 18:54:01 +01001684/* Test behavior if MSC answers with CREF to CR */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001685testcase TC_assignment_cic_only(integer bssap_idx := 0) runs on test_CT {
Harald Welte16a4adf2017-12-14 18:54:01 +01001686 var BSSAP_N_CONNECT_ind rx_c_ind;
1687 var RSL_Message rx_rsl;
1688 var DchanTuple dt;
1689
Harald Welte89d42e82017-12-17 16:42:41 +01001690 f_init(1);
Harald Welte16a4adf2017-12-14 18:54:01 +01001691
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001692 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001693 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte17b27da2018-05-25 20:33:53 +02001694 /* send assignment without AoIP IEs */
1695 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(ts_BSSMAP_IE_CIC(0, 1))));
1696 } else {
Pau Espin Pedrol35609792023-01-03 16:56:59 +01001697 /* Send assignment without CIC in IPA case */
Harald Welte17b27da2018-05-25 20:33:53 +02001698 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
1699 valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
1700 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(omit, tla)));
1701 }
Harald Welte16a4adf2017-12-14 18:54:01 +01001702 alt {
1703 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1704 setverdict(fail, "AoIP BSC cannot accept ASSIGNMENT without AoIP Transport IE");
1705 }
Harald Welte235ebf12017-12-15 14:18:16 +01001706 /* TODO: Actually expect GSM0808_CAUSE_REQ_A_IF_TYPE_NOT_SUPP */
Harald Welte16a4adf2017-12-14 18:54:01 +01001707 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1708 setverdict(pass);
1709 }
1710 [] BSSAP.receive { repeat; }
1711 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001712 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001713 f_shutdown_helper();
Harald Welte16a4adf2017-12-14 18:54:01 +01001714}
1715
Harald Welteed848512018-05-24 22:27:58 +02001716/* generate an assignment request for either AoIP or SCCPlite */
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001717function f_gen_ass_req(boolean osmux_enabled := false, integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4") return PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001718 var PDU_BSSAP ass_cmd;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001719 var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001720 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welteed848512018-05-24 22:27:58 +02001721 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001722 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001723 if (osmux_enabled) {
1724 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla, osmux_cid));
1725 } else {
1726 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla));
1727 }
Harald Welteed848512018-05-24 22:27:58 +02001728 } else {
1729 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrol096d73d2019-06-06 12:49:17 +02001730 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(cic, omit));
Harald Welteed848512018-05-24 22:27:58 +02001731 }
1732 return ass_cmd;
1733}
1734
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02001735function f_gen_handover_req(integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4",
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001736 template (value) BSSMAP_IE_CellIdentifier cell_id_source := ts_CellID_LAC_CI(1, 1),
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001737 template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit,
1738 template (omit) TestHdlrEncrParams enc := omit) return PDU_BSSAP {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001739 var PDU_BSSAP ho_req;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001740
1741 var BSSMAP_IE_EncryptionInformation encryptionInformation :=
1742 valueof(ts_BSSMAP_IE_EncrInfo('0000000000000000'O,'01'O));
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03001743 var template (omit) BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := omit;
1744 var template (omit) BSSMAP_IE_KC128 kc128 := omit;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001745 if (ispresent(enc)) {
1746 var TestHdlrEncrParams v_enc := valueof(enc);
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01001747 encryptionInformation := valueof(ts_BSSMAP_IE_EncrInfo(v_enc.enc_key, v_enc.enc_alg_permitted));
1748 if (ispresent(v_enc.enc_alg_chosen)) {
1749 chosenEncryptionAlgorithm := valueof(
1750 ts_BSSMAP_IE_ChosenEncryptionAlgorithm(int2oct(enum2int(
1751 f_cipher_mode_bssmap_to_rsl(v_enc.enc_alg_chosen)), 1)));
1752 }
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001753 if (ispresent(v_enc.enc_kc128)) {
1754 kc128 := ts_BSSMAP_IE_Kc128(v_enc.enc_kc128);
1755 }
1756 }
1757
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001758 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001759 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001760 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001761 ho_req := valueof(ts_BSSMAP_HandoverRequest(omit, tla,
1762 cell_id_source := cell_id_source,
1763 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001764 encryptionInformation := encryptionInformation,
1765 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
Neels Hofmeyr9fe13202022-03-04 00:05:43 +01001766 kC128 := kc128,
1767 /* on AoIP, allow "all" codecs (until we add more concise
1768 * tests) */
1769 codecList := ts_BSSMAP_IE_CodecList(
1770 {ts_CodecAMR_F, ts_CodecAMR_H,
1771 ts_CodecEFR, ts_CodecFR, ts_CodecHR})));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001772 } else {
1773 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001774 ho_req := valueof(ts_BSSMAP_HandoverRequest(cic, omit,
1775 cell_id_source := cell_id_source,
1776 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001777 encryptionInformation := encryptionInformation,
1778 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
1779 kC128 := kc128));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001780 }
1781 return ho_req;
1782}
1783
Harald Welteed848512018-05-24 22:27:58 +02001784/* generate an assignment complete template for either AoIP or SCCPlite */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001785function f_gen_exp_compl(integer bssap_idx := 0)
1786runs on MSC_ConnHdlr return template PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001787 var template PDU_BSSAP exp_compl;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001788 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001789 var template BSSMAP_IE_Osmo_OsmuxCID exp_osmux_cid := omit;
1790 if (g_pars.use_osmux_cn) {
1791 var template (present) INT1 exp_cid := ?;
1792 if (isbound(g_media.mgcp_conn[0].local_osmux_cid) and isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1793 exp_cid := (g_media.mgcp_conn[0].local_osmux_cid, g_media.mgcp_conn[1].local_osmux_cid);
1794 } else if (isbound(g_media.mgcp_conn[0].local_osmux_cid)) {
1795 exp_cid := g_media.mgcp_conn[0].local_osmux_cid;
1796 } else if (isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1797 exp_cid := g_media.mgcp_conn[1].local_osmux_cid;
1798 }
1799 exp_osmux_cid := tr_OsmuxCID(exp_cid);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001800 }
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001801 exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, exp_osmux_cid);
Harald Welteed848512018-05-24 22:27:58 +02001802 } else {
1803 /* CIC is optional "*" as the MSC allocated it */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001804 exp_compl := tr_BSSMAP_AssignmentComplete(*, omit, omit);
Harald Welteed848512018-05-24 22:27:58 +02001805 }
1806 return exp_compl;
1807}
1808
Harald Welte235ebf12017-12-15 14:18:16 +01001809/* Run everything required up to sending a caller-specified assignment command and expect response */
1810function f_assignment_exp(PDU_BSSAP ass_cmd, template PDU_BSSAP exp, charstring fail_text)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001811runs on test_CT return DchanTuple {
Harald Welte235ebf12017-12-15 14:18:16 +01001812 var BSSAP_N_CONNECT_ind rx_c_ind;
1813 var RSL_Message rx_rsl;
1814 var DchanTuple dt;
1815
Harald Welte89d42e82017-12-17 16:42:41 +01001816 f_init(1);
Harald Welte235ebf12017-12-15 14:18:16 +01001817
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001818 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte235ebf12017-12-15 14:18:16 +01001819 /* send assignment without AoIP IEs */
1820 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
1821 alt {
1822 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1823 if (ischosen(exp.pdu.bssmap.assignmentComplete)) {
1824 setverdict(pass);
1825 } else {
1826 setverdict(fail, fail_text);
1827 }
1828 }
1829 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1830 if (ischosen(exp.pdu.bssmap.assignmentFailure)) {
1831 setverdict(pass);
1832 } else {
1833 setverdict(fail, fail_text);
1834 }
1835 }
1836 [] BSSAP.receive { repeat; }
1837 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001838 return dt;
Harald Welte235ebf12017-12-15 14:18:16 +01001839}
Oliver Smithdd002752023-02-21 13:35:00 +01001840
1841private function f_tc_assignment_csd(charstring id) runs on MSC_ConnHdlr {
1842 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welteed848512018-05-24 22:27:58 +02001843 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Oliver Smithdd002752023-02-21 13:35:00 +01001844
Harald Welte235ebf12017-12-15 14:18:16 +01001845 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smithdd002752023-02-21 13:35:00 +01001846 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecCSData}));
1847
1848 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := GSM0808_DATA_RATE_TRANSP_4k8;
1849
1850 f_establish_fully(ass_cmd, exp_compl);
1851 f_perform_clear();
1852}
1853testcase TC_assignment_csd() runs on test_CT {
1854 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.10.0 */
1855 var MSC_ConnHdlr vc_conn;
1856 var TestHdlrParams pars := f_gen_test_hdlr_pars();
1857 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
1858
1859 f_init(1, true);
1860 f_sleep(1.0);
1861 vc_conn := f_start_handler(refers(f_tc_assignment_csd), pars);
1862 vc_conn.done;
1863 } else {
1864 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
1865 var PDU_BSSAP ass_cmd := f_gen_ass_req();
1866 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
1867 //exp_fail.pdu.bssmap.assignmentFailure.cause.causeValue := int2bit(enum2int(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL), 7);
1868 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for CSD");
1869 f_perform_clear_test_ct(dt);
1870 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001871 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001872}
1873
1874testcase TC_assignment_ctm() runs on test_CT {
1875 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001876 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001877 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
1878 //exp_fail.pdu.bssmap.assignmentFailure.cause.causeValue := int2bit(enum2int(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL), 7);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001879 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
1880 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001881 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001882}
1883
Harald Welte4003d112017-12-09 22:35:39 +01001884type record DchanTuple {
1885 integer sccp_conn_id,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001886 RslChannelNr rsl_chan_nr,
1887 BtsTrxIdx idx
Harald Weltea5d2ab22017-12-09 14:21:42 +01001888}
1889
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +02001890type record of DchanTuple DchanTuples;
1891
Harald Welted6939652017-12-13 21:02:46 +01001892/* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001893private function f_chreq_act_ack(OCT1 ra := '23'O,
1894 GsmFrameNumber fn := 23,
1895 BtsTrxIdx idx := {0, 0})
Harald Welted6939652017-12-13 21:02:46 +01001896runs on test_CT return RslChannelNr {
1897 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001898 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
1899 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Harald Welted6939652017-12-13 21:02:46 +01001900 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001901 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10), idx);
1902 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Harald Welted6939652017-12-13 21:02:46 +01001903 return chan_nr;
1904}
1905
Harald Welte4003d112017-12-09 22:35:39 +01001906/* helper function to establish a dedicated channel via BTS and MSC */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001907function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1908 BtsTrxIdx idx := {0, 0})
Harald Welte4003d112017-12-09 22:35:39 +01001909runs on test_CT return DchanTuple {
1910 var BSSAP_N_CONNECT_ind rx_c_ind;
Harald Welte4003d112017-12-09 22:35:39 +01001911 var DchanTuple dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001912
Harald Welte4003d112017-12-09 22:35:39 +01001913 /* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001914 dt.rsl_chan_nr := f_chreq_act_ack(ra, fn, idx);
Harald Welte4003d112017-12-09 22:35:39 +01001915
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001916 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3), idx);
Harald Welte4003d112017-12-09 22:35:39 +01001917
1918 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1919 dt.sccp_conn_id := rx_c_ind.connectionId;
1920 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1921
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001922 dt.idx := idx;
Harald Welte4003d112017-12-09 22:35:39 +01001923 return dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001924}
1925
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001926/* Like f_est_dchan(), but for the first lchan of a dynamic timeslot: first ACK the deactivation of PDCH. */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001927function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1928 BtsTrxIdx idx := {0, 0})
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001929runs on test_CT return DchanTuple {
1930 var BSSAP_N_CONNECT_ind rx_c_ind;
1931 var DchanTuple dt;
1932
1933 /* Send CHAN RQD */
1934 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001935 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001936
1937 /* The dyn TS first deactivates PDCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001938 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), idx, Tval := T3101_MAX);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001939 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001940 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001941
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001942 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001943 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1944
1945 /* Now activates the signalling channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001946 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10), idx);
1947 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001948
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001949 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001950
1951 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1952 dt.sccp_conn_id := rx_c_ind.connectionId;
1953 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1954
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001955 dt.idx := idx;
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001956 return dt;
1957}
1958
Harald Welte641fcbe2018-06-14 10:58:35 +02001959/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001960private function f_exp_chan_rel_and_clear(DchanTuple dt)
1961runs on test_CT {
Harald Welte641fcbe2018-06-14 10:58:35 +02001962 var RSL_Message rx_rsl;
1963 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001964 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), dt.idx, Tval := T3101_MAX);
Harald Welte641fcbe2018-06-14 10:58:35 +02001965 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001966 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), dt.idx);
Harald Welte641fcbe2018-06-14 10:58:35 +02001967
1968 /* expect Clear Complete from BSC */
1969 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
1970
1971 /* MSC disconnects as instructed. */
1972 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
1973}
1974
Harald Welte4003d112017-12-09 22:35:39 +01001975/* Test behavior of channel release after unilateral RLL REL IND (DISC from MS) */
1976testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001977 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01001978 var DchanTuple dt;
Harald Welte96c94412017-12-09 03:12:45 +01001979
Harald Welte89d42e82017-12-17 16:42:41 +01001980 f_init(1);
Harald Welte96c94412017-12-09 03:12:45 +01001981
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001982 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01001983
1984 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001985 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Harald Welte4003d112017-12-09 22:35:39 +01001986
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001987 /* expect Clear Request on MSC side */
1988 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
1989
1990 /* Instruct BSC to clear channel */
1991 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
1992 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
1993
Harald Welte4003d112017-12-09 22:35:39 +01001994 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001995 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001996
1997 /* wait for SCCP emulation to do its job */
1998 f_sleep(1.0);
Harald Welte4003d112017-12-09 22:35:39 +01001999
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002000 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002001}
2002
2003/* Test behavior of channel release after CONN FAIL IND from BTS */
2004testcase TC_chan_rel_conn_fail() runs on test_CT {
2005 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002006 var DchanTuple dt;
2007
Harald Welte89d42e82017-12-17 16:42:41 +01002008 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002009
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002010 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002011
Vadim Yanitskiy01d0a902022-12-14 22:41:42 +07002012 /* Sending CONN FAIL IND immediately may trigger a race condition.
2013 * Give the BSC some time to process a new SCCP connection (OS#5823). */
2014 f_sleep(0.2);
2015
Harald Welte4003d112017-12-09 22:35:39 +01002016 /* simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002017 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte4003d112017-12-09 22:35:39 +01002018 /* TODO: different cause values? */
2019
Harald Welte4003d112017-12-09 22:35:39 +01002020 /* expect Clear Request from BSC */
2021 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2022
2023 /* Instruct BSC to clear channel */
2024 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2025 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2026
Harald Welte6ff76ea2018-01-28 13:08:01 +01002027 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002028 f_exp_chan_rel_and_clear(dt);
Harald Welte4003d112017-12-09 22:35:39 +01002029
2030 /* wait for SCCP emulation to do its job */
2031 f_sleep(1.0);
2032
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002033 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002034}
2035
Harald Welte99f3ca02018-06-14 13:40:29 +02002036/* Test behavior of early CONN FAIL IND from BTS (before EST IND!) */
2037/* See also https://www.osmocom.org/issues/3182 */
2038testcase TC_early_conn_fail() runs on test_CT {
2039 var RSL_Message rx_rsl;
2040 var DchanTuple dt;
2041
2042 f_init(1);
2043
2044 /* BTS->BSC: Send CHAN RQD and wait for allocation; acknowledge it */
Harald Weltec46ea3c2020-10-10 18:46:12 +02002045 dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_ra_cs(), 23);
Harald Welte99f3ca02018-06-14 13:40:29 +02002046
2047 /* BTS->BSC: simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002048 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002049
2050 /* BTS->BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002051 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002052
2053 /* BTS<-BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002054 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002055
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002056 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002057}
2058
2059/* Test behavior of late CONN FAIL IND from BTS (ater REL IND!) */
2060/* See also https://www.osmocom.org/issues/3182 */
2061testcase TC_late_conn_fail() runs on test_CT {
2062 var RSL_Message rx_rsl;
2063 var DchanTuple dt;
2064
2065 f_init(1);
2066
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002067 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99f3ca02018-06-14 13:40:29 +02002068
2069 /* BSC<-MSC: Instruct BSC to clear connection */
2070 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(0)));
2071
2072 /* BTS->BSC: expect BSC to deactivate SACCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002073 rx_rsl := f_exp_ipa_rx(tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002074
2075 /* BTS->BSC: simulate a late CONN FAIL IND from BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002076 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002077
2078 /* BTS<-BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002079 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002080 /* BTS->BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002081 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002082
2083 /* BSC->MSC: expect Clear Complete from BSC */
2084 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2085
2086 /* BSC<-MSC: MSC disconnects as requested. */
2087 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2088
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002089 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002090}
2091
Oliver Smithaf03bef2021-08-24 15:34:51 +02002092private function f_TC_stats_conn_fail(charstring id) runs on MSC_ConnHdlr {
2093 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
2094 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2095
2096 f_statsd_reset();
2097
2098 /* Establish SDCCH */
2099 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
2100 f_establish_fully(ass_cmd, exp_fail);
2101
2102 /* Expect stats to be 0 */
2103 var StatsDExpects expect := {
2104 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
2105 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
2106 };
2107 f_statsd_expect(expect);
2108
2109 /* Simulate CONN FAIL IND on SDCCH */
2110 RSL.send(ts_ASP_RSL_UD(
2111 ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
2112 IPAC_PROTO_RSL_TRX0));
2113
Neels Hofmeyr58be48a2021-09-07 18:39:21 +02002114 f_sleep(1.0);
2115
Oliver Smithaf03bef2021-08-24 15:34:51 +02002116 /* Expect stats to be 1 */
2117 expect := {
2118 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
2119 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
2120 };
2121 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002122 BSSAP.receive(tr_BSSMAP_ClearRequest);
2123 f_perform_clear();
Oliver Smithaf03bef2021-08-24 15:34:51 +02002124}
2125testcase TC_stats_conn_fail() runs on test_CT {
2126 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2127 var MSC_ConnHdlr vc_conn;
2128
2129 f_init(1, true);
2130 f_sleep(1.0);
2131
2132 vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
2133 vc_conn.done;
2134
2135 f_shutdown_helper();
2136}
2137
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002138function f_expect_chan_rel(RslChannelNr rsl_chan_nr,
2139 BtsTrxIdx idx := {0, 0},
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002140 boolean expect_deact_sacch := true,
2141 boolean expect_rr_chan_rel := true,
2142 boolean expect_rll_rel_req := true,
Harald Welte99787102019-02-04 10:41:36 +01002143 boolean handle_rll_rel := true,
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002144 template CellSelIndValue expect_cells := omit,
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002145 template (present) RR_Cause expect_rr_cause := ?
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002146 ) runs on test_CT {
Harald Welte91d54a52018-01-28 15:35:07 +01002147
2148 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002149 var boolean got_deact_sacch := false;
2150 var boolean got_rr_chan_rel := false;
2151 var boolean got_rll_rel_req := false;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002152 var ASP_RSL_Unitdata ud;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002153 var RSL_IE_Body l3_ie;
2154 var PDU_ML3_NW_MS l3;
2155 var RR_Cause got_cause;
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002156 log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
2157 " expect_rll_rel_req=", expect_rll_rel_req);
Harald Welte91d54a52018-01-28 15:35:07 +01002158 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002159 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_DEACT_SACCH(rsl_chan_nr))) {
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002160 got_deact_sacch := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002161 repeat;
2162 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002163 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_DATA_REQ(rsl_chan_nr, ?, decmatch tr_RRM_RR_RELEASE))) -> value ud {
Harald Welte99787102019-02-04 10:41:36 +01002164 got_rr_chan_rel := true;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002165
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002166 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2167 setverdict(fail, "cannot find L3");
2168 mtc.stop;
2169 }
2170 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2171
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002172 if (not istemplatekind(expect_cells, "omit")) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002173 var CellSelIndValue cells := dec_CellSelIndValue(
2174 l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
2175
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002176 log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
2177 if (match(cells, expect_cells)) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002178 setverdict(pass);
2179 } else {
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002180 log("EXPECTED CELLS: ", expect_cells);
2181 setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002182 }
2183 }
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002184
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002185 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2186 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2187 if (match(got_cause, expect_rr_cause)) {
2188 setverdict(pass);
2189 } else {
2190 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2191 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002192 }
Harald Welte99787102019-02-04 10:41:36 +01002193 repeat;
2194 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002195 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_REL_REQ(rsl_chan_nr, ?))) {
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002196 got_rll_rel_req := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002197 /* FIXME: Why are we getting this for LinkID SACCH? */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002198 if (handle_rll_rel) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002199 f_ipa_tx(ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002200 }
Harald Welte91d54a52018-01-28 15:35:07 +01002201 repeat;
2202 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002203 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002204 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002205 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
Harald Welte91d54a52018-01-28 15:35:07 +01002206 }
2207 /* ignore any user data */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002208 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002209 repeat;
2210 }
2211 }
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002212
2213 log("f_expect_chan_rel() summary: got_deact_sacch=", got_deact_sacch, " got_rr_chan_rel=", got_rr_chan_rel,
2214 " got_rll_rel_req=", got_rll_rel_req);
2215
2216 if (expect_deact_sacch != got_deact_sacch) {
2217 setverdict(fail, "f_expect_chan_rel(): expect_deact_sacch=", expect_deact_sacch, " got_deact_sacch=", got_deact_sacch);
2218 }
2219 if (expect_rr_chan_rel != got_rr_chan_rel) {
2220 setverdict(fail, "f_expect_chan_rel(): expect_rr_chan_rel=", expect_rr_chan_rel, " got_rr_chan_rel=", got_rr_chan_rel);
2221 }
2222 if (expect_rll_rel_req != got_rll_rel_req) {
2223 setverdict(fail, "f_expect_chan_rel(): expect_rll_rel_req=", expect_rll_rel_req, " got_rll_rel_req=", got_rll_rel_req);
2224 }
Harald Welte91d54a52018-01-28 15:35:07 +01002225}
2226
Harald Welte4003d112017-12-09 22:35:39 +01002227/* Test behavior of channel release after hard Clear Command from MSC */
2228testcase TC_chan_rel_hard_clear() runs on test_CT {
2229 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002230 var DchanTuple dt;
Harald Welte4003d112017-12-09 22:35:39 +01002231
Harald Welte89d42e82017-12-17 16:42:41 +01002232 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002233
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002234 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002235
2236 /* Instruct BSC to clear channel */
2237 var BssmapCause cause := 0;
2238 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2239
2240 /* expect Clear Complete from BSC on A */
2241 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2242 /* release the SCCP connection */
2243 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2244 }
2245
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002246 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002247 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002248}
2249
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002250function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
2251 var BSSAP_N_DATA_ind rx_di;
2252 var DchanTuple dt;
2253
2254 f_init(1);
2255
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002256 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002257 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2258 /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
2259 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
2260
2261 /* Instruct BSC to clear channel */
2262 var BssmapCause cause := 0;
2263 if (tx_csfb_ind) {
2264 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2265 } else {
2266 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2267 }
2268
2269 /* expect Clear Complete from BSC on A */
2270 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2271 /* release the SCCP connection */
2272 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2273 }
2274
2275 /* 1 neighbor is added by default in osmo-bts.cfg and
2276 SystemInformationConfig_default, use that: */
2277 var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
2278
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002279 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := exp_cells);
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002280 f_shutdown_helper();
2281}
2282
2283/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
2284 from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
2285 PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2286 EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
2287 Indicator or not shouldn't matter at all. */
2288testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
2289 f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
2290}
2291
2292/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
2293 MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
2294 Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2295 EUTRAN neighbor list sent later on by BSC in RR Channel. */
2296testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
2297 f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
2298}
2299
2300/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
2301 MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
2302 Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
2303 CSFB Indicator should not be used anymore, and hence, there should be no
2304 EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
2305 Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
Harald Welte99787102019-02-04 10:41:36 +01002306testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
2307 var BSSAP_N_DATA_ind rx_di;
2308 var DchanTuple dt;
2309
2310 f_init(1);
2311
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002312 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99787102019-02-04 10:41:36 +01002313
2314 /* Instruct BSC to clear channel */
2315 var BssmapCause cause := 0;
2316 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2317
2318 /* expect Clear Complete from BSC on A */
2319 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2320 /* release the SCCP connection */
2321 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2322 }
2323
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002324 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002325 f_shutdown_helper();
Harald Welte99787102019-02-04 10:41:36 +01002326}
2327
Harald Welted8c36cd2017-12-09 23:05:31 +01002328/* Test behavior of channel release after hard RLSD from MSC */
2329testcase TC_chan_rel_hard_rlsd() runs on test_CT {
Harald Welted8c36cd2017-12-09 23:05:31 +01002330 var DchanTuple dt;
Harald Welted8c36cd2017-12-09 23:05:31 +01002331
Harald Welte89d42e82017-12-17 16:42:41 +01002332 f_init(1);
Harald Welted8c36cd2017-12-09 23:05:31 +01002333
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002334 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welted8c36cd2017-12-09 23:05:31 +01002335
2336 /* release the SCCP connection */
2337 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2338
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002339 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002340 f_shutdown_helper();
Harald Welted8c36cd2017-12-09 23:05:31 +01002341}
2342
Harald Welte550daf92018-06-11 19:22:13 +02002343/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
2344testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
2345 var DchanTuple dt;
2346
2347 f_init(1);
2348
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002349 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte550daf92018-06-11 19:22:13 +02002350
2351 /* release the SCCP connection */
2352 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2353
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002354 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002355 f_shutdown_helper();
Harald Welte550daf92018-06-11 19:22:13 +02002356}
2357
Harald Welte85804d42017-12-10 14:11:58 +01002358/* Test behavior of channel release after BSSMAP RESET from MSC */
2359testcase TC_chan_rel_a_reset() runs on test_CT {
Harald Welte85804d42017-12-10 14:11:58 +01002360 var DchanTuple dt;
Harald Welte85804d42017-12-10 14:11:58 +01002361
Harald Welte89d42e82017-12-17 16:42:41 +01002362 f_init(1);
Harald Welte85804d42017-12-10 14:11:58 +01002363
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002364 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte85804d42017-12-10 14:11:58 +01002365
2366 /* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002367 IPA_RSL[0][0].clear;
Harald Welte85804d42017-12-10 14:11:58 +01002368
2369 /* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002370 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own, ts_BSSMAP_Reset(0, g_osmux_enabled_cn)));
Harald Welte85804d42017-12-10 14:11:58 +01002371 interleave {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002372 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[0].sccp_addr_own, g_bssap[0].sccp_addr_peer, tr_BSSMAP_ResetAck(g_osmux_enabled_cn))) { }
Harald Welte85804d42017-12-10 14:11:58 +01002373 [] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
2374 }
2375
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002376 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002377 f_shutdown_helper();
Harald Welte85804d42017-12-10 14:11:58 +01002378}
2379
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002380/* Verify T(iar) triggers and releases the channel */
2381testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
2382 var DchanTuple dt;
2383
2384 /* Set T(iar) in BSC low enough that it will trigger before other side
2385 has time to keep alive with a T(ias). Keep recommended ratio of
2386 T(iar) >= T(ias)*2 */
2387 g_bsc_sccp_timer_ias := 2;
2388 g_bsc_sccp_timer_iar := 5;
2389
2390 f_init(1);
2391
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002392 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002393 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002394 f_shutdown_helper();
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002395}
2396
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002397private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause,
2398 template (present) RR_Cause expect_rr_cause)
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002399runs on test_CT
2400{
2401 var DchanTuple dt;
2402
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002403 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002404 var BssmapCause cause := 0;
2405 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
2406 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2407 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2408 }
2409
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002410 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_rr_cause := expect_rr_cause);
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002411}
2412
2413/* Test that Clear Command cause codes affect the RR Channel Release cause code */
2414testcase TC_chan_rel_rr_cause() runs on test_CT {
2415 f_init(1);
2416
2417 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
2418 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
2419 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
2420 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
2421 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
2422 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
Vadim Yanitskiye18aebb2021-01-03 13:10:43 +01002423
2424 f_shutdown_helper();
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002425}
2426
Harald Welte5cd20ed2017-12-13 21:03:20 +01002427/* Test behavior if RSL EST IND for non-active channel */
2428testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
2429 timer T := 2.0;
2430
Harald Welte89d42e82017-12-17 16:42:41 +01002431 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002432
Harald Welte5cd20ed2017-12-13 21:03:20 +01002433 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002434 var octetstring l3_payload := gen_l3_valid_payload();
2435 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002436
2437 T.start;
2438 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002439 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002440 setverdict(fail, "MSC received COMPL L3 for non-active lchan");
2441 }
2442 [] BSSAP.receive {}
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002443 [] IPA_RSL[0][0].receive {}
Harald Welte5cd20ed2017-12-13 21:03:20 +01002444 [] T.timeout {}
2445 }
2446
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002447 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002448}
2449
2450/* Test behavior if RSL EST IND for invalid SAPI */
2451testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
2452 var RslChannelNr chan_nr;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002453 var octetstring l3_payload;
Harald Welte5cd20ed2017-12-13 21:03:20 +01002454
Harald Welte89d42e82017-12-17 16:42:41 +01002455 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002456
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002457 chan_nr := f_chreq_act_ack();
2458 l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002459
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002460 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002461
2462 timer T := 2.0;
2463 T.start;
2464 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002465 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002466 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
2467 }
2468 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002469 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002470 [] T.timeout {}
2471 }
2472
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002473 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002474}
2475
2476/* Test behavior if RSL EST IND for invalid SAPI */
2477testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
2478 timer T := 2.0;
2479
Harald Welte89d42e82017-12-17 16:42:41 +01002480 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002481
2482 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002483 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002484
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002485 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002486
2487 T.start;
2488 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002489 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002490 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
2491 }
2492 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002493 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002494 [] T.timeout {}
2495 }
2496
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002497 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002498}
2499
2500/* Test behavior if RSL EST IND for invalid SACCH */
2501testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
2502 timer T := 2.0;
2503
Harald Welte89d42e82017-12-17 16:42:41 +01002504 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002505
2506 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002507 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002508
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002509 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002510
2511 T.start;
2512 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002513 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002514 setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
2515 }
2516 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002517 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002518 [] T.timeout {}
2519 }
2520
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002521 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002522}
2523
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002524/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
2525private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
2526 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
2527 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2528
2529 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
2530 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
2531
2532 f_establish_fully(ass_cmd, exp_compl);
2533
2534 /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
2535 RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
2536 /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
2537 BSSAP.receive(PDU_BSSAP:{
2538 discriminator := '1'B,
2539 spare := '0000000'B,
2540 dlci := 'C3'O,
2541 lengthIndicator := ?,
2542 pdu := { dtap := '0904'O }
2543 });
2544
2545 /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
2546 for (var integer i := 0; i < 32; i := i + 1) {
2547 var octetstring l3 := '09'O & f_rnd_octstring(14);
2548 var template (value) RslLinkId link_id;
2549 var template (value) OCT1 dlci;
2550
2551 if (i mod 2 == 0) {
2552 /* SAPI0 on FACCH or SDCCH */
2553 link_id := ts_RslLinkID_DCCH(0);
2554 dlci := '80'O;
2555 } else {
2556 /* SAPI3 on SACCH */
2557 link_id := ts_RslLinkID_SACCH(3);
2558 dlci := 'C3'O;
2559 }
2560
2561 /* Send MO message: RSL -> BSSAP */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002562 f_mo_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002563 /* Send MT message: BSSAP -> RSL */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002564 f_mt_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002565 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002566 f_perform_clear();
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002567}
2568testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
2569 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2570 var MSC_ConnHdlr vc_conn;
2571
2572 f_init(1, true);
2573 f_sleep(1.0);
2574
2575 vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
2576 vc_conn.done;
2577
2578 f_shutdown_helper();
2579}
2580
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002581private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002582 template (present) myBSSMAP_Cause cause := ?,
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002583 template (present) BIT2 cc := ?,
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002584 float T_val := 2.0)
2585runs on test_CT {
2586 var BSSAP_N_DATA_ind rx_di;
2587 timer T;
2588
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002589 var template (present) BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
2590 var template (present) PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002591
2592 T.start(T_val);
2593 alt {
2594 [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
2595 var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
2596 if (not match(rx_cause, tr_cause)) {
2597 setverdict(fail, "Rx unexpected Cause IE: ",
2598 rx_cause, " vs expected ", tr_cause);
2599 }
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002600
2601 /* Who ever on the earth decided to define this field as two separate bits?!? */
2602 var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
2603 & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
2604 if (not match(rx_cc, cc)) {
2605 setverdict(fail, "Rx unexpected Control Channel type: ",
2606 rx_cc, " vs expected ", cc);
2607 }
2608
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002609 setverdict(pass);
2610 }
2611 [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
2612 setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
2613 }
2614 [] T.timeout {
2615 setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
2616 }
2617 }
2618}
2619
2620/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
2621testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002622 var RSL_Message rx_rsl;
2623 var DchanTuple dt;
2624
2625 f_init(1);
2626
2627 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002628 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002629
2630 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002631 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(gen_l3_valid_payload(), '03'O)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002632 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002633 rx_rsl := f_exp_ipa_rx(tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002634
2635 /* MS sends unexpected RELease INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002636 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002637 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2638 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
2639
2640 /* Clean up the connection */
2641 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002642 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002643
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002644 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002645}
2646
2647/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
2648testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002649 var RSL_Message rx_rsl;
2650 var DchanTuple dt;
2651
2652 f_init(1);
2653
2654 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002655 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002656
2657 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002658 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(gen_l3_valid_payload(), '03'O)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002659 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002660 rx_rsl := f_exp_ipa_rx(tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002661
2662 /* BTS sends unexpected ERROR INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002663 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002664 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2665 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
2666
2667 /* Clean up the connection */
2668 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002669 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002670
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002671 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002672}
2673
2674/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
2675testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002676 var RSL_Message rx_rsl;
2677 var DchanTuple dt;
2678
2679 f_init(1);
2680
2681 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002682 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002683
2684 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002685 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(gen_l3_valid_payload(), '03'O)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002686 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002687 rx_rsl := f_exp_ipa_rx(tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002688
2689 /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
2690 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
2691
2692 /* Clean up the connection */
2693 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002694 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002695
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002696 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002697}
2698
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002699/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
2700testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002701 var RSL_Message rx_rsl;
2702 var DchanTuple dt;
2703
2704 f_init(1);
2705
2706 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002707 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002708
2709 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002710 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(gen_l3_valid_payload(), '03'O)));
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002711 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002712 rx_rsl := f_exp_ipa_rx(tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002713
2714 /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002715 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Pau Espin Pedrol121f27f2022-01-12 12:02:10 +01002716 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, '10'B);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002717
2718 /* Clean up the connection */
2719 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002720 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002721
2722 f_shutdown_helper();
2723}
2724
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002725testcase TC_si_default() runs on test_CT {
2726 f_init(0);
2727 f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002728 f_shutdown_helper();
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002729}
Harald Welte4003d112017-12-09 22:35:39 +01002730
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002731/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
2732 * the entire value range. This function provides the same EARFCN numbers for the same earfcn_index */
2733private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uint16_t
2734{
2735 select (earfcn_index) {
2736 case (0) {
2737 /* E-ARFCN 111 is already added in the osmo-bsc.cfg */
2738 return 111;
2739 }
2740 case (1) {
2741 return 1;
2742 }
2743 case (2) {
2744 return 0;
2745 }
2746 case (3) {
2747 return 65535;
2748 }
2749 case else {
2750 return 23 * (earfcn_index - 3);
2751 }
2752 }
2753}
2754
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002755function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
2756 template CellSelIndValue expect_cells := omit) runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002757
2758 f_init(0);
2759
2760 /* E-ARFCN 111 is already added in the osmo-bsc.cfg, so only add more arfcns if total_earfcns > 1 */
2761 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002762 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2763 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002764 }
2765
2766 f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
2767
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002768 if (not istemplatekind(expect_cells, "omit")) {
2769 /* Also check that RR Channel Release contains these EARFCNs.
2770 * (copied code from TC_chan_rel_hard_clear_csfb) */
2771 var BSSAP_N_DATA_ind rx_di;
2772 var DchanTuple dt;
2773
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002774 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrold0046312021-04-19 16:35:58 +02002775 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2776 * yet when generating the EUTRAN neigh list in RR CHannel Release) */
2777 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002778
2779 /* Instruct BSC to clear channel */
2780 var BssmapCause cause := 0;
2781 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2782
2783 /* expect Clear Complete from BSC on A */
2784 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2785 /* release the SCCP connection */
2786 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2787 }
2788
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002789 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := expect_cells);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002790 }
2791
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002792 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002793 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list del earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002794 }
2795}
2796
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002797private function f_tr_si2quater_earfcns(integer count) return template SI2quaterRestOctetsList
2798{
2799 var template SI2quaterRestOctetsList si2quater := {};
2800 var integer si2quater_count := (count + 2) / 3;
2801
2802 for (var integer i := 0; i < count; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002803 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002804 var integer index := i / 3;
2805 var integer earfcn_index := i mod 3;
2806 if (index >= lengthof(si2quater)) {
2807 si2quater[index] := tr_SI2quaterRestOctets_EUTRAN(index := index, count := si2quater_count - 1);
2808 }
2809 si2quater[index].rel_additions.rel5.rel6.rel7.rel8.prio_eutran_params_desc.desc.eutran_params_desc.desc.repeated_neigh_cells[0].cell_desc_list[earfcn_index] := tr_EUTRAN_CellDesc_default(e_arfcn := earfcn);
2810 }
2811
2812 return si2quater;
2813}
2814
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002815private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
2816{
2817 var template CellSelIndValue_EUTRAN_Descrs cells := {};
2818
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002819 /* the lte neighbors must match the config & vty to pass this test */
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002820 for (var integer i := 0; i < count; i := i + 1) {
2821 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002822 cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002823 }
2824
2825 return tr_CellSelIndValue_EUTRAN(cells);
2826}
2827
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002828private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
2829{
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002830 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrol8ab62e42020-12-18 16:19:11 +01002831 sic.si2quater := f_tr_si2quater_earfcns(n);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002832 var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
2833 f_test_si2quater(n, sic, cells);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002834}
2835
2836testcase TC_si2quater_2_earfcns() runs on test_CT {
2837 f_tc_si2quater_n_earfcns(2);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002838 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002839}
2840
2841testcase TC_si2quater_3_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002842 f_tc_si2quater_n_earfcns(3);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002843 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002844}
2845
2846testcase TC_si2quater_4_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002847 f_tc_si2quater_n_earfcns(4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002848 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002849}
2850
2851testcase TC_si2quater_5_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002852 f_tc_si2quater_n_earfcns(5);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002853 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002854}
2855
2856testcase TC_si2quater_6_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002857 f_tc_si2quater_n_earfcns(6);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002858 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002859}
2860
2861testcase TC_si2quater_12_earfcns() runs on test_CT {
2862 f_tc_si2quater_n_earfcns(12);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002863 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002864}
2865
2866testcase TC_si2quater_23_earfcns() runs on test_CT {
2867 f_tc_si2quater_n_earfcns(23);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002868 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002869}
2870
2871testcase TC_si2quater_32_earfcns() runs on test_CT {
2872 f_tc_si2quater_n_earfcns(32);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002873 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002874}
2875
2876testcase TC_si2quater_33_earfcns() runs on test_CT {
2877 f_tc_si2quater_n_earfcns(33);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002878 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002879}
2880
2881testcase TC_si2quater_42_earfcns() runs on test_CT {
2882 f_tc_si2quater_n_earfcns(42);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002883 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002884}
2885
2886testcase TC_si2quater_48_earfcns() runs on test_CT {
2887 f_tc_si2quater_n_earfcns(48);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002888 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002889}
2890
2891/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
2892 * 48 EARFCNs. */
2893testcase TC_si2quater_49_earfcns() runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002894 var template SystemInformationConfig sic := SystemInformationConfig_default;
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002895 sic.si2quater := f_tr_si2quater_earfcns(48); /* 48, not 49! */
2896 f_init(0);
2897
2898 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002899 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2900 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002901 }
2902
2903 /* The 49th EARFCN no longer fits, expect VTY error */
2904 f_vty_enter_cfg_bts(BSCVTY, 0);
2905 var charstring vty_error;
2906 vty_error := f_vty_transceive_ret(BSCVTY,
2907 "si2quater neighbor-list add earfcn 70 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3")
2908 f_vty_transceive(BSCVTY, "end");
2909
2910 if (f_strstr(vty_error, "Unable to add ARFCN 70") >= 0) {
2911 log("Got expected VTY error: ", vty_error);
2912 setverdict(pass);
2913 } else {
2914 setverdict(fail, "Expected the 49th EUTRAN ARFCN to be rejected by vty config, got: ", vty_error);
2915 }
2916
2917 f_init_bts_and_check_sysinfo(0, expect_si := sic);
2918
2919 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002920 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list del earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002921 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002922 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002923}
2924
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002925private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
2926{
2927 var uint8_t count := 0;
2928 for (var integer i := 5; i < 16; i := i + 1) {
2929 if (acc[i] == '0'B) { /* the list marks barred, we count allowed */
2930 count := count + 1;
2931 }
2932 }
2933 return count;
2934}
2935
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002936private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return SystemInformationType1
2937{
2938 var ASP_RSL_Unitdata rx_rsl_ud;
2939 var SystemInformationType1 last_si1;
2940
2941 timer T := 30.0;
2942 T.start;
2943 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002944 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
2945 tr_RSL_BCCH_INFO,
2946 tr_RSL_NO_SACCH_FILL,
2947 tr_RSL_SACCH_FILL))) -> value rx_rsl_ud {
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002948 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
2949 if (g_system_information[rsl_idx].si1 == omit) {
2950 repeat;
2951 }
2952 last_si1 := g_system_information[rsl_idx].si1;
2953 g_system_information[rsl_idx].si1 := omit;
2954 T.stop;
2955 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002956 [] IPA_RSL[rsl_idx][0].receive { repeat; }
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002957 [] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
2958 }
2959 return last_si1;
2960}
2961
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002962/* verify ACC rotate feature */
2963testcase TC_si_acc_rotate() runs on test_CT {
2964 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002965 var SystemInformationType1 last_si1;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002966 var AccessControlClass acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002967 var uint8_t count;
2968 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2969
2970 f_init(0, guard_timeout := 60.0);
2971
2972 f_bts_0_cfg(BSCVTY, {"rach access-control-class 5 barred",
2973 "access-control-class-rotate 3",
2974 "access-control-class-rotate-quantum 1"});
2975
2976 /* Init and get first sysinfo */
2977 f_init_bts_and_check_sysinfo(0, expect_si := ?);
2978
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002979 for (var integer i:= 0; i < 20; i := i + 1) {
2980 last_si1 := f_recv_next_si1(0);
2981 acc := last_si1.rach_control.acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002982 count := f_acc09_count_allowed(acc);
2983 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
2984
2985 if (count != 3) {
2986 log("RSL: EXPECTED SI ACC len=3");
2987 setverdict(fail, "received SI does not match expectations");
2988 break;
2989 }
2990
2991 for (var integer j := 0; j < 10; j := j + 1) {
2992 if (acc[16 - 1 - j] == '0'B) { /* the list marks barred, we count allowed */
2993 times_allowed[j] := times_allowed[j] + 1;
2994 }
2995 }
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002996 }
2997
2998 for (var integer j := 0; j < 10; j := j + 1) {
2999 log("ACC", j, " allowed ", times_allowed[j], " times" );
3000 if (j != 5 and times_allowed[j] < 3) {
3001 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " < 1 times");
3002 } else if (j == 5 and times_allowed[j] > 0) {
3003 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " > 0 times");
3004 }
3005 }
3006
3007 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3008 "rach access-control-class 5 allowed"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003009 f_shutdown_helper();
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003010}
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02003011
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003012/* verify ACC startup ramp+rotate feature */
3013testcase TC_si_acc_ramp_rotate() runs on test_CT {
3014 var template SystemInformationConfig sic := SystemInformationConfig_default;
3015 var SystemInformationType1 last_si1;
3016 var AccessControlClass acc;
3017 var ASP_RSL_Unitdata rx_rsl_ud;
3018 var uint8_t count;
3019 var uint8_t prev_count;
3020 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3021
3022 f_init(0, guard_timeout := 80.0);
3023
3024 f_bts_0_cfg(BSCVTY, {"rach access-control-class 4 barred",
3025 "access-control-class-rotate 0",
3026 "access-control-class-rotate-quantum 1",
3027 "access-control-class-ramping",
3028 "access-control-class-ramping-step-interval 5",
3029 "access-control-class-ramping-step-size 5"});
3030
3031 /* Init and get first sysinfo */
3032 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3033 last_si1 := g_system_information[0].si1;
3034 acc := last_si1.rach_control.acc;
3035 count := f_acc09_count_allowed(acc);
3036 /* Adm subset size was set to 0 above, so wait until all ACC are barred */
3037 while (count > 0) {
3038 last_si1 := f_recv_next_si1(0);
3039 acc := last_si1.rach_control.acc;
3040 count := f_acc09_count_allowed(acc);
3041 log("RSL: wait len()=0: GOT SI1 ACC len=", count, ": ", acc);
3042 }
3043
3044 /* Increase adm subset size, we should see ramping start up */
3045 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10"});
3046 prev_count := 0;
3047 while (true) {
3048 last_si1 := f_recv_next_si1(0);
3049 acc := last_si1.rach_control.acc;
3050 count := f_acc09_count_allowed(acc);
3051 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3052
3053 if (prev_count > count) {
3054 setverdict(fail, "ACC allowed count dropped while expecting grow: ", prev_count, " -> ", count);
3055 break;
3056 }
3057
3058 if (count == 9) {
3059 break; /* Maximum reached (10 - 1 perm barred), done here */
3060 }
3061
3062 prev_count := count;
3063 }
3064
3065 setverdict(pass);
3066
3067 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3068 "rach access-control-class 4 allowed",
3069 "no access-control-class-ramping"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003070 f_shutdown_helper();
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003071}
3072
Harald Welte4003d112017-12-09 22:35:39 +01003073testcase TC_ctrl_msc_connection_status() runs on test_CT {
3074 var charstring ctrl_resp;
3075
Harald Welte89d42e82017-12-17 16:42:41 +01003076 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003077
3078 /* See https://osmocom.org/issues/2729 */
3079 f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003080 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01003081}
3082
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003083testcase TC_ctrl_msc0_connection_status() runs on test_CT {
3084 var charstring ctrl_resp;
3085
3086 f_init(1);
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003087
3088 f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003089 f_shutdown_helper();
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003090}
3091
Neels Hofmeyr0bc470d2021-08-21 13:37:13 +02003092/* Verify correct stats on the number of configured and connected MSCs */
3093private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
3094 g_pars := f_gen_test_hdlr_pars();
3095 var StatsDExpects expect := {
3096 { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
3097 { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
3098 };
3099 f_statsd_expect(expect);
3100}
3101
3102private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
3103{
3104 var MSC_ConnHdlr vc_conn;
3105
3106 f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
3107 f_sleep(1.0);
3108 vc_conn := f_start_handler(tc_fn);
3109 vc_conn.done;
3110
3111 /* Also verify stat exposed on CTRL interface */
3112 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
3113 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
3114
3115 f_shutdown_helper();
3116}
3117
3118/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
3119private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
3120 f_tc_stat_num_msc_connected_msc_connhdlr(1);
3121}
3122testcase TC_stat_num_msc_connected_1() runs on test_CT {
3123 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
3124}
3125
3126/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
3127private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
3128 f_tc_stat_num_msc_connected_msc_connhdlr(2);
3129}
3130testcase TC_stat_num_msc_connected_2() runs on test_CT {
3131 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
3132}
3133
3134/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
3135private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
3136 f_tc_stat_num_msc_connected_msc_connhdlr(3);
3137}
3138testcase TC_stat_num_msc_connected_3() runs on test_CT {
3139 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
3140}
3141
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003142/* Verify correct stats on the number of configured and connected MSCs */
3143private function f_tc_stat_num_bts_connected_msc_connhdlr(integer expect_num_bts_connected) runs on MSC_ConnHdlr {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003144 var integer num_trx_connected := 0;
3145 var integer num_trx_total := 0;
3146
3147 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3148 var integer trx_num := c_BtsParams[i].trx_num;
3149 num_trx_total := num_trx_total + trx_num;
3150 if (i < expect_num_bts_connected) {
3151 num_trx_connected := num_trx_connected + trx_num;
3152 }
3153 }
3154
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003155 var StatsDExpects expect := {
3156 { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
3157 { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3158 { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003159 { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := num_trx_connected, max := num_trx_connected },
3160 { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := num_trx_total, max := num_trx_total }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003161 };
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003162
3163 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003164 f_statsd_expect(expect);
3165}
3166
3167private function f_tc_stat_num_bts_connected_test_ct(void_fn tc_fn, integer nr_bts) runs on test_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003168 var integer num_trx_connected := 0;
3169 var integer num_trx_total := 0;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003170 var MSC_ConnHdlr vc_conn;
3171
3172 f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
3173 f_sleep(1.0);
3174 vc_conn := f_start_handler(tc_fn);
3175 vc_conn.done;
3176
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003177 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3178 var integer trx_num := c_BtsParams[i].trx_num;
3179 num_trx_total := num_trx_total + trx_num;
3180 if (i < nr_bts) {
3181 num_trx_connected := num_trx_connected + trx_num;
3182 }
3183 }
3184
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003185 /* Also verify stat exposed on CTRL interface */
3186 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
3187 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:total", int2str(NUM_BTS_CFG));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003188 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(num_trx_connected));
3189 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:total", int2str(num_trx_total));
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003190
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003191 /* Verify rf_states exposed on CTRL interface */
3192 var charstring expect_net_rf_states := "";
3193 for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003194 var charstring expect_bts_rf_states := "";
3195
3196 for (var integer j := 0; j < c_BtsParams[i].trx_num; j := j + 1) {
3197 expect_bts_rf_states := expect_bts_rf_states &
3198 int2str(i) & "," & int2str(j) & ",";
3199 if (i < NUM_BTS) {
3200 /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
3201 expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
3202 } else {
3203 /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
3204 expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
3205 }
3206 /* The RF policy is still global in osmo-bsc, i.e. always "on" */
3207 expect_bts_rf_states := expect_bts_rf_states & "on,";
3208 if (i < nr_bts) {
3209 /* For BTS where RSL is connected, the RSL state will be "up" */
3210 expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
3211 } else {
3212 expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
3213 }
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003214 }
3215
3216 f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
3217 expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
3218 }
3219 f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
3220
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003221 f_shutdown_helper();
3222}
3223
3224/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
3225private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
3226 f_tc_stat_num_bts_connected_msc_connhdlr(1);
3227}
3228testcase TC_stat_num_bts_connected_1() runs on test_CT {
3229 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
3230}
3231
3232/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
3233private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
3234 f_tc_stat_num_bts_connected_msc_connhdlr(2);
3235}
3236testcase TC_stat_num_bts_connected_2() runs on test_CT {
3237 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
3238}
3239
3240/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
3241private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
3242 f_tc_stat_num_bts_connected_msc_connhdlr(3);
3243}
3244testcase TC_stat_num_bts_connected_3() runs on test_CT {
3245 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
3246}
3247
Harald Welte4003d112017-12-09 22:35:39 +01003248testcase TC_ctrl() runs on test_CT {
3249 var charstring ctrl_resp;
3250
Harald Welte89d42e82017-12-17 16:42:41 +01003251 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003252
3253 /* all below values must match the osmo-bsc.cfg config file used */
3254
Harald Welte6a129692018-03-17 17:30:14 +01003255 f_ctrl_get_exp(IPA_CTRL, "mcc", "001");
3256 f_ctrl_get_exp(IPA_CTRL, "mnc", "01");
Oliver Smith75aa0202019-08-19 14:17:50 +02003257 f_ctrl_get_exp(IPA_CTRL, "number-of-bts", "4");
Harald Welte4003d112017-12-09 22:35:39 +01003258
3259 var integer bts_nr := 0;
3260 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "location-area-code", "1");
3261 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "cell-identity", "0");
3262 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "oml-connection-state", "connected");
3263 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "gprs-mode", "gprs");
3264 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "rf_state", "operational,unlocked,on");
3265 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "arfcn", "871");
3266 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "max-power-reduction", "20");
3267
3268 var integer uptime := str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime"));
3269 f_sleep(2.0);
3270 if (str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime")) < uptime+1) {
3271 setverdict(fail, "oml-uptime not incrementing as expected");
3272 }
3273 /* TODO: Disconnect RSL, imply that OML is disconnected and check for uptime zero? */
3274
3275 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
3276
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003277 f_shutdown_helper();
Harald Welte96c94412017-12-09 03:12:45 +01003278}
3279
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003280/* Verify that Upon receival of SET "location", BSC forwards a TRAP
3281 "location-state" over the SCCPlite IPA conn */
3282testcase TC_ctrl_location() runs on test_CT {
3283 var MSC_ConnHdlr vc_conn;
3284 var integer bts_nr := 0;
3285
3286 f_init(1, true);
3287 f_sleep(1.0);
3288
3289 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234567,fix3d,0.340000,0.560000,0.780000");
3290 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3291 "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
3292
3293 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "1");
3294 f_sleep(2.0);
3295
3296 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234888,fix3d,0.350000,0.570000,0.790000");
3297 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3298 "1234888,fix3d,0.350000,0.570000,0.790000,operational,locked,off,001,01");
3299
3300 /* should match the one from config */
3301 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
3302
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003303 f_shutdown_helper();
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003304}
3305
Harald Welte6f521d82017-12-11 19:52:02 +01003306
3307/***********************************************************************
3308 * Paging Testing
3309 ***********************************************************************/
3310
3311type record Cell_Identity {
3312 GsmMcc mcc,
3313 GsmMnc mnc,
3314 GsmLac lac,
3315 GsmCellId ci
3316};
Harald Welte24135bd2018-03-17 19:27:53 +01003317private const Cell_Identity cid := { '001'H, '01'H, 1, 0 };
Stefan Sperling049a86e2018-03-20 15:51:00 +01003318private const Cell_Identity unknown_cid := { '678'H, 'f90'H, 1, 0 };
Harald Welte6f521d82017-12-11 19:52:02 +01003319
Harald Welte5d1a2202017-12-13 19:51:29 +01003320type set of integer BtsIdList;
3321
3322private function f_bts_in_list(integer bts_id, BtsIdList bts_ids) return boolean {
3323 for (var integer j := 0; j < sizeof(bts_ids); j := j + 1) {
3324 if (bts_id == bts_ids[j]) {
3325 return true;
3326 }
3327 }
3328 return false;
3329}
Harald Welte6f521d82017-12-11 19:52:02 +01003330
3331/* core paging test helper function; used by most paging test cases */
3332private function f_pageing_helper(hexstring imsi,
3333 template BSSMAP_FIELD_CellIdentificationList cid_list,
Harald Welte5d1a2202017-12-13 19:51:29 +01003334 BtsIdList bts_ids := { 0 },
Harald Welte6f521d82017-12-11 19:52:02 +01003335 template RSL_ChanNeeded rsl_chneed := omit,
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003336 template (omit) OCT4 tmsi := omit) runs on test_CT
Harald Welte6f521d82017-12-11 19:52:02 +01003337{
3338 var template BSSMAP_IE_ChannelNeeded bssmap_chneed;
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003339 var template MobileIdentityV mi;
Harald Welte6f521d82017-12-11 19:52:02 +01003340 var RSL_Message rx_rsl;
3341 var integer paging_group := hex2int(imsi[lengthof(imsi)-1]);
Harald Welte5d1a2202017-12-13 19:51:29 +01003342 var integer i;
Harald Welte6f521d82017-12-11 19:52:02 +01003343
3344 f_init();
Harald Welte6f521d82017-12-11 19:52:02 +01003345
3346 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Harald Weltec3068592018-03-17 19:55:31 +01003347 for (i := 0; i < NUM_BTS; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003348 IPA_RSL[i][0].clear;
Harald Welte5d1a2202017-12-13 19:51:29 +01003349 }
Harald Welte6f521d82017-12-11 19:52:02 +01003350
3351 if (isvalue(rsl_chneed)) {
3352 /* The values of 08.08 3.2.2.36 and 08.58 9.3.40 are luckily identical */
3353 bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
3354 } else {
3355 bssmap_chneed := omit;
3356 }
3357
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003358 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
3359 ts_BSSMAP_Paging(imsi, cid_list, tmsi, bssmap_chneed)));
Harald Welte6f521d82017-12-11 19:52:02 +01003360
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003361 if (not istemplatekind(tmsi, "omit")) {
3362 mi := t_MI_TMSI(tmsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003363 } else {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003364 mi := tr_MI_IMSI(imsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003365 }
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003366
Harald Welte5d1a2202017-12-13 19:51:29 +01003367 for (i := 0; i < sizeof(bts_ids); i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003368 rx_rsl := f_exp_ipa_rx(tr_RSL_PAGING_CMD(mi), idx := {bts_ids[i], 0});
Harald Welte5d1a2202017-12-13 19:51:29 +01003369 /* check channel type, paging group */
3370 if (rx_rsl.ies[1].body.paging_group != paging_group) {
3371 setverdict(fail, "Paging for wrong paging group");
3372 }
3373 if (ispresent(rsl_chneed) and
3374 rx_rsl.ies[3].body.chan_needed.chan_needed != valueof(rsl_chneed)) {
3375 setverdict(fail, "RSL Channel Needed != BSSMAP Channel Needed");
3376 }
Harald Welte6f521d82017-12-11 19:52:02 +01003377 }
Harald Welte2fccd982018-01-31 15:48:19 +01003378 f_sleep(2.0);
Harald Welte5d1a2202017-12-13 19:51:29 +01003379 /* do a quick check on all not-included BTSs if they received paging */
3380 for (i := 0; i < NUM_BTS; i := i + 1) {
3381 timer T := 0.1;
3382 if (f_bts_in_list(i, bts_ids)) {
3383 continue;
3384 }
3385 T.start;
3386 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003387 [] IPA_RSL[i][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003388 setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
3389 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003390 [] IPA_RSL[i][0].receive { repeat; }
Harald Welte5d1a2202017-12-13 19:51:29 +01003391 [] T.timeout { }
3392 }
Harald Welte6f521d82017-12-11 19:52:02 +01003393 }
3394
3395 setverdict(pass);
3396}
3397
Harald Welte5d1a2202017-12-13 19:51:29 +01003398const BtsIdList c_BtsId_all := { 0, 1, 2 };
Harald Welte751d3eb2018-01-31 15:51:06 +01003399const BtsIdList c_BtsId_none := { };
Harald Welte5d1a2202017-12-13 19:51:29 +01003400const BtsIdList c_BtsId_LAC1 := { 0, 1 };
3401const BtsIdList c_BtsId_LAC2 := { 2 };
3402
Harald Welte6f521d82017-12-11 19:52:02 +01003403/* PAGING by IMSI + TMSI */
3404testcase TC_paging_imsi_nochan() runs on test_CT {
3405 var BSSMAP_FIELD_CellIdentificationList cid_list;
3406 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Philipp Maier8c04b0a2018-02-23 13:48:48 +01003407 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, omit);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003408 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003409}
3410
3411/* PAGING by IMSI + TMSI */
3412testcase TC_paging_tmsi_nochan() runs on test_CT {
3413 var BSSMAP_FIELD_CellIdentificationList cid_list;
3414 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003415 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, 'A1B2C301'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003416 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003417}
3418
3419/* Paging with different "channel needed' values */
3420testcase TC_paging_tmsi_any() runs on test_CT {
3421 var BSSMAP_FIELD_CellIdentificationList cid_list;
3422 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003423 f_pageing_helper('001010100000002'H, cid_list, c_BtsId_all, RSL_CHANNEED_ANY, 'A1B2C302'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003424 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003425}
3426testcase TC_paging_tmsi_sdcch() runs on test_CT {
3427 var BSSMAP_FIELD_CellIdentificationList cid_list;
3428 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003429 f_pageing_helper('001010100000003'H, cid_list, c_BtsId_all, RSL_CHANNEED_SDCCH, 'A1B2C303'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003430 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003431}
3432testcase TC_paging_tmsi_tch_f() runs on test_CT {
3433 var BSSMAP_FIELD_CellIdentificationList cid_list;
3434 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003435 f_pageing_helper('001010000000004'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_F, 'A1B2C304'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003436 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003437}
3438testcase TC_paging_tmsi_tch_hf() runs on test_CT {
3439 var BSSMAP_FIELD_CellIdentificationList cid_list;
3440 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003441 f_pageing_helper('001010000000005'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_ForH, 'A1B2C305'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003442 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003443}
3444
3445/* Paging by CGI */
3446testcase TC_paging_imsi_nochan_cgi() runs on test_CT {
3447 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3448 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(cid.mcc, cid.mnc, cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003449 f_pageing_helper('001010000000006'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003450 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003451}
3452
3453/* Paging by LAC+CI */
3454testcase TC_paging_imsi_nochan_lac_ci() runs on test_CT {
3455 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3456 cid_list := { cIl_LAC_CI := { ts_BSSMAP_CI_LAC_CI(cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003457 f_pageing_helper('001010000000007'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003458 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003459}
3460
3461/* Paging by CI */
3462testcase TC_paging_imsi_nochan_ci() runs on test_CT {
3463 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3464 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003465 f_pageing_helper('001010000000008'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003466 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003467}
3468
3469/* Paging by LAI */
3470testcase TC_paging_imsi_nochan_lai() runs on test_CT {
3471 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3472 cid_list := { cIl_LAI := { ts_BSSMAP_CI_LAI(cid.mcc, cid.mnc, cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003473 f_pageing_helper('001010000000009'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003474 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003475}
3476
3477/* Paging by LAC */
3478testcase TC_paging_imsi_nochan_lac() runs on test_CT {
3479 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3480 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003481 f_pageing_helper('001010000000010'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003482 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003483}
3484
3485/* Paging by "all in BSS" */
3486testcase TC_paging_imsi_nochan_all() runs on test_CT {
3487 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3488 cid_list := { cIl_allInBSS := ''O };
Harald Welte5d1a2202017-12-13 19:51:29 +01003489 f_pageing_helper('001010000000011'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003490 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003491}
3492
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003493/* Paging by PLMN+LAC+RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003494testcase TC_paging_imsi_nochan_plmn_lac_rnc() runs on test_CT {
3495 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3496 cid_list := { cIl_PLMN_LAC_RNC := { ts_BSSMAP_CI_PLMN_LAC_RNC(cid.mcc, cid.mnc, cid.lac, 12) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003497 f_pageing_helper('001010000000012'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003498 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003499}
Harald Welte6f521d82017-12-11 19:52:02 +01003500
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003501/* Paging by RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003502testcase TC_paging_imsi_nochan_rnc() runs on test_CT {
3503 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3504 cid_list := { cIl_RNC := { int2oct(13, 2) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003505 f_pageing_helper('001010000000013'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003506 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003507}
3508
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003509/* Paging by LAC+RNC; We do not implement; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003510testcase TC_paging_imsi_nochan_lac_rnc() runs on test_CT {
3511 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3512 cid_list := { cIl_LAC_RNC := { ts_BSSMAP_CI_LAC_RNC(cid.lac, 14) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003513 f_pageing_helper('001010000000014'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003514 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003515}
3516
Harald Welte6f521d82017-12-11 19:52:02 +01003517/* Paging on multiple cells (multiple entries in list): Verify all of them page */
Harald Welte751d3eb2018-01-31 15:51:06 +01003518testcase TC_paging_imsi_nochan_lacs() runs on test_CT {
3519 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3520 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(1), ts_BSSMAP_CI_LAC(2) } };
3521 f_pageing_helper('001010000000015'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003522 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003523}
3524
3525/* Paging on empty list: Verify none of them page */
3526testcase TC_paging_imsi_nochan_lacs_empty() runs on test_CT {
3527 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3528 cid_list := { cIl_LAC := { } };
3529 f_pageing_helper('001010000000016'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003530 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003531}
3532
Stefan Sperling049a86e2018-03-20 15:51:00 +01003533/* Paging by CGI with unknown MCC/MNC: Verify nothing is paged. */
3534testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
3535 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3536 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(unknown_cid.mcc, unknown_cid.mnc, unknown_cid.lac, unknown_cid.ci) } };
3537 f_pageing_helper('001010000000006'H, cid_list, c_BtsId_none);
3538 f_shutdown_helper();
3539}
3540
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +01003541/* Send paging response containing invalid (wrongly formatted) MobileIdentity IE. */
3542testcase TC_paging_imsi_nochan_ci_resp_invalid_mi() runs on test_CT {
3543 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3544 var BSSAP_N_CONNECT_ind rx_c_ind;
3545 var DchanTuple dt;
3546 var octetstring rr_pag_resp := '06270003535992617965720000'O;
3547 /* { 06 27 } is { GSM48_PDISC_RR, GSM48_MT_RR_PAG_RESP }
3548 * see 3GPP TS 44.018, table 9.1.25.1
3549 * { 00 } or { 01 } is CKSN + Spare Half Octet, not important
3550 * { 03 53 59 92 } is Mobile Station Classmark
3551 * { 61 79 65 72 00 00 } is the invalid Mobile Identity IE (3GPP TS 24.008, 10.5.1.4),
3552 * Length is 0x61 (97 in decimal).
3553 */
3554
3555 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
3556 f_pageing_helper('001010000000008'H, cid_list, { 0 });
3557
3558 /* Send CHAN RQD and wait for allocation; acknowledge it */
3559 dt.rsl_chan_nr := f_chreq_act_ack();
3560 dt.idx := {0, 0};
3561
3562 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
3563 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), rr_pag_resp));
3564
3565 /* Expevct a CR with a matching Paging response on the A-Interface */
3566 timer T := 5.0;
3567 T.start;
3568 alt {
3569 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
3570 setverdict(pass);
3571 dt.sccp_conn_id := rx_c_ind.connectionId;
3572 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
3573 }
3574 [] BSSAP.receive {
3575 setverdict(fail, "Received unexpected message on A-Interface!");
3576 }
3577 [] T.timeout {
3578 setverdict(fail, "Received nothing on A-Interface!");
3579 }
3580 }
3581
3582 f_perform_clear_test_ct(dt);
3583 f_shutdown_helper();
3584}
3585
Harald Welte6f521d82017-12-11 19:52:02 +01003586/* Verify paging retransmission interval + count */
3587/* Verify paging stops after channel establishment */
Harald Welte6f521d82017-12-11 19:52:02 +01003588/* Test behavior under paging overload */
Harald Welteae026692017-12-09 01:03:01 +01003589
Harald Weltee65d40e2017-12-13 00:09:06 +01003590/* Verify PCH load */
3591testcase TC_paging_imsi_load() runs on test_CT {
3592 var BSSMAP_FIELD_CellIdentificationList cid_list;
3593 timer T := 4.0;
Harald Welte2caa1062018-03-17 18:19:05 +01003594 timer T_retrans := 1.0;
Harald Weltee65d40e2017-12-13 00:09:06 +01003595 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003596 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Weltee65d40e2017-12-13 00:09:06 +01003597
3598 /* tell BSC there is no paging space anymore */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003599 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte3b57ab52018-03-17 18:01:10 +01003600 f_sleep(0.2);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003601 IPA_RSL[0][0].clear;
Harald Weltee65d40e2017-12-13 00:09:06 +01003602
3603 /* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
3604 * there would be 8 retransmissions during 4 seconds */
3605 T.start;
Harald Welte2caa1062018-03-17 18:19:05 +01003606 T_retrans.start;
Harald Weltee65d40e2017-12-13 00:09:06 +01003607 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003608 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Weltee65d40e2017-12-13 00:09:06 +01003609 setverdict(fail, "Received PAGING after LOAD_IND(0)");
Daniel Willmannafce8662018-07-06 23:11:32 +02003610 mtc.stop;
Harald Weltee65d40e2017-12-13 00:09:06 +01003611 }
Harald Welte2caa1062018-03-17 18:19:05 +01003612 [] T_retrans.timeout {
3613 /* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003614 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte2caa1062018-03-17 18:19:05 +01003615 T_retrans.start;
3616 repeat;
3617 }
Harald Weltee65d40e2017-12-13 00:09:06 +01003618 [] T.timeout {
3619 setverdict(pass);
3620 }
3621 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003622
3623 f_shutdown_helper();
Harald Weltee65d40e2017-12-13 00:09:06 +01003624}
3625
Harald Welte235ebf12017-12-15 14:18:16 +01003626/* Verify Paging Counter */
Harald Welte1ff69992017-12-14 12:31:17 +01003627testcase TC_paging_counter() runs on test_CT {
3628 var BSSMAP_FIELD_CellIdentificationList cid_list;
3629 timer T := 4.0;
3630 var integer i;
3631 var integer paging_attempted_bsc;
3632 var integer paging_attempted_bts[NUM_BTS];
Oliver Smith8b343d32021-11-26 13:01:42 +01003633 var integer paging_expired_bsc;
Harald Welte1ff69992017-12-14 12:31:17 +01003634 var integer paging_expired_bts[NUM_BTS];
3635 cid_list := valueof(ts_BSSMAP_CIL_noCell);
3636
3637 f_init();
3638
3639 /* read counters before paging */
3640 paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003641 paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
Harald Welte1ff69992017-12-14 12:31:17 +01003642 for (i := 0; i < NUM_BTS; i := i+1) {
3643 paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
3644 paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
3645 }
3646
3647 f_pageing_helper('001230000000001'H, cid_list, c_BtsId_all);
3648
3649 /* expect the attempted pages on BSC and each BTSs to have incremented by one */
3650 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", paging_attempted_bsc+1);
3651 for (i := 0; i < NUM_BTS; i := i+1) {
3652 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted",
3653 paging_attempted_bts[i]+1);
3654 }
3655
3656 /* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
3657 f_sleep(12.0);
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003658 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
Harald Welte1ff69992017-12-14 12:31:17 +01003659 for (i := 0; i < NUM_BTS; i := i+1) {
3660 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
3661 paging_expired_bts[i]+1);
3662 }
Harald Welte1ff69992017-12-14 12:31:17 +01003663
Philipp Maier282ca4b2018-02-27 17:17:00 +01003664 f_shutdown_helper();
Harald Welte1ff69992017-12-14 12:31:17 +01003665}
3666
3667
Harald Welte10985002017-12-12 09:29:15 +01003668/* Verify paging stops after A-RESET */
3669testcase TC_paging_imsi_a_reset() runs on test_CT {
3670 var BSSMAP_FIELD_CellIdentificationList cid_list;
3671 timer T := 3.0;
3672 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003673 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Welte10985002017-12-12 09:29:15 +01003674
3675 /* Perform a BSSMAP Reset and wait for ACK */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003676 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own, ts_BSSMAP_Reset(0, g_osmux_enabled_cn)));
Harald Welte10985002017-12-12 09:29:15 +01003677 alt {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003678 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[0].sccp_addr_own, g_bssap[0].sccp_addr_peer, tr_BSSMAP_ResetAck(g_osmux_enabled_cn))) { }
Harald Welte10985002017-12-12 09:29:15 +01003679 [] BSSAP.receive { repeat; }
3680 }
3681
Daniel Willmanncbef3982018-07-30 09:22:40 +02003682 /* Wait to avoid a possible race condition if a paging message is
3683 * received right before the reset ACK. */
3684 f_sleep(0.2);
3685
Harald Welte10985002017-12-12 09:29:15 +01003686 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Philipp Maier1e6b4422018-02-23 14:02:13 +01003687 for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003688 IPA_RSL[i][0].clear;
Philipp Maier1e6b4422018-02-23 14:02:13 +01003689 }
Harald Welte10985002017-12-12 09:29:15 +01003690
3691 /* Wait for 3 seconds if any more PAGING CMD are received on RSL */
3692 T.start;
3693 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003694 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte10985002017-12-12 09:29:15 +01003695 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003696 mtc.stop;
Harald Welte10985002017-12-12 09:29:15 +01003697 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003698 [] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003699 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003700 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003701 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003702 [] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003703 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003704 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003705 }
Harald Welte10985002017-12-12 09:29:15 +01003706 [] T.timeout {
3707 setverdict(pass);
3708 }
3709 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003710
3711 f_shutdown_helper();
Harald Welte10985002017-12-12 09:29:15 +01003712}
Harald Welteae026692017-12-09 01:03:01 +01003713
Philipp Maierf45824a2019-08-14 14:44:10 +02003714/* Verify how we handle unsolicited Paging Response. In case of an unsolicit
3715 * paging response we can not know which MSC is in charge, so we will blindly
3716 * pick the first configured MSC. This behavior is required in order to make
3717 * MT-CSFB calls working because in those cases the BSC can not know that the
3718 * MSC has already paged the subscriver via SGs. So any MT-CSFB call will look
3719 * like an unsolicited Paging Response to the MSC.
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003720 */
3721testcase TC_paging_resp_unsol() runs on test_CT {
3722
3723 f_init(1);
Philipp Maierf45824a2019-08-14 14:44:10 +02003724 timer T := 5.0;
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003725
3726 var BSSAP_N_CONNECT_ind rx_c_ind;
3727 var DchanTuple dt;
3728 var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010008880018'H))));
Philipp Maierf45824a2019-08-14 14:44:10 +02003729 var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003730
3731 /* Send CHAN RQD and wait for allocation; acknowledge it */
3732 dt.rsl_chan_nr := f_chreq_act_ack();
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003733 dt.idx := {0, 0};
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003734
3735 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
Pau Espin Pedrole8a51012023-01-03 11:59:59 +01003736 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), rr_pag_resp));
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003737
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003738
Philipp Maierf45824a2019-08-14 14:44:10 +02003739 /* Expevct a CR with a matching Paging response on the A-Interface */
3740 T.start;
3741 alt {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003742 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
Philipp Maierf45824a2019-08-14 14:44:10 +02003743 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003744 dt.sccp_conn_id := rx_c_ind.connectionId;
3745 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
Philipp Maierf45824a2019-08-14 14:44:10 +02003746 }
3747 [] BSSAP.receive {
3748 setverdict(fail, "Received unexpected message on A-Interface!");
3749 }
3750 [] T.timeout {
3751 setverdict(fail, "Received nothing on A-Interface!");
3752 }
3753 }
3754
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003755 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003756 f_shutdown_helper();
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003757}
3758
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003759/* Verify BSC can schedule N paging requests under one minute if BTS buffer is good enough */
3760function f_TC_paging_Nreq(integer num_subscribers, boolean send_pag_load_ind) runs on test_CT {
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003761 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003762 var Hexstrings imsis := {};
3763 var Booleans rx_paging_done := {};
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003764 var integer rx_paging_num := 0;
3765 var integer i;
3766 timer T_rx := 60.0;
3767 timer T_load_ind := 1.0;
3768
3769 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003770 imsis := imsis & {f_gen_imsi(i)};
3771 rx_paging_done := rx_paging_done & { false };
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003772 }
3773
3774 f_init(1, guard_timeout := 100.0);
3775
3776 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003777 IPA_RSL[0][0].clear;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003778 if (send_pag_load_ind) {
3779 /* Tell there's plenty of space at the BTS (UINT16_MAX): */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003780 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(65535));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003781 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003782
3783 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003784 /* Page on LAC-CI of BTS0: */
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003785 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003786 ts_BSSMAP_Paging(imsis[i], valueof(ts_BSSMAP_CIL_LAC_CI({ts_BSSMAP_CI_LAC_CI(1, 0)})),
3787 omit, omit)));
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003788 }
3789
3790 T_rx.start;
3791 T_load_ind.start;
3792 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003793 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?), IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003794 var hexstring imsi := rx_rsl_ud.rsl.ies[2].body.ms_identity.mobileIdentityV.oddEvenInd_identity.imsi.digits;
3795 var hexstring imsi_suffix := substr(imsi, lengthof(imsi)-6, 6);
3796 var charstring imsi_str := hex2str(imsi_suffix);
3797 var integer imsi_idx := str2int(imsi_str);
3798 if (rx_paging_done[imsi_idx] == false) {
3799 rx_paging_done[imsi_idx] := true;
3800 rx_paging_num := rx_paging_num + 1;
Pau Espin Pedrolef7ef632022-04-25 13:34:57 +02003801 } else {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003802 setverdict(fail, "Retrans of ", imsi_str, " happened before Rx initial trans for all reqs. rx_paging_num=", rx_paging_num);
Pau Espin Pedrolef7ef632022-04-25 13:34:57 +02003803 mtc.stop;
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003804 }
3805 if (rx_paging_num < num_subscribers) {
3806 repeat;
3807 }
3808 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003809 [] IPA_RSL[0][0].receive { repeat; }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003810 [] T_load_ind.timeout {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003811 log("[CCH Load Ind timer] received paging requests so far: ", rx_paging_num);
3812 if (send_pag_load_ind) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003813 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(40));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003814 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003815 T_load_ind.start;
3816 repeat;
3817 }
3818 [] T_rx.timeout {
3819 setverdict(fail, "Timeout expecting paging requests, so far ", rx_paging_num);
3820 mtc.stop;
3821 }
3822 }
3823
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003824 /* Drop OML connection to have all paging requests flushed: */
3825 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
3826
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003827 f_shutdown_helper();
3828}
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003829/* Verify BSC can schedule 500 paging requests under one minute if BTS buffer is good enough */
3830testcase TC_paging_500req() runs on test_CT {
3831 f_TC_paging_Nreq(500, true);
3832}
3833/* Same as TC_paging_500req, but without sending CCCH Load Indication, which
3834 * means BTS is always under CCH Load Threshold, aka capable of sending tons of requests.
3835 * Since No CCCH Load Ind, BSC uses a conservative estimation of BTS load, which
3836 * for current config yields ~8req/sec, so 480req/min maximum. */
3837testcase TC_paging_450req_no_paging_load_ind() runs on test_CT {
3838 f_TC_paging_Nreq(450, false);
3839}
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003840
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003841/* Test RSL link drop causes counter increment */
3842testcase TC_rsl_drop_counter() runs on test_CT {
3843 var integer rsl_fail;
3844
Harald Welte89d42e82017-12-17 16:42:41 +01003845 f_init(1);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003846
3847 rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
3848
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003849 f_ipa_rsl_stop(bts[0][0].rsl);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003850
3851 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
3852
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003853 f_shutdown_helper();
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003854}
3855
3856/* TODO: Test OML link drop causes counter increment */
3857
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003858/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
3859function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003860 var IPA_Client client;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003861 timer T := 10.0;
3862
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003863 client.id := "IPA-BTS0-TRX0-RSL";
3864 client.vc_IPA := IPA_Emulation_CT.create(client.id & "-IPA") alive;
3865 client.ccm_pars := c_IPA_default_ccm_pars;
3866 client.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
3867 client.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003868
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01003869 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003870
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003871 f_init_mgcp(0, "VirtMGW");
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003872
3873 /* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003874 map(client.vc_IPA:IPA_PORT, system:IPA);
3875 connect(client.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0][0]);
3876 client.vc_IPA.start(IPA_Emulation.main_client(mp_bsc_ip, mp_bsc_ipa_port, "", 10000, client.ccm_pars));
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003877
3878 /* wait for IPA OML link to connect and then disconnect */
3879 T.start;
3880 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003881 [] IPA_RSL[0][0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003882 T.stop;
3883 return true;
3884 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003885 [] IPA_RSL[0][0].receive { repeat }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003886 [] T.timeout {
Daniel Willmannafce8662018-07-06 23:11:32 +02003887 return false;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003888 }
3889 }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003890 return false;
3891}
3892
3893/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3894testcase TC_rsl_unknown_unit_id() runs on test_CT {
3895 if (f_ipa_unknown_unit_id(mp_bsc_rsl_port)) {
3896 setverdict(pass);
3897 } else {
3898 setverdict(fail, "Timeout RSL waiting for connection to close");
3899 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003900 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003901}
3902
3903
3904/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3905testcase TC_oml_unknown_unit_id() runs on test_CT {
3906 if (f_ipa_unknown_unit_id(mp_bsc_oml_port)) {
3907 setverdict(pass);
3908 } else {
3909 setverdict(fail, "Timeout OML waiting for connection to close");
3910 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003911 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003912}
3913
3914
Harald Weltec1a2fff2017-12-17 11:06:19 +01003915/***********************************************************************
Harald Welte6811d102019-04-14 22:23:14 +02003916 * "New world" test cases using RSL_Emulation + RAN_Emulation
Harald Weltec1a2fff2017-12-17 11:06:19 +01003917 ***********************************************************************/
3918
Harald Welte6811d102019-04-14 22:23:14 +02003919import from RAN_Emulation all;
Harald Welte47cd0e32020-08-21 12:39:11 +02003920import from BSSAP_LE_Emulation all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01003921import from RSL_Emulation all;
3922import from MSC_ConnectionHandler all;
3923
3924type function void_fn(charstring id) runs on MSC_ConnHdlr;
3925
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003926/* helper function to create and connect a MSC_ConnHdlr component
3927 * TODO: allow connecting to TRX1..N, not only TRX0 */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003928private function f_connect_handler(inout MSC_ConnHdlr vc_conn, integer bssap_idx := 0, integer mgwpool_idx := 0) runs on test_CT {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003929 connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003930 connect(vc_conn:RSL, bts[0][0].rsl.vc_RSL:CLIENT_PT);
3931 connect(vc_conn:RSL_PROC, bts[0][0].rsl.vc_RSL:RSL_PROC);
3932 if (isvalue(bts[1][0])) {
3933 connect(vc_conn:RSL1, bts[1][0].rsl.vc_RSL:CLIENT_PT);
3934 connect(vc_conn:RSL1_PROC, bts[1][0].rsl.vc_RSL:RSL_PROC);
Philipp Maier956a92f2018-02-16 10:58:07 +01003935 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003936 if (isvalue(bts[2][0])) {
3937 connect(vc_conn:RSL2, bts[2][0].rsl.vc_RSL:CLIENT_PT);
3938 connect(vc_conn:RSL2_PROC, bts[2][0].rsl.vc_RSL:RSL_PROC);
Neels Hofmeyr91401012019-07-11 00:42:35 +02003939 }
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003940 connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02003941 if (mp_enable_lcs_tests) {
3942 connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
3943 connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
3944 }
Daniel Willmannebdecc02020-08-12 15:30:17 +02003945 connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003946 connect(vc_conn:MGCP_PROC, vc_MGCP[mgwpool_idx]:MGCP_PROC);
3947 connect(vc_conn:MGCP, vc_MGCP[mgwpool_idx]:MGCP_CLIENT);
3948 connect(vc_conn:MGCP_MULTI, vc_MGCP[mgwpool_idx]:MGCP_CLIENT_MULTI);
Harald Welte336820c2018-05-31 20:34:52 +02003949}
3950
Neels Hofmeyrda436782021-07-20 22:09:06 +02003951function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
Harald Welte336820c2018-05-31 20:34:52 +02003952runs on test_CT return MSC_ConnHdlr {
3953 var charstring id := testcasename();
3954 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003955 var integer bssap_idx := 0;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003956 var integer mgwpool_idx := 0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003957 if (isvalue(pars)) {
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003958 var TestHdlrParams pars_val := valueof(pars);
3959 bssap_idx := pars_val.mscpool.bssap_idx;
3960 mgwpool_idx := pars_val.mgwpool_idx;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003961 }
Harald Welte336820c2018-05-31 20:34:52 +02003962 vc_conn := MSC_ConnHdlr.create(id);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003963 f_connect_handler(vc_conn, bssap_idx, mgwpool_idx);
Neels Hofmeyrda436782021-07-20 22:09:06 +02003964 return vc_conn;
3965}
3966
3967function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
3968runs on test_CT return MSC_ConnHdlr {
3969 var charstring id := testcasename();
Harald Weltea0630032018-03-20 21:09:55 +01003970 vc_conn.start(f_handler_init(fn, id, pars));
Harald Weltec1a2fff2017-12-17 11:06:19 +01003971 return vc_conn;
3972}
3973
Neels Hofmeyrda436782021-07-20 22:09:06 +02003974function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
3975runs on test_CT return MSC_ConnHdlr {
3976 return f_start_handler_run(f_start_handler_create(pars), fn, pars);
3977}
3978
Harald Weltea0630032018-03-20 21:09:55 +01003979/* first function inside ConnHdlr component; sets g_pars + starts function */
3980private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
3981runs on MSC_ConnHdlr {
3982 if (isvalue(pars)) {
3983 g_pars := valueof(pars);
3984 }
3985 fn.apply(id);
3986}
3987
Oliver Smith26a3db72021-07-09 13:51:29 +02003988private function f_vty_encryption_a5(charstring options) runs on test_CT {
3989 f_vty_transceive(BSCVTY, "configure terminal");
3990 f_vty_transceive(BSCVTY, "network");
3991 f_vty_transceive(BSCVTY, "encryption a5 " & options);
3992 f_vty_transceive(BSCVTY, "exit");
3993 f_vty_transceive(BSCVTY, "exit");
3994}
3995
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01003996const charstring VTY_A5_DEFAULT := "0 1 3";
3997
Oliver Smith26a3db72021-07-09 13:51:29 +02003998private function f_vty_encryption_a5_reset() runs on test_CT {
3999 /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004000 f_vty_encryption_a5(VTY_A5_DEFAULT);
Oliver Smith26a3db72021-07-09 13:51:29 +02004001}
4002
Harald Welte3c86ea02018-05-10 22:28:05 +02004003/* Establish signalling channel (non-assignment case) followed by cipher mode */
4004private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004005 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4006 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte3c86ea02018-05-10 22:28:05 +02004007 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Philipp Maier23000732018-05-18 11:25:37 +02004008 ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode := omit;
4009 ass_cmd.pdu.bssmap.assignmentRequest.aoIPTransportLayer := omit;
4010 exp_compl.pdu.bssmap.assignmentComplete.circuitIdentityCode := omit;
4011 exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
Harald Welte3c86ea02018-05-10 22:28:05 +02004012
Philipp Maier23000732018-05-18 11:25:37 +02004013 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004014 f_perform_clear();
Harald Welte3c86ea02018-05-10 22:28:05 +02004015}
4016testcase TC_ciph_mode_a5_0() runs on test_CT {
4017 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004018 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004019 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
4020
4021 f_init(1, true);
4022 f_sleep(1.0);
4023 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4024 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004025 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004026}
4027testcase TC_ciph_mode_a5_1() runs on test_CT {
4028 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004029 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004030 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
4031
4032 f_init(1, true);
4033 f_sleep(1.0);
4034 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4035 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004036 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004037}
Oliver Smith50b98122021-07-09 15:00:28 +02004038/* OS#4975: verify that A5/2 is preferred over A5/0 */
4039testcase TC_ciph_mode_a5_2_0() runs on test_CT {
4040 var MSC_ConnHdlr vc_conn;
4041 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4042
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004043 pars.encr := f_encr_params('05'O, '04'O); /* A5/0 and A5/2 (0x01|0x04)*/
Oliver Smith50b98122021-07-09 15:00:28 +02004044
4045 f_init(1, true);
4046 f_vty_encryption_a5("0 1 2 3");
4047 f_sleep(1.0);
4048 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4049 vc_conn.done;
4050 f_vty_encryption_a5_reset();
4051 f_shutdown_helper();
4052}
Oliver Smith1dff88d2021-07-09 08:45:51 +02004053/* OS#4975: verify that A5/1 is preferred over A5/2 */
4054testcase TC_ciph_mode_a5_2_1() runs on test_CT {
4055 var MSC_ConnHdlr vc_conn;
4056 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4057
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004058 pars.encr := f_encr_params('06'O, '02'O); /* A5/1 and A5/2 (0x02|0x04)*/
Oliver Smith1dff88d2021-07-09 08:45:51 +02004059
4060 f_init(1, true);
4061 f_vty_encryption_a5("1 2");
4062 f_sleep(1.0);
4063 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4064 vc_conn.done;
4065 f_vty_encryption_a5_reset();
4066 f_shutdown_helper();
4067}
Harald Welte3c86ea02018-05-10 22:28:05 +02004068testcase TC_ciph_mode_a5_3() runs on test_CT {
4069 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004070 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004071 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
4072
4073 f_init(1, true);
4074 f_sleep(1.0);
4075 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4076 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004077 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004078}
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004079/* Establish a Signalling channel with A5/4 encryption. */
4080testcase TC_ciph_mode_a5_4() runs on test_CT {
4081 var MSC_ConnHdlr vc_conn;
4082 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4083 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Harald Welte3c86ea02018-05-10 22:28:05 +02004084
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004085 f_init(1, true);
Oliver Smith26a3db72021-07-09 13:51:29 +02004086 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004087 f_sleep(1.0);
4088 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4089 vc_conn.done;
Oliver Smith26a3db72021-07-09 13:51:29 +02004090 f_vty_encryption_a5_reset();
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004091 f_shutdown_helper();
4092}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004093/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
4094private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
4095 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4096 var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
4097 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4098 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4099
4100 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004101 f_perform_clear();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004102}
4103testcase TC_assignment_aoip_tla_v6() runs on test_CT {
4104 var MSC_ConnHdlr vc_conn;
4105 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4106
4107 f_init(1, true);
4108 f_sleep(1.0);
4109 vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
4110 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004111 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004112}
4113
Harald Welte3c86ea02018-05-10 22:28:05 +02004114
4115/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
Harald Welte651fcdc2018-05-10 20:23:16 +02004116private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004117 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4118 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004119
Harald Welte552620d2017-12-16 23:21:36 +01004120 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4121 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte73cd2712017-12-17 00:44:52 +01004122
Harald Weltea0630032018-03-20 21:09:55 +01004123 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004124 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004125}
Harald Welte552620d2017-12-16 23:21:36 +01004126testcase TC_assignment_fr_a5_0() runs on test_CT {
4127 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004128 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004129 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
Harald Welte552620d2017-12-16 23:21:36 +01004130
Harald Welte89d42e82017-12-17 16:42:41 +01004131 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004132 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004133 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004134 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004135 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004136}
Harald Welte552620d2017-12-16 23:21:36 +01004137testcase TC_assignment_fr_a5_1() runs on test_CT {
Harald Weltec1a2fff2017-12-17 11:06:19 +01004138 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004139 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004140 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004141
Harald Welte89d42e82017-12-17 16:42:41 +01004142 f_init(1, true);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004143 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004144 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4145 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004146 f_shutdown_helper();
Harald Welte651fcdc2018-05-10 20:23:16 +02004147}
4148testcase TC_assignment_fr_a5_3() runs on test_CT {
4149 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004150 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004151 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004152
Harald Welte651fcdc2018-05-10 20:23:16 +02004153 f_init(1, true);
4154 f_sleep(1.0);
4155 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004156 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004157 f_shutdown_helper();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004158}
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004159/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
4160testcase TC_assignment_fr_a5_4() runs on test_CT {
4161 var MSC_ConnHdlr vc_conn;
4162 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4163 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
4164
4165 f_init(1, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02004166 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004167 f_sleep(1.0);
4168 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4169 vc_conn.done;
Oliver Smith7eabd312021-07-12 14:18:56 +02004170 f_vty_encryption_a5_reset();
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004171 f_shutdown_helper();
4172}
Harald Weltec1a2fff2017-12-17 11:06:19 +01004173
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +02004174/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
4175testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
4176 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4177 var MSC_ConnHdlr vc_conn;
4178
4179 f_init(1, true);
4180 f_sleep(1.0);
4181
4182 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
4183 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
4184 vc_conn.done;
4185 f_shutdown_helper();
4186}
4187
Harald Welte552620d2017-12-16 23:21:36 +01004188/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
4189private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004190 g_pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004191 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02004192 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004193
4194 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02004195 /* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
4196
Harald Weltea0630032018-03-20 21:09:55 +01004197 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004198 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004199}
Harald Welte552620d2017-12-16 23:21:36 +01004200testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
4201 var MSC_ConnHdlr vc_conn;
4202
Harald Welte89d42e82017-12-17 16:42:41 +01004203 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004204 f_sleep(1.0);
4205
Harald Welte8863fa12018-05-10 20:15:27 +02004206 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
Harald Welte552620d2017-12-16 23:21:36 +01004207 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004208 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004209}
4210
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004211private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
4212 var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
4213 var PDU_BSSAP exp_ass_req := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004214
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004215 exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4216 exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4217
4218 /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
4219
4220 var BSSMAP_FIELD_CodecType codecType;
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004221
4222 codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
4223 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
4224
4225 f_create_chan_and_exp();
4226 /* we should now have a COMPL_L3 at the MSC */
4227
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004228 /* Start ciphering, expect Cipher Mode Reject */
Neels Hofmeyr6c388f22021-06-11 02:36:56 +02004229 f_cipher_mode(g_pars.encr, exp_fail := true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004230 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004231}
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004232testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
4233 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004234 var MSC_ConnHdlr vc_conn;
4235
Harald Welte89d42e82017-12-17 16:42:41 +01004236 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004237 f_sleep(1.0);
4238
Neels Hofmeyr0588cad2021-06-11 01:38:18 +02004239 pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004240 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004241 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004242 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004243}
4244
4245
Harald Welte4532e0a2017-12-23 02:05:44 +01004246private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004247 g_pars := f_gen_test_hdlr_pars();
Harald Welte4532e0a2017-12-23 02:05:44 +01004248 var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
Philipp Maier48604732018-10-09 15:00:37 +02004249 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte4532e0a2017-12-23 02:05:44 +01004250 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004251
4252 f_statsd_reset();
Harald Weltea0630032018-03-20 21:09:55 +01004253 f_establish_fully(ass_cmd, exp_compl);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004254
4255 var StatsDExpects expect := {
Daniel Willmannc5398f72020-09-21 10:41:35 +02004256 { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
4257 { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
Daniel Willmannebdecc02020-08-12 15:30:17 +02004258 { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
4259 { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
4260 };
4261 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004262 f_perform_clear();
Harald Welte4532e0a2017-12-23 02:05:44 +01004263}
4264
4265testcase TC_assignment_sign() runs on test_CT {
4266 var MSC_ConnHdlr vc_conn;
4267
4268 f_init(1, true);
4269 f_sleep(1.0);
4270
Harald Welte8863fa12018-05-10 20:15:27 +02004271 vc_conn := f_start_handler(refers(f_tc_assignment_sign));
Harald Welte4532e0a2017-12-23 02:05:44 +01004272 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004273 f_shutdown_helper();
Harald Welte4532e0a2017-12-23 02:05:44 +01004274}
4275
Harald Welte60aa5762018-03-21 19:33:13 +01004276/***********************************************************************
4277 * Codec (list) testing
4278 ***********************************************************************/
4279
4280/* check if the given rsl_mode is compatible with the a_elem */
4281private function f_match_codec(BSSMAP_FIELD_CodecElement a_elem, RSL_IE_ChannelMode rsl_mode)
4282return boolean {
4283 select (a_elem.codecType) {
4284 case (GSM_FR) {
4285 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1))) {
4286 return true;
4287 }
4288 }
4289 case (GSM_HR) {
4290 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1))) {
4291 return true;
4292 }
4293 }
4294 case (GSM_EFR) {
4295 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2))) {
4296 return true;
4297 }
4298 }
4299 case (FR_AMR) {
4300 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3))) {
4301 return true;
4302 }
4303 }
4304 case (HR_AMR) {
4305 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3))) {
4306 return true;
4307 }
4308 }
4309 case else { }
4310 }
4311 return false;
4312}
4313
4314/* check if the given rsl_mode is compatible with the a_list */
4315private function f_match_codecs(BSSMAP_IE_SpeechCodecList a_list, RSL_IE_ChannelMode rsl_mode)
4316return boolean {
4317 for (var integer i := 0; i < sizeof(a_list); i := i+1) {
4318 if (f_match_codec(a_list.codecElements[i], rsl_mode)) {
4319 return true;
4320 }
4321 }
4322 return false;
4323}
4324
4325/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
Philipp Maier61f6b572018-07-06 14:03:38 +02004326function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
Harald Welte60aa5762018-03-21 19:33:13 +01004327return BSSMAP_IE_ChannelType {
4328 /* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
4329 var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
4330 select (a_elem.codecType) {
4331 case (GSM_FR) {
4332 ret.channelRateAndType := ChRate_TCHF;
4333 ret.speechId_DataIndicator := Spdi_TCHF_FR;
4334 }
4335 case (GSM_HR) {
4336 ret.channelRateAndType := ChRate_TCHH;
4337 ret.speechId_DataIndicator := Spdi_TCHH_HR;
4338 }
4339 case (GSM_EFR) {
4340 ret.channelRateAndType := ChRate_TCHF;
4341 ret.speechId_DataIndicator := Spdi_TCHF_EFR;
4342 }
4343 case (FR_AMR) {
4344 ret.channelRateAndType := ChRate_TCHF;
4345 ret.speechId_DataIndicator := Spdi_TCHF_AMR;
4346 }
4347 case (HR_AMR) {
4348 ret.channelRateAndType := ChRate_TCHH;
4349 ret.speechId_DataIndicator := Spdi_TCHH_AMR;
4350 }
4351 case else {
4352 setverdict(fail, "Unsupported codec ", a_elem);
Daniel Willmannafce8662018-07-06 23:11:32 +02004353 mtc.stop;
Harald Welte60aa5762018-03-21 19:33:13 +01004354 }
4355 }
4356 return ret;
4357}
4358
Harald Weltea63b9102018-03-22 20:36:16 +01004359private function f_rsl_chmod_tmpl_from_codec(BSSMAP_FIELD_CodecElement a_elem)
4360return template RSL_IE_Body {
4361 var template RSL_IE_Body mode_ie := {
4362 chan_mode := {
4363 len := ?,
4364 reserved := ?,
4365 dtx_d := ?,
4366 dtx_u := ?,
4367 spd_ind := RSL_SPDI_SPEECH,
4368 ch_rate_type := -,
Oliver Smith0033b122023-02-28 13:30:53 +01004369 u := { speech := - }
Harald Weltea63b9102018-03-22 20:36:16 +01004370 }
4371 }
4372
4373 select (a_elem.codecType) {
4374 case (GSM_FR) {
4375 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004376 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004377 }
4378 case (GSM_HR) {
4379 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004380 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004381 }
4382 case (GSM_EFR) {
4383 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004384 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM2;
Harald Weltea63b9102018-03-22 20:36:16 +01004385 }
4386 case (FR_AMR) {
4387 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004388 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004389 }
4390 case (HR_AMR) {
4391 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004392 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004393 }
4394 }
4395 return mode_ie;
4396}
4397
Harald Welte60aa5762018-03-21 19:33:13 +01004398type record CodecListTest {
4399 BSSMAP_IE_SpeechCodecList codec_list,
4400 charstring id
4401}
4402type record of CodecListTest CodecListTests
4403
4404private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004405 f_assignment_codec(id);
4406}
4407
4408private function f_assignment_codec(charstring id, boolean do_perform_clear := true) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02004409 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02004410 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welte60aa5762018-03-21 19:33:13 +01004411
4412 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004413 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte79f3f542018-05-25 20:02:37 +02004414 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4415 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
4416 g_pars.ass_codec_list.codecElements[0];
Philipp Maierd0e64b02019-03-13 14:15:23 +01004417 if (isvalue(g_pars.expect_mr_s0_s7)) {
4418 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
4419 g_pars.expect_mr_s0_s7;
4420 }
Harald Welte79f3f542018-05-25 20:02:37 +02004421 }
Harald Welte60aa5762018-03-21 19:33:13 +01004422 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4423 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
Harald Welte60aa5762018-03-21 19:33:13 +01004424 log("expecting ASS COMPL like this: ", exp_compl);
4425
4426 f_establish_fully(ass_cmd, exp_compl);
Harald Weltea63b9102018-03-22 20:36:16 +01004427
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004428 if (not g_pars.expect_channel_mode_modify) {
4429 /* Verify that the RSL-side activation actually matches our expectations */
4430 var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
Harald Weltea63b9102018-03-22 20:36:16 +01004431
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004432 var RSL_IE_Body mode_ie;
4433 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
4434 setverdict(fail, "Couldn't find CHAN_MODE IE");
Daniel Willmannafce8662018-07-06 23:11:32 +02004435 mtc.stop;
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004436 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004437 var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
4438 if (not match(mode_ie, t_mode_ie)) {
4439 log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
4440 setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004441 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004442
4443 var RSL_IE_Body mr_conf;
4444 if (g_pars.expect_mr_conf_ie != omit) {
4445 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
4446 setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
4447 mtc.stop;
4448 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004449 log("found RSL MR CONFIG IE: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004450
4451 if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
Vadim Yanitskiy8b189372022-09-14 17:31:17 +07004452 setverdict(fail, "RSL MR CONFIG IE does not match expectation. ",
4453 "Expected: ", g_pars.expect_mr_conf_ie, ", got: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004454 }
4455 } else {
4456 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
4457 log("found RSL MR CONFIG IE: ", mr_conf);
4458 setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
4459 mtc.stop;
4460 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004461 }
4462 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004463
4464 if (do_perform_clear) {
4465 f_perform_clear();
4466 }
Harald Welte60aa5762018-03-21 19:33:13 +01004467}
4468
Philipp Maierd0e64b02019-03-13 14:15:23 +01004469private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
4470
4471 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4472 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4473
4474 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004475 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maierd0e64b02019-03-13 14:15:23 +01004476 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4477 }
4478 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4479 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
4480 log("expecting ASS FAIL like this: ", exp_fail);
4481
4482 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004483 f_perform_clear();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004484}
4485
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004486const CounterNameVals counternames_bsc_bts_assignment := {
4487 { "assignment:attempted", 0 },
4488 { "assignment:completed", 0 },
4489 { "assignment:stopped", 0 },
4490 { "assignment:no_channel", 0 },
4491 { "assignment:timeout", 0 },
4492 { "assignment:failed", 0 },
4493 { "assignment:error", 0 }
4494};
4495
4496const CounterNameVals counternames_bts_assignment := {
4497 { "assignment:attempted_sign", 0 },
4498 { "assignment:attempted_speech", 0 },
4499 { "assignment:completed_sign", 0 },
4500 { "assignment:completed_speech", 0 },
4501 { "assignment:stopped_sign", 0 },
4502 { "assignment:stopped_speech", 0 },
4503 { "assignment:no_channel_sign", 0 },
4504 { "assignment:no_channel_speech", 0 },
4505 { "assignment:timeout_sign", 0 },
4506 { "assignment:timeout_speech", 0 },
4507 { "assignment:failed_sign", 0 },
4508 { "assignment:failed_speech", 0 },
4509 { "assignment:error_sign", 0 },
4510 { "assignment:error_speech", 0 }
4511};
4512
4513function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
4514 var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
4515 f_ctrs_bts_init(bts_count, bts_names);
4516 f_ctrs_bsc_init(counternames_bsc_bts_assignment);
4517}
4518
Harald Welte60aa5762018-03-21 19:33:13 +01004519testcase TC_assignment_codec_fr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004520 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004521 var MSC_ConnHdlr vc_conn;
4522
4523 f_init(1, true);
4524 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004525 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004526
4527 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004528 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004529 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004530
4531 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4532 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4533 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4534 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4535 f_ctrs_bts_verify();
4536
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004537 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004538}
4539
4540testcase TC_assignment_codec_hr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004541 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004542 var MSC_ConnHdlr vc_conn;
4543
4544 f_init(1, true);
4545 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004546 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004547
4548 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004549 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004550 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004551
4552 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4553 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4554 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4555 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4556 f_ctrs_bts_verify();
4557
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004558 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004559}
4560
4561testcase TC_assignment_codec_efr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004562 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004563 var MSC_ConnHdlr vc_conn;
4564
4565 f_init(1, true);
4566 f_sleep(1.0);
4567
4568 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004569 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004570 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004571 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004572}
4573
Philipp Maierd0e64b02019-03-13 14:15:23 +01004574/* Allow 5,90k only (current default config) */
4575private function f_allow_amr_rate_5_90k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004576 f_vty_cfg_msc(BSCVTY, 0, {
4577 "amr-config 12_2k forbidden",
4578 "amr-config 10_2k forbidden",
4579 "amr-config 7_95k forbidden",
4580 "amr-config 7_40k forbidden",
4581 "amr-config 6_70k forbidden",
4582 "amr-config 5_90k allowed",
4583 "amr-config 5_15k forbidden",
4584 "amr-config 4_75k forbidden"
4585 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004586}
4587
4588/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
4589 * ("Config-NB-Code = 1") */
4590private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004591 f_vty_cfg_msc(BSCVTY, 0, {
4592 "amr-config 12_2k allowed",
4593 "amr-config 10_2k forbidden",
4594 "amr-config 7_95k forbidden",
4595 "amr-config 7_40k allowed",
4596 "amr-config 6_70k forbidden",
4597 "amr-config 5_90k allowed",
4598 "amr-config 5_15k forbidden",
4599 "amr-config 4_75k allowed"
4600 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004601}
4602
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004603private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
4604 var charstring tch;
4605 if (fr) {
4606 tch := "tch-f";
4607 } else {
4608 tch := "tch-h";
4609 }
4610 f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
4611}
4612
4613/* Set the AMR start-mode for this TCH back to the default configuration. */
4614private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
4615 f_vty_amr_start_mode_set(fr, "auto");
4616}
4617
Harald Welte60aa5762018-03-21 19:33:13 +01004618testcase TC_assignment_codec_amr_f() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004619 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004620 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004621
4622 /* Note: This setups the codec configuration. The parameter payload in
4623 * mr_conf must be consistant with the parameter codecElements in pars
4624 * and also must match the amr-config in osmo-bsc.cfg! */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004625 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004626 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004627 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004628 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004629
Harald Welte60aa5762018-03-21 19:33:13 +01004630 f_init(1, true);
4631 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004632 f_vty_amr_start_mode_set(true, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004633 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004634
Harald Welte8863fa12018-05-10 20:15:27 +02004635 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004636 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004637
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004638 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4639 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4640 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4641 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4642 f_ctrs_bts_verify();
4643
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004644 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004645 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004646}
4647
4648testcase TC_assignment_codec_amr_h() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004649 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004650 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004651
4652 /* See note above */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004653 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004654 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004655 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004656 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004657
Harald Welte60aa5762018-03-21 19:33:13 +01004658 f_init(1, true);
4659 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004660 f_vty_amr_start_mode_set(false, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004661 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004662
Harald Welte8863fa12018-05-10 20:15:27 +02004663 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004664 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004665
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004666 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4667 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4668 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4669 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4670 f_ctrs_bts_verify();
4671
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004672 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004673 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004674}
4675
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004676/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
4677testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
4678 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4679 var MSC_ConnHdlr vc_conn;
4680
4681 f_init(1, true);
4682 f_sleep(1.0);
4683
4684 /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
4685 * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
4686 * expecting a Channel Mode Modify if the channel type is compatible. */
4687 f_disable_all_sdcch();
4688 f_disable_all_tch_h();
4689
4690 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4691 pars.expect_channel_mode_modify := true;
4692 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4693 vc_conn.done;
4694
4695 f_enable_all_sdcch();
4696 f_enable_all_tch();
4697 f_shutdown_helper();
4698}
4699
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004700/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
4701testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
4702 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4703 var MSC_ConnHdlr vc_conn;
4704
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004705 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4706 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
4707 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy36fe9582022-09-14 15:25:04 +07004708 pars.expect_mr_conf_ie := c_mr_conf_5_90;
4709 pars.expect_mr_conf_ie.multirate_cfg.icmi := false; /* expect ICMI=0, smod=00: */
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004710
4711 f_init(1, true);
4712 f_sleep(1.0);
4713
4714 /* First set nonzero start mode bits */
4715 f_vty_amr_start_mode_set(true, "4");
4716 /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
4717 * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
4718 * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
4719 f_vty_amr_start_mode_set(true, "auto");
4720
4721 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4722 vc_conn.done;
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004723
4724 /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
4725 f_vty_amr_start_mode_set(true, "1");
4726 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004727 f_shutdown_helper();
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004728}
4729
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004730function f_TC_assignment_codec_amr(boolean fr, RSL_IE_MultirateCfg mr_cfg,
4731 bitstring s8_s0, bitstring exp_s8_s0,
4732 charstring start_mode := "1")
Philipp Maierd0e64b02019-03-13 14:15:23 +01004733runs on test_CT {
4734
4735 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4736 var MSC_ConnHdlr vc_conn;
4737
Philipp Maierd0e64b02019-03-13 14:15:23 +01004738 if (fr) {
4739 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4740 } else {
4741 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4742 }
4743 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4744 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004745 pars.expect_mr_conf_ie := { multirate_cfg := mr_cfg };
Philipp Maierd0e64b02019-03-13 14:15:23 +01004746 pars.expect_mr_s0_s7 := exp_s8_s0;
4747
4748 f_init(1, true);
4749 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004750 f_vty_amr_start_mode_set(fr, start_mode);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004751 f_sleep(1.0);
4752
4753 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4754 vc_conn.done;
4755 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004756 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004757}
4758
4759function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
4760runs on test_CT {
4761
4762 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4763 var MSC_ConnHdlr vc_conn;
4764
4765 if (fr) {
4766 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4767 } else {
4768 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4769 }
4770 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4771 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4772
4773 f_init(1, true);
4774 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004775 f_vty_amr_start_mode_set(fr, "1");
Philipp Maierd0e64b02019-03-13 14:15:23 +01004776 f_sleep(1.0);
4777
4778 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
4779 vc_conn.done;
4780 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004781 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004782}
4783
Philipp Maierd0e64b02019-03-13 14:15:23 +01004784/* Set S1, we expect an AMR multirate configuration IE with all four rates
4785 * set. */
4786testcase TC_assignment_codec_amr_f_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004787 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4788 params := '20882208'O));
4789 f_TC_assignment_codec_amr(true, mr_cfg, '00000011'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004790 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004791}
4792
4793/* Set S1, we expect an AMR multirate configuration IE with the lower three
4794 * rates set. */
4795testcase TC_assignment_codec_amr_h_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004796 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4797 params := '208820'O));
4798 f_TC_assignment_codec_amr(false, mr_cfg, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004799 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004800}
4801
4802/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4803 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4804testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004805 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4806 params := '20882208'O));
4807 f_TC_assignment_codec_amr(true, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004808 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004809}
4810
4811/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4812 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4813testcase TC_assignment_codec_amr_h_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004814 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4815 params := '208820'O));
4816 f_TC_assignment_codec_amr(false, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004817 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004818}
4819
4820/* The following block of tests selects more and more rates until all four
4821 * possible rates are in the active set (full rate) */
4822testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004823 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4824 f_TC_assignment_codec_amr(true, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004825 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004826}
4827
4828testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004829 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4830 params := '2080'O));
4831 f_TC_assignment_codec_amr(true, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004832 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004833}
4834
4835testcase TC_assignment_codec_amr_f_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004836 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4837 params := '208820'O));
4838 f_TC_assignment_codec_amr(true, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004839 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004840}
4841
4842testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004843 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4844 params := '20882208'O));
4845 f_TC_assignment_codec_amr(true, mr_cfg, '10010101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004846 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004847}
4848
4849/* The following block of tests selects more and more rates until all three
4850 * possible rates are in the active set (half rate) */
4851testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004852 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4853 f_TC_assignment_codec_amr(false, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004854 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004855}
4856
4857testcase TC_assignment_codec_amr_h_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004858 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4859 params := '2080'O));
4860 f_TC_assignment_codec_amr(false, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004861 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004862}
4863
4864testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004865 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4866 params := '208820'O));
4867 f_TC_assignment_codec_amr(false, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004868 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004869}
4870
4871/* The following block tests what happens when the MSC does offer rate
4872 * configurations that are not supported by the BSC. Normally such situations
4873 * should not happen because the MSC gets informed by the BSC in advance via
4874 * the L3 COMPLETE message which rates are applicable. The MSC should not try
4875 * to offer rates that are not applicable anyway. */
4876
4877testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004878 /* Try to include 12,2k in into the active set even though the channel
4879 * is half rate only. The BSC is expected to remove the 12,0k */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004880 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4881 params := '208820'O));
4882 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004883 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004884}
4885
4886testcase TC_assignment_codec_amr_f_S01234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004887 /* See what happens when all rates are selected at once. Since then
4888 * Also S1 is selected, this setting will be prefered and we should
4889 * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004890 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4891 params := '20882208'O));
4892 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004893 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004894}
4895
4896testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004897 /* Same as above, but with S1 missing, the MSC is then expected to
4898 * select the currently supported rates, which are also 12.2k, 7,40k,
4899 * 5,90k, and 4,75k, into the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004900 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4901 params := '20882208'O));
4902 f_TC_assignment_codec_amr(true, mr_cfg, '11111101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004903 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004904}
4905
4906testcase TC_assignment_codec_amr_f_zero() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004907 /* Try to select no rates at all */
4908 f_TC_assignment_codec_amr_fail(true, '00000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004909 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004910}
4911
4912testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004913 /* Try to select only unsupported rates */
4914 f_TC_assignment_codec_amr_fail(true, '01101000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004915 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004916}
4917
4918testcase TC_assignment_codec_amr_h_S7() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004919 /* Try to select 12,2k for half rate */
4920 f_TC_assignment_codec_amr_fail(false, '10000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004921 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004922}
4923
Neels Hofmeyr21863562020-11-26 00:34:33 +00004924testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004925 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4926 codec_modes := '10010101'B,
4927 params := '20882208'O));
4928 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004929 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004930}
4931
4932testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004933 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4934 codec_modes := '00010101'B,
4935 params := '208820'O));
4936 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B,
Neels Hofmeyr21863562020-11-26 00:34:33 +00004937 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004938 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004939}
4940
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004941testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004942 /* "amr tch-f modes 0 2 4 7" => total 4 modes and start mode 4 => '11'B on the wire */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004943 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 3,
4944 codec_modes := '10010101'B,
4945 params := '20882208'O));
4946 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004947 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004948}
4949
4950testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004951 /* "amr tch-h modes 0 2 4" => total 3 modes and start mode 4 => '10'B on the wire */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004952 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 2,
4953 codec_modes := '00010101'B,
4954 params := '208820'O));
4955 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004956 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004957}
4958
Philipp Maierac09bfc2019-01-08 13:41:39 +01004959private function f_disable_all_tch_f() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004960 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 borken");
4961 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 borken");
4962 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 borken");
4963 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004964}
4965
4966private function f_disable_all_tch_h() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004967 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 borken");
4968 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004969}
4970
4971private function f_enable_all_tch() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004972 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 unused");
4973 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 unused");
4974 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 unused");
4975 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 unused");
4976 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 unused");
4977 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004978}
4979
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004980private function f_disable_all_sdcch() runs on test_CT {
4981 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
4982 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
4983 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
4984 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
4985}
4986
4987private function f_enable_all_sdcch() runs on test_CT {
4988 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
4989 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
4990 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
4991 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
4992}
4993
Philipp Maierac09bfc2019-01-08 13:41:39 +01004994/* Allow HR only */
4995private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs on MSC_ConnHdlr {
4996 g_pars := f_gen_test_hdlr_pars();
4997 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4998 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4999 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5000 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5001 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5002 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5003 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005004 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005005}
5006
5007/* Allow FR only */
5008private function f_TC_assignment_codec_xr_exhausted_req_fr(charstring id) runs on MSC_ConnHdlr {
5009 g_pars := f_gen_test_hdlr_pars();
5010 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5011 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5012 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5013 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5014 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5015 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5016 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005017 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005018}
5019
5020/* Allow HR only (expect assignment failure) */
5021private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) runs on MSC_ConnHdlr {
5022 g_pars := f_gen_test_hdlr_pars();
5023 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5024 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5025 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5026 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5027 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5028 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5029 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005030 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005031}
5032
5033/* Allow FR only (expect assignment failure) */
5034private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) runs on MSC_ConnHdlr {
5035 g_pars := f_gen_test_hdlr_pars();
5036 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5037 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5038 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5039 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5040 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5041 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5042 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005043 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005044}
5045
5046/* Allow FR and HR, but prefer FR */
5047private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5048 g_pars := f_gen_test_hdlr_pars();
5049 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5050 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5051 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5052 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5053 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5054 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5055 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5056 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005057 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005058}
5059
5060/* Allow FR and HR, but prefer HR */
5061private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5062 g_pars := f_gen_test_hdlr_pars();
5063 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5064 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5065 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5066 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5067 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5068 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5069 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5070 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005071 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005072}
5073
5074/* Allow FR and HR, but prefer FR */
5075private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5076 g_pars := f_gen_test_hdlr_pars();
5077 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5078 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5079 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5080 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5081 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5082 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5083 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5084 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005085 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005086}
5087
5088/* Allow FR and HR, but prefer HR */
5089private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5090 g_pars := f_gen_test_hdlr_pars();
5091 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5092 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5093 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5094 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5095 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5096 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5097 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5098 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005099 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005100}
5101
5102/* Request a HR channel while all FR channels are exhausted, this is expected
5103 * to work without conflicts */
5104testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
5105 var MSC_ConnHdlr vc_conn;
5106 f_init(1, true);
5107 f_sleep(1.0);
5108 f_enable_all_tch();
5109 f_disable_all_tch_f();
5110 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
5111 vc_conn.done;
5112 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005113 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005114}
5115
5116/* Request a FR channel while all FR channels are exhausted, this is expected
5117 * to fail. */
5118testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
5119 var MSC_ConnHdlr vc_conn;
5120 f_init(1, true);
5121 f_sleep(1.0);
5122 f_enable_all_tch();
5123 f_disable_all_tch_f();
5124 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
5125 vc_conn.done;
5126 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005127 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005128}
5129
5130/* Request a FR (prefered) or alternatively a HR channel while all FR channels
5131 * are exhausted, this is expected to be resolved by selecting a HR channel. */
5132testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
5133 var MSC_ConnHdlr vc_conn;
5134 f_init(1, true);
5135 f_sleep(1.0);
5136 f_enable_all_tch();
5137 f_disable_all_tch_f();
5138 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
5139 vc_conn.done;
5140 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005141 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005142}
5143
5144/* Request a HR (prefered) or alternatively a FR channel while all FR channels
5145 * are exhausted, this is expected to work without conflicts. */
5146testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
5147 var MSC_ConnHdlr vc_conn;
5148 f_init(1, true);
5149 f_sleep(1.0);
5150 f_enable_all_tch();
5151 f_disable_all_tch_f();
5152 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
5153 vc_conn.done;
5154 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005155 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005156}
5157
5158/* Request a FR channel while all HR channels are exhausted, this is expected
5159 * to work without conflicts */
5160testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
5161 var MSC_ConnHdlr vc_conn;
5162 f_init(1, true);
5163 f_sleep(1.0);
5164 f_enable_all_tch();
5165 f_disable_all_tch_h();
5166 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
5167 vc_conn.done;
5168 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005169 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005170}
5171
5172/* Request a HR channel while all HR channels are exhausted, this is expected
5173 * to fail. */
5174testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
5175 var MSC_ConnHdlr vc_conn;
5176 f_init(1, true);
5177 f_sleep(1.0);
5178 f_enable_all_tch();
5179 f_disable_all_tch_h();
5180 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
5181 vc_conn.done;
5182 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005183 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005184}
5185
5186/* Request a HR (prefered) or alternatively a FR channel while all HR channels
5187 * are exhausted, this is expected to be resolved by selecting a FR channel. */
5188testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
5189 var MSC_ConnHdlr vc_conn;
5190 f_init(1, true);
5191 f_sleep(1.0);
5192 f_enable_all_tch();
5193 f_disable_all_tch_h();
5194 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
5195 vc_conn.done;
5196 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005197 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005198}
5199
5200/* Request a FR (prefered) or alternatively a HR channel while all HR channels
5201 * are exhausted, this is expected to work without conflicts. */
5202testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
5203 var MSC_ConnHdlr vc_conn;
5204 f_init(1, true);
5205 f_sleep(1.0);
5206 f_enable_all_tch();
5207 f_disable_all_tch_h();
5208 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
5209 vc_conn.done;
5210 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005211 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005212}
5213
5214/* Allow FR and HR, but prefer HR */
5215private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5216 g_pars := f_gen_test_hdlr_pars();
5217 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5218 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5219 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5220 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5221 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5222 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5223 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5224 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005225 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005226}
5227
5228/* Allow FR and HR, but prefer FR */
5229private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5230 g_pars := f_gen_test_hdlr_pars();
5231 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5232 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5233 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5234 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5235 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5236 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5237 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5238 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005239 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005240}
5241
5242/* Request a HR (prefered) or alternatively a FR channel, it is expected that
5243 * HR, which is the prefered type, is selected. */
5244testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
5245 var MSC_ConnHdlr vc_conn;
5246 f_init(1, true);
5247 f_sleep(1.0);
5248 f_enable_all_tch();
5249 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
5250 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005251 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005252}
5253
5254/* Request a FR (prefered) or alternatively a HR channel, it is expected that
5255 * FR, which is the prefered type, is selected. */
5256testcase TC_assignment_codec_req_fr_hr() runs on test_CT {
5257 var MSC_ConnHdlr vc_conn;
5258 f_init(1, true);
5259 f_sleep(1.0);
5260 f_enable_all_tch();
5261 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_fr_hr));
5262 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005263 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005264}
5265
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005266/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
5267private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
5268 g_pars := f_gen_test_hdlr_pars();
5269 g_pars.ra := '02'O; /* RA containing reason=LU */
5270
5271 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5272 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5273 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5274 var template uint3_t tsc := ?;
5275
5276 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5277 f_create_bssmap_exp(l3_enc);
5278 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5279 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5280
5281 /* we should now have a COMPL_L3 at the MSC */
5282 timer T := 10.0;
5283 T.start;
5284 alt {
5285 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5286 [] T.timeout {
5287 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5288 }
5289 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005290
5291 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005292}
5293testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
5294 var MSC_ConnHdlr vc_conn;
5295 f_init(1, true);
5296 f_sleep(1.0);
5297 f_disable_all_sdcch();
5298 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
5299 vc_conn.done;
5300 f_enable_all_sdcch();
5301 f_shutdown_helper();
5302}
5303
5304/* Request a signalling channel with all SDCCH exhausted, it is
5305 expected that no TCH will be selected for signalling and assigment will fail
5306 because it's dictated by VTY config */
5307testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
5308 var RSL_Message rsl_unused, rsl_msg;
5309 var GsmRrMessage rr;
5310 f_init(1, false);
5311 f_sleep(1.0);
5312 f_vty_allow_tch_for_signalling(false, 0);
5313 f_disable_all_sdcch();
5314
5315 /* RA containing reason=LU */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005316 f_ipa_tx(ts_RSL_CHAN_RQD('02'O, 2342));
5317 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005318 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
5319 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
5320 setverdict(fail, "Expected reject");
5321 }
5322
5323 f_vty_allow_tch_for_signalling(true, 0);
5324 f_enable_all_sdcch();
5325 f_shutdown_helper();
5326}
5327
5328/* Request a voice channel with all SDCCH exhausted, it is
5329 * expected that TCH channel will be allocated since the VTY option is only
5330 * aimed at signalling requests */
5331private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
5332 g_pars := f_gen_test_hdlr_pars();
5333 g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
5334
5335 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5336 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5337 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5338 var template uint3_t tsc := ?;
5339
5340 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5341 f_create_bssmap_exp(l3_enc);
5342 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5343 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5344
5345 /* we should now have a COMPL_L3 at the MSC */
5346 timer T := 10.0;
5347 T.start;
5348 alt {
5349 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5350 [] T.timeout {
5351 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5352 }
5353 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005354 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005355}
5356testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
5357 var MSC_ConnHdlr vc_conn;
5358 f_init(1, true);
5359 f_sleep(1.0);
5360 f_vty_allow_tch_for_signalling(false, 0);
5361 f_disable_all_sdcch();
5362
5363 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
5364 vc_conn.done;
5365
5366 f_vty_allow_tch_for_signalling(true, 0);
5367 f_enable_all_sdcch();
5368 f_shutdown_helper();
5369}
5370
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005371/* Test Osmux setup BSC<->MSC */
5372testcase TC_assignment_osmux_cn() runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005373 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5374 var MSC_ConnHdlr vc_conn;
5375
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005376 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5377 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5378 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiyb9bf00f2022-09-14 15:35:37 +07005379 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02005380 pars.use_osmux_cn := true;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005381
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02005382 g_osmux_enabled_cn := true;
5383 f_init(1, true);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005384 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005385 f_vty_amr_start_mode_set(false, "1");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005386
5387 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5388 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005389
5390 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01005391 f_shutdown_helper();
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005392}
5393
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005394/* Test Osmux setup BTS<->BSC */
5395testcase TC_assignment_osmux_bts() runs on test_CT {
5396 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5397 var MSC_ConnHdlr vc_conn;
5398
5399 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5400 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5401 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005402 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005403 pars.use_osmux_bts := true;
5404
5405 g_osmux_enabled_bts := true;
5406 f_init(1, true);
5407 f_sleep(1.0);
5408 f_vty_amr_start_mode_set(false, "1");
5409
5410 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5411 vc_conn.done;
5412
5413 f_vty_amr_start_mode_restore(false);
5414 f_shutdown_helper();
5415}
5416
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +02005417/* Test non-AMR codecs still work fine as RTP when Osmux is enabled BTS<->BSC<->MSC */
5418testcase TC_assignment_codec_hr_osmux_on() runs on test_CT {
5419 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5420 var MSC_ConnHdlr vc_conn;
5421
5422 g_osmux_enabled_cn := true;
5423 g_osmux_enabled_bts := true;
5424 f_init(1, true);
5425 f_sleep(1.0);
5426 f_ctrs_bsc_and_bts_assignment_init(1);
5427
5428 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5429 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5430 vc_conn.done;
5431
5432 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
5433 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
5434 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
5435 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
5436 f_ctrs_bts_verify();
5437
5438 f_shutdown_helper();
5439}
5440
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005441/* Test Osmux setup BTS<->BSC<->MSC */
5442testcase TC_assignment_osmux() runs on test_CT {
5443 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5444 var MSC_ConnHdlr vc_conn;
5445
5446 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5447 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5448 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005449 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005450 pars.use_osmux_cn := true;
5451 pars.use_osmux_bts := true;
5452
5453 g_osmux_enabled_cn := true;
5454 g_osmux_enabled_bts := true;
5455 f_init(1, true);
5456 f_sleep(1.0);
5457 f_vty_amr_start_mode_set(false, "1");
5458
5459 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5460 vc_conn.done;
5461
5462 f_vty_amr_start_mode_restore(false);
5463 f_shutdown_helper();
5464}
5465
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005466/* test the procedure of the MSC requesting a Classmark Update:
5467 * a) BSSMAP Classmark Request should result in RR CLASSMARK ENQUIRY,
5468 * b) L3 RR CLASSMARK CHANGE should result in BSSMAP CLASSMARK UPDATE */
Harald Welte898113b2018-01-31 18:32:21 +01005469private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005470 g_pars := f_gen_test_hdlr_pars();
5471
Harald Weltea0630032018-03-20 21:09:55 +01005472 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005473 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005474
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005475 BSSAP.send(ts_BSSMAP_ClassmarkRequest);
5476 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
5477
Harald Welte898113b2018-01-31 18:32:21 +01005478 f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
5479 BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
5480 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005481
5482 f_perform_clear();
Harald Welte898113b2018-01-31 18:32:21 +01005483}
5484testcase TC_classmark() runs on test_CT {
5485 var MSC_ConnHdlr vc_conn;
5486 f_init(1, true);
5487 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005488 vc_conn := f_start_handler(refers(f_tc_classmark));
Harald Welte898113b2018-01-31 18:32:21 +01005489 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005490 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005491}
5492
Harald Welteeddf0e92020-06-21 19:42:15 +02005493/* Send a CommonID from the simulated MSC and verify that the information is used to
5494 * fill BSC-internal data structures (specifically, bsc_subscr associated with subscr_conn) */
5495private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
5496 g_pars := f_gen_test_hdlr_pars();
5497 f_MscConnHdlr_init_vty();
5498
5499 f_create_chan_and_exp();
5500 /* we should now have a COMPL_L3 at the MSC */
Harald Welteeddf0e92020-06-21 19:42:15 +02005501
5502 /* Send CommonID */
5503 BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
5504
5505 /* Use VTY to verify that the IMSI of the subscr_conn is set */
5506 var charstring regex := "*(IMSI: " & hex2str(g_pars.imsi) & ")*";
5507 f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
5508
5509 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005510
5511 f_perform_clear();
Harald Welteeddf0e92020-06-21 19:42:15 +02005512}
5513testcase TC_common_id() runs on test_CT {
5514 var MSC_ConnHdlr vc_conn;
5515 f_init(1, true);
5516 f_sleep(1.0);
5517 vc_conn := f_start_handler(refers(f_tc_common_id));
5518 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005519 f_shutdown_helper();
Harald Welteeddf0e92020-06-21 19:42:15 +02005520}
5521
Harald Weltee3bd6582018-01-31 22:51:25 +01005522private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005523 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005524 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005525 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005526
Harald Weltee3bd6582018-01-31 22:51:25 +01005527 /* send the single message we want to send */
5528 f_rsl_send_l3(l3);
5529}
5530
5531private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr {
5532 timer T := sec;
5533 var PDU_BSSAP bssap;
Harald Welte898113b2018-01-31 18:32:21 +01005534 T.start;
5535 alt {
Harald Weltee3bd6582018-01-31 22:51:25 +01005536 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap {
5537 setverdict(fail, "Unexpected BSSMAP ", bssap);
Daniel Willmannafce8662018-07-06 23:11:32 +02005538 mtc.stop;
Harald Welte898113b2018-01-31 18:32:21 +01005539 }
5540 [] T.timeout {
5541 setverdict(pass);
5542 }
5543 }
5544}
5545
Harald Weltee3bd6582018-01-31 22:51:25 +01005546/* unsolicited ASSIGNMENT FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5547private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
5548 f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
5549 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005550 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005551}
Harald Welte898113b2018-01-31 18:32:21 +01005552testcase TC_unsol_ass_fail() runs on test_CT {
5553 var MSC_ConnHdlr vc_conn;
5554 f_init(1, true);
5555 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005556 vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
Harald Welte898113b2018-01-31 18:32:21 +01005557 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005558 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005559}
Harald Welte552620d2017-12-16 23:21:36 +01005560
Harald Welteea99a002018-01-31 20:46:43 +01005561
5562/* unsolicited ASSIGNMENT COMPLETE (without ASSIGN) from MS shouldn't bring BSC down */
5563private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005564 f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
5565 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005566 f_perform_clear();
Harald Welteea99a002018-01-31 20:46:43 +01005567}
5568testcase TC_unsol_ass_compl() runs on test_CT {
5569 var MSC_ConnHdlr vc_conn;
5570 f_init(1, true);
5571 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005572 vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
Harald Welteea99a002018-01-31 20:46:43 +01005573 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005574 f_shutdown_helper();
Harald Welteea99a002018-01-31 20:46:43 +01005575}
5576
5577
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005578/* unsolicited HANDOVER FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5579private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005580 f_est_single_l3(ts_RRM_HandoverFailure('00'O));
5581 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005582 f_perform_clear();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005583}
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005584testcase TC_unsol_ho_fail() runs on test_CT {
5585 var MSC_ConnHdlr vc_conn;
5586 f_init(1, true);
5587 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005588 vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005589 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005590 f_shutdown_helper();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005591}
5592
5593
Harald Weltee3bd6582018-01-31 22:51:25 +01005594/* short message from MS should be ignored */
5595private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005596 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005597 f_create_chan_and_exp();
Harald Weltee3bd6582018-01-31 22:51:25 +01005598 /* we should now have a COMPL_L3 at the MSC */
Harald Weltee3bd6582018-01-31 22:51:25 +01005599
5600 /* send short message */
5601 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
5602 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005603 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005604}
5605testcase TC_err_82_short_msg() runs on test_CT {
5606 var MSC_ConnHdlr vc_conn;
5607 f_init(1, true);
5608 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005609 vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
Harald Weltee3bd6582018-01-31 22:51:25 +01005610 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005611 f_shutdown_helper();
Harald Weltee3bd6582018-01-31 22:51:25 +01005612}
5613
5614
Harald Weltee9e02e42018-01-31 23:36:25 +01005615/* 24.008 8.4 Unknown message must trigger RR STATUS */
5616private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
5617 f_est_single_l3(ts_RRM_UL_REL('00'O));
5618 timer T := 3.0
5619 alt {
5620 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
5621 setverdict(pass);
5622 }
5623 [] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
Harald Welte458fd372018-03-21 11:26:23 +01005624 [] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
Harald Weltee9e02e42018-01-31 23:36:25 +01005625 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005626 f_perform_clear();
Harald Weltee9e02e42018-01-31 23:36:25 +01005627}
5628testcase TC_err_84_unknown_msg() runs on test_CT {
5629 var MSC_ConnHdlr vc_conn;
5630 f_init(1, true);
5631 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005632 vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
Harald Weltee9e02e42018-01-31 23:36:25 +01005633 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005634 f_shutdown_helper();
Harald Weltee9e02e42018-01-31 23:36:25 +01005635}
5636
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005637/***********************************************************************
5638 * Handover
5639 ***********************************************************************/
5640
Harald Welte94e0c342018-04-07 11:33:23 +02005641/* execute a "bts <0-255> trx <0-255> timeslot <0-7> " command on given Dchan */
5642private function f_vty_ts_action(charstring suffix, integer bts_nr, integer trx_nr, integer ts_nr)
5643runs on test_CT {
5644 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5645 " timeslot "&int2str(ts_nr)&" ";
5646 f_vty_transceive(BSCVTY, cmd & suffix);
5647}
5648
Harald Welte261af4b2018-02-12 21:20:39 +01005649/* execute a "bts <0-255> trx <0-255> timeslot <0-7> sub-slot <0-7>" command on given Dchan */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005650private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
5651 uint8_t bts_nr, uint8_t trx_nr,
5652 in RslChannelNr chan_nr)
5653{
Harald Welte261af4b2018-02-12 21:20:39 +01005654 /* FIXME: resolve those from component-global state */
5655 var integer ts_nr := chan_nr.tn;
5656 var integer ss_nr;
5657 if (ischosen(chan_nr.u.ch0)) {
5658 ss_nr := 0;
5659 } else if (ischosen(chan_nr.u.lm)) {
5660 ss_nr := chan_nr.u.lm.sub_chan;
5661 } else if (ischosen(chan_nr.u.sdcch4)) {
5662 ss_nr := chan_nr.u.sdcch4.sub_chan;
5663 } else if (ischosen(chan_nr.u.sdcch8)) {
5664 ss_nr := chan_nr.u.sdcch8.sub_chan;
5665 } else {
5666 setverdict(fail, "Invalid ChanNr ", chan_nr);
Daniel Willmannafce8662018-07-06 23:11:32 +02005667 mtc.stop;
Harald Welte261af4b2018-02-12 21:20:39 +01005668 }
5669
5670 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5671 " timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005672 f_vty_transceive(pt, cmd & suffix);
Harald Welte261af4b2018-02-12 21:20:39 +01005673}
5674
Neels Hofmeyr91401012019-07-11 00:42:35 +02005675/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
5676 * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor
5677 * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
5678 * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
5679 * pair, not really to a specific BTS number. */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005680private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
5681 in RslChannelNr chan_nr, uint8_t new_bts_nr)
5682{
5683 f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
Harald Welte261af4b2018-02-12 21:20:39 +01005684}
5685
5686/* intra-BSC hand-over between BTS0 and BTS1 */
5687private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02005688 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5689 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte261af4b2018-02-12 21:20:39 +01005690
5691 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5692 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5693
Harald Weltea0630032018-03-20 21:09:55 +01005694 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005695 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Harald Welte261af4b2018-02-12 21:20:39 +01005696
5697 var HandoverState hs := {
5698 rr_ho_cmpl_seen := false,
5699 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005700 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005701 expect_target_tsc := c_BtsParams[1].tsc
Harald Welte261af4b2018-02-12 21:20:39 +01005702 };
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005703 /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005704 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
Harald Welte261af4b2018-02-12 21:20:39 +01005705 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5706 f_rslem_suspend(RSL1_PROC);
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005707
5708 /* From the MGW perspective, a handover is is characterized by
5709 * performing one MDCX operation with the MGW. So we expect to see
5710 * one more MDCX during handover. */
5711 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5712
Harald Welte261af4b2018-02-12 21:20:39 +01005713 alt {
5714 [] as_handover(hs);
Harald Welte261af4b2018-02-12 21:20:39 +01005715 }
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005716
Philipp Maier4dae0652018-11-12 12:03:26 +01005717 /* Since this is an internal handover we expect the BSC to inform the
5718 * MSC about the event */
5719 BSSAP.receive(tr_BSSMAP_HandoverPerformed);
5720
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005721 /* Check the amount of MGCP transactions is still consistant with the
5722 * test expectation */
5723 f_check_mgcp_expectations()
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005724
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005725 var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
5726
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005727 /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
5728 * g_chan_nr to the new lchan that was handed over to. It lives in bts 1, so look it up at RSL1_PROC. */
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005729 f_verify_encr_info(chan_act);
5730
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005731 f_chan_act_verify_tsc(chan_act, c_BtsParams[1].tsc);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005732
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005733 f_perform_clear(RSL1, RSL1_PROC);
5734
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005735 f_sleep(0.5);
Harald Welte261af4b2018-02-12 21:20:39 +01005736}
5737
5738testcase TC_ho_int() runs on test_CT {
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005739 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte261af4b2018-02-12 21:20:39 +01005740 var MSC_ConnHdlr vc_conn;
5741 f_init(2, true);
5742 f_sleep(1.0);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005743
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005744 pars.expect_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005745
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005746 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005747
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005748 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
Harald Welte261af4b2018-02-12 21:20:39 +01005749 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005750
5751 /* from f_establish_fully() */
5752 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5753 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5754 /* from handover */
5755 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5756 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5757 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5758 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005759 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5760 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005761 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005762 f_shutdown_helper(ho := true);
Harald Welte261af4b2018-02-12 21:20:39 +01005763}
Harald Weltee9e02e42018-01-31 23:36:25 +01005764
Oliver Smith7eabd312021-07-12 14:18:56 +02005765function f_tc_ho_int_a5(OCT1 encr_alg, charstring enc_a5 := "0 1 3") runs on test_CT {
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005766 var MSC_ConnHdlr vc_conn;
5767 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5768 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
5769
5770 f_init(2, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02005771 f_vty_encryption_a5(enc_a5);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005772 f_sleep(1.0);
5773
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005774 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005775
5776 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
5777 vc_conn.done;
5778
5779 /* from f_establish_fully() */
5780 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5781 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5782 /* from handover */
5783 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5784 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5785 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5786 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005787 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5788 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005789 f_ctrs_bsc_and_bts_verify();
Oliver Smith7eabd312021-07-12 14:18:56 +02005790 f_vty_encryption_a5_reset();
Oliver Smith39f53072022-10-27 14:44:04 +02005791 f_shutdown_helper(ho := true);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005792}
5793
5794testcase TC_ho_int_a5_0() runs on test_CT {
5795 f_tc_ho_int_a5('01'O);
5796}
5797
5798testcase TC_ho_int_a5_1() runs on test_CT {
5799 f_tc_ho_int_a5('02'O);
5800}
5801
5802testcase TC_ho_int_a5_3() runs on test_CT {
5803 f_tc_ho_int_a5('08'O);
5804}
5805
5806testcase TC_ho_int_a5_4() runs on test_CT {
Oliver Smith7eabd312021-07-12 14:18:56 +02005807 f_tc_ho_int_a5('10'O, "0 1 3 4");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005808}
5809
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005810/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
5811private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
5812 g_pars := f_gen_test_hdlr_pars();
5813 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5814 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005815
5816 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5817 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5818
5819 f_establish_fully(ass_cmd, exp_compl);
5820 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
5821
5822 var HandoverState hs := {
5823 rr_ho_cmpl_seen := false,
5824 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005825 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005826 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005827 };
5828 /* issue hand-over command on VTY */
5829 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
5830 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5831 f_rslem_suspend(RSL1_PROC);
5832
5833 /* From the MGW perspective, a handover is is characterized by
5834 * performing one MDCX operation with the MGW. So we expect to see
5835 * one more MDCX during handover. */
5836 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5837
5838 var RSL_Message rsl;
5839 var PDU_ML3_NW_MS l3;
5840 var RslChannelNr new_chan_nr;
5841 var GsmArfcn arfcn;
5842 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
5843 l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
5844 if (not ischosen(l3.msgs.rrm.handoverCommand)) {
5845 setverdict(fail, "Expected handoverCommand");
5846 mtc.stop;
5847 }
5848 }
5849 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
5850 new_chan_nr, arfcn);
5851
5852 f_rslem_register(0, new_chan_nr, RSL1_PROC);
5853
5854 /* resume processing of RSL DChan messages, which was temporarily suspended
5855 * before performing a hand-over */
5856 f_rslem_resume(RSL1_PROC);
5857 RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
5858
5859 f_sleep(1.0);
5860
5861 /* Handover fails because no HANDO DET appears on the new lchan,
5862 * and the old lchan reports a Radio Link Failure. */
5863 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
5864
5865 var PDU_BSSAP rx_clear_request;
5866 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5867 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5868 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5869
5870 var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
5871
5872 var MgcpCommand mgcp;
5873 interleave {
5874 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
5875 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005876 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005877 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005878 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005879 }
5880 [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005881 [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005882 RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005883 f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005884 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005885 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5886 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5887 }
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005888 }
5889
5890 f_sleep(0.5);
5891 setverdict(pass);
5892}
5893testcase TC_ho_int_radio_link_failure() runs on test_CT {
5894 var MSC_ConnHdlr vc_conn;
5895 f_init(2, true);
5896 f_sleep(1.0);
5897
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005898 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005899
5900 vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
5901 vc_conn.done;
5902
5903 /* from f_establish_fully() */
5904 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5905 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5906 /* from handover */
5907 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5908 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
5909 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5910 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005911 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5912 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005913 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005914 f_shutdown_helper(ho := true);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005915}
5916
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005917/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005918private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005919 var MgcpCommand mgcp;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005920 var template MgcpResponse mgcp_resp;
5921 var MGCP_RecvFrom mrf;
5922 var template MgcpMessage msg_resp;
5923 var template MgcpMessage msg_dlcx := {
5924 command := tr_DLCX()
5925 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005926
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005927 if (g_pars.aoip) {
5928 MGCP.receive(tr_DLCX()) -> value mgcp {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005929 log("Got first DLCX: ", mgcp);
5930 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005931 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005932
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005933 MGCP.receive(tr_DLCX()) -> value mgcp {
5934 log("Got second DLCX: ", mgcp);
5935 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
5936 };
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005937 } else {
5938 /* For SCCPLite, BSC doesn't handle the MSC-side */
5939 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
5940 log("Got first DLCX: ", mrf.msg.command);
5941 msg_resp := {
5942 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
5943 }
5944 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
5945 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005946 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005947}
5948
Oliver Smithc9a5f532022-10-21 11:32:23 +02005949private function f_ho_out_of_this_bsc(template (omit) BSSMAP_oldToNewBSSIEs exp_oldToNewBSSIEs := omit,
5950 boolean skip_meas_rep := false) runs on MSC_ConnHdlr {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005951
Oliver Smithc9a5f532022-10-21 11:32:23 +02005952 if (not skip_meas_rep) {
5953 var NcellReports neighbor_rep := {
5954 { rxlev := 20, bcch_freq := 0, bsic := 11 }
5955 };
5956 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
5957 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
5958 l3_mr, 0));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005959
Oliver Smithc9a5f532022-10-21 11:32:23 +02005960 BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
5961 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005962
5963 f_sleep(0.5);
5964 /* The MSC negotiates Handover Request and Handover Request Ack with
5965 * the other BSS and comes back with a BSSMAP Handover Command
5966 * containing an RR Handover Command coming from the target BSS... */
5967
5968 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5969 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
5970 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5971 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
5972 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
5973
5974 /* expect the Handover Command to go out on RR */
5975 var RSL_Message rsl_ho_cmd
5976 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
5977 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
5978 var RSL_IE_Body rsl_ho_cmd_l3;
5979 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
5980 log("RSL message contains no L3 Info IE, expected RR Handover Command");
5981 setverdict(fail);
5982 } else {
5983 log("Found L3 Info: ", rsl_ho_cmd_l3);
5984 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
5985 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
5986 setverdict(fail);
5987 } else {
5988 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
5989 setverdict(pass);
5990 }
5991 }
5992
5993 /* When the other BSS has reported a completed handover, this side is
5994 * torn down. */
5995
5996 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_HANDOVER_SUCCESSFUL;
5997 var BssmapCause cause := enum2int(cause_val);
5998 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5999
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006000 f_expect_dlcx_conns();
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006001
6002 interleave {
6003 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
6004 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
6005 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006006 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
6007 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
6008 }
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006009 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006010 setverdict(pass);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006011}
6012
6013private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
6014 g_pars := f_gen_test_hdlr_pars();
6015 var PDU_BSSAP ass_req := f_gen_ass_req();
6016 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6017 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6018 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6019 f_establish_fully(ass_req, exp_compl);
6020
6021 f_ho_out_of_this_bsc();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006022}
6023testcase TC_ho_out_of_this_bsc() runs on test_CT {
6024 var MSC_ConnHdlr vc_conn;
6025
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006026 f_init_vty();
6027 f_bts_0_cfg(BSCVTY,
6028 {"neighbor-list mode automatic",
6029 "handover 1",
6030 "handover algorithm 2",
6031 "handover2 window rxlev averaging 1",
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006032 "no neighbors",
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006033 "neighbor lac 99 arfcn 123 bsic any"});
6034 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6035
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006036 f_init(1, true);
6037 f_sleep(1.0);
6038
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006039 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006040
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006041 vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
6042 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006043
6044 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6045 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6046 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6047 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6048 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6049 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
6050 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006051 f_shutdown_helper(ho := true);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006052}
6053
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006054private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6055 template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
Vadim Yanitskiy2ef6a2f2020-10-08 23:17:32 +07006056 template (present) OCT1 dlci := ?,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006057 octetstring l3 := '0123456789'O)
6058runs on MSC_ConnHdlr {
Neels Hofmeyr43654812020-09-25 01:35:35 +02006059 /* The old lchan and conn should still be active. See that arbitrary L3
6060 * is still going through. */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006061 rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
Neels Hofmeyr43654812020-09-25 01:35:35 +02006062 var template PDU_BSSAP exp_data := {
6063 discriminator := '1'B,
6064 spare := '0000000'B,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006065 dlci := dlci,
6066 lengthIndicator := lengthof(l3),
Neels Hofmeyr43654812020-09-25 01:35:35 +02006067 pdu := {
6068 dtap := l3
6069 }
6070 };
6071 BSSAP.receive(exp_data);
6072 setverdict(pass);
6073}
6074
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006075private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6076 template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006077 template (value) OCT1 dlci := '00'O,
6078 octetstring l3 := '0123456789'O)
6079runs on MSC_ConnHdlr {
6080 BSSAP.send(PDU_BSSAP:{
6081 discriminator := '1'B,
6082 spare := '0000000'B,
6083 dlci := dlci,
6084 lengthIndicator := lengthof(l3),
6085 pdu := {
6086 dtap := l3
6087 }
6088 });
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006089 rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006090 setverdict(pass);
6091}
6092
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006093/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
6094 * simply never sends a BSSMAP Handover Command. */
6095private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006096 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006097
6098 var PDU_BSSAP ass_req := f_gen_ass_req();
6099 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6100 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6101 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6102 f_establish_fully(ass_req, exp_compl);
6103
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006104 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006105 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6106
6107 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6108
6109 /* osmo-bsc should time out 10 seconds after the handover started.
6110 * Let's give it a bit extra. */
6111 f_sleep(15.0);
6112
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006113 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006114 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006115 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006116}
6117testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
6118 var MSC_ConnHdlr vc_conn;
6119
6120 f_init(1, true);
6121 f_sleep(1.0);
6122
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006123 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006124
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006125 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
6126 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006127
6128 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6129 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6130 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6131 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6132 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6133 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6134 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006135 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006136}
6137
6138/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
6139 * RR Handover Failure. */
6140private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006141 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006142
6143 var PDU_BSSAP ass_req := f_gen_ass_req();
6144 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6145 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6146 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6147 f_establish_fully(ass_req, exp_compl);
6148
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006149 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006150 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6151
6152 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6153
6154 f_sleep(0.5);
6155 /* The MSC negotiates Handover Request and Handover Request Ack with
6156 * the other BSS and comes back with a BSSMAP Handover Command
6157 * containing an RR Handover Command coming from the target BSS... */
6158
6159 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6160 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6161 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6162 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6163 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6164
6165 /* expect the Handover Command to go out on RR */
6166 var RSL_Message rsl_ho_cmd
6167 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6168 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6169 var RSL_IE_Body rsl_ho_cmd_l3;
6170 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6171 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6172 setverdict(fail);
6173 } else {
6174 log("Found L3 Info: ", rsl_ho_cmd_l3);
6175 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6176 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6177 setverdict(fail);
6178 } else {
6179 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6180 setverdict(pass);
6181 }
6182 }
6183
6184 f_sleep(0.2);
6185 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
6186
6187 /* Should tell the MSC about the failure */
6188 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6189
6190 f_sleep(1.0);
6191
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006192 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006193 f_sleep(1.0);
6194
6195 setverdict(pass);
6196 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006197 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006198}
6199testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
6200 var MSC_ConnHdlr vc_conn;
6201
6202 f_init(1, true);
6203 f_sleep(1.0);
6204
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006205 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006206
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006207 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
6208 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006209
6210 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6211 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6212 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6213 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6214 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6215 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
6216 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006217 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006218}
6219
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006220/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
6221 * (neither BSSMAP Clear Command for success nor RR Handover Failure). 48.008 3.1.5.3.3 "Abnormal Conditions" applies
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006222 * and the lchan is released. */
6223private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006224 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006225
6226 var PDU_BSSAP ass_req := f_gen_ass_req();
6227 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6228 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6229 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6230 f_establish_fully(ass_req, exp_compl);
6231
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006232 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006233 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6234
6235 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6236
6237 f_sleep(0.5);
6238 /* The MSC negotiates Handover Request and Handover Request Ack with
6239 * the other BSS and comes back with a BSSMAP Handover Command
6240 * containing an RR Handover Command coming from the target BSS... */
6241
6242 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6243 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6244 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6245 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6246 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6247
6248 /* expect the Handover Command to go out on RR */
6249 var RSL_Message rsl_ho_cmd
6250 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6251 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6252 var RSL_IE_Body rsl_ho_cmd_l3;
6253 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6254 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6255 setverdict(fail);
6256 } else {
6257 log("Found L3 Info: ", rsl_ho_cmd_l3);
6258 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6259 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6260 setverdict(fail);
6261 } else {
6262 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6263 setverdict(pass);
6264 }
6265 }
6266
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006267 /* We get neither success nor failure report from the remote BSS. Eventually T8 times out and we run into 3GPP
6268 * TS 48.008 3.1.5.3.3 "Abnormal Conditions": Clear Request should go to the MSC, and RR should be released
6269 * after Clear Command */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006270
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006271 var PDU_BSSAP rx_clear_request;
Neels Hofmeyre1797aa2019-07-09 19:34:04 +02006272 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
6273 log("Got BSSMAP Clear Request");
6274 /* Instruct BSC to clear channel */
6275 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6276 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6277
6278 var MgcpCommand mgcp;
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006279 interleave {
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01006280 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
6281 log("Got Deact SACCH");
6282 }
Harald Welte924b6ea2019-02-04 01:05:34 +01006283 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
Neels Hofmeyr211169d2018-11-07 00:37:29 +01006284 log("Got RR Release");
6285 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02006286 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006287 log("Got RF Chan Rel");
6288 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02006289 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006290 }
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006291 }
6292
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006293 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006294 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006295 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006296
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006297 setverdict(pass);
6298 f_sleep(1.0);
6299}
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006300testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006301 var MSC_ConnHdlr vc_conn;
6302
6303 f_init(1, true);
6304 f_sleep(1.0);
6305
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006306 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006307
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006308 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006309 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006310
6311 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6312 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6313 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6314 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6315 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6316 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6317 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006318 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006319}
6320
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006321private function f_ho_into_this_bsc(charstring id, template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit) runs on MSC_ConnHdlr {
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006322 var PDU_BSSAP rx_bssap;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006323 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6324 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6325 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6326 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6327 * before we get started. */
6328 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6329 f_rslem_register(0, new_chan_nr);
6330 g_chan_nr := new_chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06006331 var uint3_t expect_target_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006332 f_sleep(1.0);
6333
6334 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6335 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006336 var default as_media := activate(as_Media());
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006337
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01006338 var PDU_BSSAP ho_req := f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
6339 cell_id_source := g_pars.cell_id_source,
6340 oldToNewBSSIEs := oldToNewBSSIEs,
6341 enc := g_pars.encr);
6342 if (g_pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr) {
6343 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, ho_req));
6344 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6345 } else {
6346 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, omit));
6347 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6348 BSSAP.send(ho_req);
6349 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006350
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006351 alt {
6352 [] BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap {
6353 if (g_pars.expect_ho_fail) {
6354 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6355 "Expected Handover Request to fail, but got Handover Request Ack")
6356 }
6357 }
6358 [] BSSAP.receive(tr_BSSMAP_HandoverFailure) -> value rx_bssap {
6359 if (not g_pars.expect_ho_fail) {
6360 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6361 "Expected Handover Request to succeed, but got Handover Failure")
6362 }
6363 // TODO: evaluate correct cause value. But osmo-bsc doesn't seem to send meaningful causes yet!
6364 // For now just accept any cause.
6365 BSSAP.receive(tr_BSSMAP_ClearRequest);
6366 setverdict(pass);
6367 return;
6368 }
6369 }
6370
Oliver Smith7a8594a2023-02-13 14:30:49 +01006371 if (g_pars.expect_ho_fail_lchan_est) {
6372 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6373 setverdict(pass);
Oliver Smitha1cbec52023-02-21 12:44:12 +01006374
6375 /* When we let MGCP MDCX run into a timeout, it's still in the
6376 * queue and additionally after BSSAP HandoverFailure, two DLCX
6377 * get sent. */
6378 if (g_pars.ignore_mgw_mdcx) {
6379 MGCP.receive(tr_MDCX);
6380 MGCP.receive(tr_DLCX);
6381 MGCP.receive(tr_DLCX);
6382 }
Oliver Smith7a8594a2023-02-13 14:30:49 +01006383 return;
6384 }
6385
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006386 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6387
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006388 /* we're sure that the channel activation is done now, verify the parameters in it */
6389 var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
6390 f_verify_encr_info(chan_act);
6391 f_chan_act_verify_tsc(chan_act, expect_target_tsc);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006392
Neels Hofmeyr46e16e52022-02-23 17:04:00 +01006393 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.codecList)) {
6394 if (not g_pars.aoip) {
6395 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6396 "handoverRequestAck: Expected no Speech Codec List (BSS Supported), because this is not AoIP");
6397 }
6398 /* TODO: check actual codecs? */
6399 } else {
6400 if (g_pars.aoip) {
6401 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6402 "handoverRequestAck: Expected Speech Codec List (BSS Supported), but none found");
6403 }
6404 }
6405
6406 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.speechCodec)) {
6407 if (not g_pars.aoip) {
6408 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6409 "handoverRequestAck: Expected no Speech Codec (Chosen), because this is not AoIP");
6410 }
6411 /* TODO: check actual codec? */
6412 } else {
6413 if (g_pars.aoip) {
6414 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6415 "handoverRequestAck: Expected Speech Codec (Chosen), but none found");
6416 }
6417 }
6418
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006419 var octetstring ho_command_str;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006420 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6421 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6422 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6423 log("L3 Info in HO Request Ack is ", ho_command);
6424
6425 var GsmArfcn arfcn;
6426 var RslChannelNr actual_new_chan_nr;
6427 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6428 actual_new_chan_nr, arfcn);
6429
6430 if (actual_new_chan_nr != new_chan_nr) {
6431 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6432 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6433 setverdict(fail);
6434 return;
6435 }
6436 log("Handover Command chan_nr is", actual_new_chan_nr);
6437
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006438 var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
6439 if (not match(got_tsc, expect_target_tsc)) {
6440 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6441 expect_target_tsc, " got ", got_tsc);
6442 mtc.stop;
6443 } else {
6444 log("handoverCommand: verified TSC = ", got_tsc);
6445 }
6446
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006447 /* Check the Cipher Mode Setting IE (shall be present during inter-RAT handover) */
6448 if (ispresent(ho_command.msgs.rrm.handoverCommand.cipherModeSetting)) {
6449 var CipherModeSetting_TV cms := ho_command.msgs.rrm.handoverCommand.cipherModeSetting;
6450 var template (present) CipherModeSetting_TV tr_cms := {
6451 sC := '0'B, /* no ciphering by default */
6452 algorithmIdentifier := '000'B,
6453 elementIdentifier := ?
6454 };
6455 if (ispresent(g_pars.encr) and g_pars.encr.enc_alg_expect != '01'O) { /* A5/N */
6456 tr_cms.algorithmIdentifier := f_cipher_mode_bssmap_to_rr(g_pars.encr.enc_alg_expect);
6457 tr_cms.sC := '1'B;
6458 }
6459 if (not match(cms, tr_cms)) {
6460 setverdict(fail, "RR Handover Command: unexpected Cipher Mode Setting IE: ",
6461 cms, ", expected: ", tr_cms);
6462 }
6463 } else {
6464 setverdict(fail, "RR Handover Command: Cipher Mode Setting IE is not present");
6465 }
6466
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006467 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6468 * tells the MS to handover to the new lchan. Here comes the new MS on
6469 * the new lchan with a Handover RACH: */
6470
6471 /* send handover detect */
6472
6473 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6474
6475 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6476
6477 /* send handover complete over the new channel */
6478
6479 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_HandoverComplete('00'O));
6480 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
6481 enc_PDU_ML3_MS_NW(l3_tx)));
6482
6483 BSSAP.receive(tr_BSSMAP_HandoverComplete);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006484 deactivate(as_media);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006485 setverdict(pass);
6486}
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006487
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006488private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006489 var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006490 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
6491 if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
6492 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006493 }
6494 if (g_pars.exp_fast_return) {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006495 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006496 } else {
6497 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006498 }
6499 f_ho_into_this_bsc(id, oldToNewBSSIEs);
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006500 if (g_pars.expect_ho_fail) {
6501 f_perform_clear_no_lchan();
Oliver Smith7a8594a2023-02-13 14:30:49 +01006502 } else if (g_pars.expect_ho_fail_lchan_est) {
6503 BSSAP.receive(tr_BSSMAP_ClearRequest);
6504 f_perform_clear_no_lchan();
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006505 } else {
6506 f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
6507 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006508 setverdict(pass);
6509}
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006510function 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 +01006511 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006512
6513 f_init(1, true);
6514 f_sleep(1.0);
6515
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006516 f_vty_encryption_a5(vty_a5_cfg);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006517 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006518
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006519 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6520 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006521
6522 vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
6523 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006524
6525 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006526 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006527 if (pars.expect_ho_fail) {
6528 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6529 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:failed");
Oliver Smith7a8594a2023-02-13 14:30:49 +01006530 } else if (pars.expect_ho_fail_lchan_est) {
6531 f_ctrs_bsc_and_bts_add(0, "handover:error");
6532 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006533 } else {
6534 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6535 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
6536 }
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006537 f_ctrs_bsc_and_bts_verify();
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006538
6539 f_vty_encryption_a5_reset();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006540}
6541
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006542testcase TC_ho_into_this_bsc() runs on test_CT {
6543 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6544 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006545 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006546}
6547
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006548function f_tc_ho_into_this_bsc_a5(TestHdlrEncrParams encr, charstring vty_a5_cfg := VTY_A5_DEFAULT,
6549 boolean expect_fail := false) runs on test_CT {
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006550 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006551 pars.encr := encr;
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006552 pars.expect_ho_fail := expect_fail;
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006553 f_tc_ho_into_this_bsc_main(pars, vty_a5_cfg);
Oliver Smith39f53072022-10-27 14:44:04 +02006554 f_shutdown_helper(ho := true);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006555}
6556
6557testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006558 f_tc_ho_into_this_bsc_a5(f_encr_params('01'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006559}
6560
6561testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006562 f_tc_ho_into_this_bsc_a5(f_encr_params('02'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006563}
6564
6565testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006566 f_tc_ho_into_this_bsc_a5(f_encr_params('08'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006567}
6568
6569testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006570 f_tc_ho_into_this_bsc_a5(f_encr_params('10'O, kc128 := true), "3 4");
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006571}
6572
Neels Hofmeyr1951be22022-02-16 16:21:07 +01006573/* Report: in inter-BSC incoming handover, when the MSC omits the Chosen Encryption Algorithm IE in the Handover Request
6574 * message, then osmo-bsc starts an unencrypted lchan even if A5/0 is not permitted.
6575 *
6576 * This test verifies that the Encryption Information is present in the Channel Activation when the Chosen Enc Alg is
6577 * omitted.
6578 *
6579 * Related: SYS#5839
6580 */
6581testcase TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() runs on test_CT {
6582 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O, alg_chosen := omit));
6583}
6584
6585testcase TC_ho_into_this_bsc_a5_1_3() runs on test_CT {
6586 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O));
6587}
6588
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006589/* Send a permitted algo mask that does not intersect with osmo-bsc.cfg */
6590testcase TC_ho_into_this_bsc_a5_mismatch() runs on test_CT {
6591 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '18'O, alg_expect := '10'O), "0 1",
6592 expect_fail := true); // 0x18 = A5/3 and A5/4
6593}
6594
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006595testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
6596 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6597 pars.host_aoip_tla := "::6";
6598 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006599 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006600}
6601
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006602/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006603 to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006604 channel is later released (RR CHannel Release), should trigger inclusion of
6605 IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
6606 neighbors. */
6607testcase TC_srvcc_eutran_to_geran() runs on test_CT {
6608 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6609 pars.last_used_eutran_plmn := '323454'O;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006610 pars.exp_fast_return := true;
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006611 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006612
6613 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6614 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6615 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006616 f_shutdown_helper(ho := true);
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006617}
6618
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006619/* Same as TC_srvcc_eutran_to_geran, but enables ciphering on the target channel. */
6620testcase TC_srvcc_eutran_to_geran_a5_3() runs on test_CT {
6621 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6622 pars.encr := f_encr_params('08'O); /* only A5/3 */
6623 pars.last_used_eutran_plmn := '323454'O;
6624 pars.exp_fast_return := true;
6625 f_tc_ho_into_this_bsc_main(pars);
6626
6627 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6628 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6629 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006630 f_shutdown_helper(ho := true);
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006631}
6632
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006633/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
6634 on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
6635 list when the channel is released. */
6636testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
6637 f_init_vty();
6638 f_vty_allow_srvcc_fast_return(true, 0)
6639
6640 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6641 pars.last_used_eutran_plmn := '323454'O;
6642 pars.exp_fast_return := false;
6643 f_tc_ho_into_this_bsc_main(pars);
6644 f_vty_allow_srvcc_fast_return(false, 0);
6645 f_shutdown_helper();
6646}
6647
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01006648/* Same as TC_srvcc_eutran_to_geran, but using SAI as serving Cell Identifier. SYS#5838 */
6649testcase TC_srvcc_eutran_to_geran_src_sai() runs on test_CT {
6650 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6651 pars.last_used_eutran_plmn := '323454'O;
6652 pars.cell_id_source := valueof(ts_CellID_SAI('123456'O, 300, 444));
6653 f_tc_ho_into_this_bsc_main(pars);
6654
6655 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6656 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6657 f_ctrs_bsc_and_bts_verify();
6658 f_shutdown_helper();
6659}
6660
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006661private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
6662 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
6663 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
6664 f_ho_into_this_bsc(id, oldToNewBSSIEs);
6665 f_ho_out_of_this_bsc(oldToNewBSSIEs);
6666 setverdict(pass);
6667}
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006668
6669private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
6670 runs on test_CT {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006671 var MSC_ConnHdlr vc_conn;
6672 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6673
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006674 f_init_vty();
6675 f_bts_0_cfg(BSCVTY,
6676 {"neighbor-list mode automatic",
6677 "handover 1",
6678 "handover algorithm 2",
6679 "handover2 window rxlev averaging 1",
6680 "no neighbors",
6681 "neighbor lac 99 arfcn 123 bsic any"});
6682 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6683
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006684 f_init(1, true);
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006685 if (disable_fast_return) {
6686 f_vty_allow_srvcc_fast_return(true, 0);
6687 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006688 f_sleep(1.0);
6689
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006690 f_ctrs_bsc_and_bts_handover_init();
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006691
6692 pars.last_used_eutran_plmn := '323454'O;
6693 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6694 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
6695
6696 vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
6697 vc_conn.done;
6698
6699 f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
6700 f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
6701 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
6702 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
6703 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
6704 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006705
6706 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
6707 f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006708 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006709
6710 if (disable_fast_return) {
6711 f_vty_allow_srvcc_fast_return(false, 0);
6712 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006713 f_shutdown_helper();
6714}
6715
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006716/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
6717 BSS Information" IE with "Last Used E-UTRAN PLMN Id".
6718 Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
6719 IE with "Last Used E-UTRAN PLMN Id" from first step. */
6720testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
6721 f_tc_srvcc_eutran_to_geran_ho_out_main(false);
6722}
6723/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
6724 * independently of fast-reture allowed/forbidden in local BTS */
6725testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
6726 f_tc_srvcc_eutran_to_geran_ho_out_main(true);
6727}
6728
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006729private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
6730 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6731 f_rslem_register(0, new_chan_nr);
6732 g_chan_nr := new_chan_nr;
6733 f_sleep(1.0);
6734
6735 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6736 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6737 activate(as_Media());
6738
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006739 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006740 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006741 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006742
6743 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6744
6745 var PDU_BSSAP rx_bssap;
6746 var octetstring ho_command_str;
6747
6748 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6749
6750 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6751 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6752 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6753 log("L3 Info in HO Request Ack is ", ho_command);
6754
6755 var GsmArfcn arfcn;
6756 var RslChannelNr actual_new_chan_nr;
6757 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6758 actual_new_chan_nr, arfcn);
6759
6760 if (actual_new_chan_nr != new_chan_nr) {
6761 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6762 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6763 setverdict(fail);
6764 return;
6765 }
6766 log("Handover Command chan_nr is", actual_new_chan_nr);
6767
Neels Hofmeyr61ca08d2019-05-06 23:52:22 +02006768 /* For deterministic test results, give some time for the MGW endpoint to be configured */
6769 f_sleep(1.0);
6770
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006771 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6772 * tells the MS to handover to the new lchan. In this case, the MS
6773 * reports a Handover Failure to the old BSS, which forwards a BSSMAP
6774 * Handover Failure to the MSC. The procedure according to 3GPP TS
6775 * 48.008 3.1.5.3.2 "Handover Failure" is then that the MSC sends a
6776 * BSSMAP Clear Command: */
6777
6778 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6779 var BssmapCause cause := enum2int(cause_val);
6780 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6781
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006782 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006783 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006784 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006785
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006786 setverdict(pass);
6787 f_sleep(1.0);
6788
6789 setverdict(pass);
6790}
6791testcase TC_ho_in_fail_msc_clears() runs on test_CT {
6792 var MSC_ConnHdlr vc_conn;
6793 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6794
6795 f_init(1, true);
6796 f_sleep(1.0);
6797
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006798 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006799
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006800 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6801 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006802
6803 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
6804 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006805
6806 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6807 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6808 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6809 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6810 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006811 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006812}
6813
6814private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
6815 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6816 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6817 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6818 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6819 * before we get started. */
6820 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6821 f_rslem_register(0, new_chan_nr);
6822 g_chan_nr := new_chan_nr;
6823 f_sleep(1.0);
6824
6825 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6826 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6827 activate(as_Media());
6828
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006829 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006830 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006831 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006832
6833 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6834
6835 var PDU_BSSAP rx_bssap;
6836 var octetstring ho_command_str;
6837
6838 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6839
6840 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6841 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6842 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6843 log("L3 Info in HO Request Ack is ", ho_command);
6844
6845 var GsmArfcn arfcn;
6846 var RslChannelNr actual_new_chan_nr;
6847 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6848 actual_new_chan_nr, arfcn);
6849
6850 if (actual_new_chan_nr != new_chan_nr) {
6851 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6852 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6853 setverdict(fail);
6854 return;
6855 }
6856 log("Handover Command chan_nr is", actual_new_chan_nr);
6857
6858 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6859 * tells the MS to handover to the new lchan. Here comes the new MS on
6860 * the new lchan with a Handover RACH: */
6861
6862 /* send handover detect */
6863
6864 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6865
6866 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6867
6868 /* The MSC chooses to clear the connection now, maybe we got the
6869 * Handover RACH on the new cell but the MS still signaled Handover
6870 * Failure to the old BSS? */
6871
6872 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6873 var BssmapCause cause := enum2int(cause_val);
6874 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6875
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006876 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006877 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006878 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006879
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006880 f_sleep(1.0);
6881}
6882testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
6883 var MSC_ConnHdlr vc_conn;
6884 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6885
6886 f_init(1, true);
6887 f_sleep(1.0);
6888
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006889 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006890
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006891 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6892 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006893
6894 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
6895 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006896
6897 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6898 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6899 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6900 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6901 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006902 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006903}
6904
6905/* The new BSS's lchan times out before the MSC decides that handover failed. */
6906private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
6907 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6908 f_rslem_register(0, new_chan_nr);
6909 g_chan_nr := new_chan_nr;
6910 f_sleep(1.0);
6911
6912 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6913 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01006914 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006915
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006916 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006917 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006918 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006919
6920 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6921
6922 var PDU_BSSAP rx_bssap;
6923 var octetstring ho_command_str;
6924
6925 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6926
6927 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6928 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6929 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6930 log("L3 Info in HO Request Ack is ", ho_command);
6931
6932 var GsmArfcn arfcn;
6933 var RslChannelNr actual_new_chan_nr;
6934 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6935 actual_new_chan_nr, arfcn);
6936
6937 if (actual_new_chan_nr != new_chan_nr) {
6938 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6939 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6940 setverdict(fail);
6941 return;
6942 }
6943 log("Handover Command chan_nr is", actual_new_chan_nr);
6944
6945 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6946 * tells the MS to handover to the new lchan. But the MS never shows up
6947 * on the new lchan. */
6948
6949 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6950
6951 /* Did osmo-bsc also send a Clear Request? */
6952 timer T := 0.5;
6953 T.start;
6954 alt {
6955 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
6956 [] T.timeout { }
6957 }
6958
6959 /* MSC plays along with a Clear Command (no matter whether osmo-bsc
6960 * asked for it, this is a Handover Failure after all). */
6961
6962 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6963 var BssmapCause cause := enum2int(cause_val);
6964 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6965
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006966 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006967 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006968 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006969
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006970 f_sleep(1.0);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006971}
6972testcase TC_ho_in_fail_no_detect() runs on test_CT {
6973 var MSC_ConnHdlr vc_conn;
6974 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6975
6976 f_init(1, true);
6977 f_sleep(1.0);
6978
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006979 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006980
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006981 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6982 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006983
6984 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect), pars);
6985 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006986
6987 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6988 f_ctrs_bsc_and_bts_add(0, "handover:error");
6989 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6990 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
6991 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006992 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006993}
6994
6995/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
6996private function f_tc_ho_in_fail_no_detect2(charstring id) runs on MSC_ConnHdlr {
6997 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6998 f_rslem_register(0, new_chan_nr);
6999 g_chan_nr := new_chan_nr;
7000 f_sleep(1.0);
7001
7002 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
7003 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01007004 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007005
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007006 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007007 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02007008 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007009
7010 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
7011
7012 var PDU_BSSAP rx_bssap;
7013 var octetstring ho_command_str;
7014
7015 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
7016
7017 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
7018 log("Received L3 Info in HO Request Ack: ", ho_command_str);
7019 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
7020 log("L3 Info in HO Request Ack is ", ho_command);
7021
7022 var GsmArfcn arfcn;
7023 var RslChannelNr actual_new_chan_nr;
7024 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
7025 actual_new_chan_nr, arfcn);
7026
7027 if (actual_new_chan_nr != new_chan_nr) {
7028 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
7029 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
7030 setverdict(fail);
7031 return;
7032 }
7033 log("Handover Command chan_nr is", actual_new_chan_nr);
7034
7035 /* Now the MSC forwards the RR Handover Command to the other BSC, which
7036 * tells the MS to handover to the new lchan. But the MS never shows up
7037 * on the new lchan. */
7038
7039 BSSAP.receive(tr_BSSMAP_HandoverFailure);
7040
7041 /* MSC plays dumb and sends no Clear Command */
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007042 var PDU_BSSAP rx_clear_request;
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02007043
7044 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request {
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007045 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
7046 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7047 };
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007048 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007049 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007050 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007051
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007052 f_sleep(1.0);
7053}
7054testcase TC_ho_in_fail_no_detect2() runs on test_CT {
7055 var MSC_ConnHdlr vc_conn;
7056 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7057
Oliver Smith735b47c2023-02-15 16:03:54 +01007058 pars.fail_on_dlcx := false;
7059
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007060 f_init(1, true);
7061 f_sleep(1.0);
7062
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007063 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007064
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007065 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7066 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007067
7068 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
7069 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007070
7071 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7072 f_ctrs_bsc_and_bts_add(0, "handover:error");
7073 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7074 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7075 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007076 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007077}
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01007078
Oliver Smith7a8594a2023-02-13 14:30:49 +01007079testcase TC_ho_in_fail_mgw_mdcx_timeout() runs on test_CT {
7080 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7081
7082 pars.ignore_mgw_mdcx := true;
7083 pars.expect_ho_fail_lchan_est := true;
7084
7085 f_tc_ho_into_this_bsc_main(pars);
7086 f_shutdown_helper(ho := true);
7087}
7088
Oliver Smith4eed06f2023-02-15 15:43:19 +01007089testcase TC_ho_in_fail_ipa_crcx_timeout() runs on test_CT {
7090 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7091
7092 pars.ignore_ipa_media := true;
7093 pars.expect_ho_fail_lchan_est := true;
7094 pars.fail_on_dlcx := false;
7095
7096 f_tc_ho_into_this_bsc_main(pars);
7097 f_shutdown_helper(ho := true);
7098}
7099
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007100/* An incoming inter-BSC HO can either issue the Handover Request message attached to the initial SCCP N-Connect (as in
7101 * the other tests we have so far), or the first CR can be "empty" with the BSSAP request following later. Test the
7102 * empty N-Connect case. */
7103testcase TC_ho_into_this_bsc_sccp_cr_without_bssap() runs on test_CT {
7104 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7105 pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr := false;
7106 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02007107 f_shutdown_helper(ho := true);
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007108}
7109
Neels Hofmeyr91401012019-07-11 00:42:35 +02007110type record of charstring Commands;
7111
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007112private function f_bts_0_cfg(TELNETasp_PT pt, Commands cmds := {})
Neels Hofmeyr91401012019-07-11 00:42:35 +02007113{
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007114 f_vty_enter_cfg_bts(pt, 0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007115 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007116 f_vty_transceive(pt, cmds[i]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007117 }
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007118 f_vty_transceive(pt, "end");
Neels Hofmeyr91401012019-07-11 00:42:35 +02007119}
7120
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01007121private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
7122{
7123 f_vty_enter_cfg_cs7_inst(pt, 0);
7124 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
7125 f_vty_transceive(pt, cmds[i]);
7126 }
7127 f_vty_transceive(pt, "end");
7128}
7129
Neels Hofmeyr91401012019-07-11 00:42:35 +02007130private function f_probe_for_handover(charstring log_label,
7131 charstring log_descr,
7132 charstring handover_vty_cmd,
7133 boolean expect_handover,
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007134 boolean is_inter_bsc_handover := false,
7135 template uint3_t expect_target_tsc := ?)
Neels Hofmeyr91401012019-07-11 00:42:35 +02007136runs on MSC_ConnHdlr
7137{
Neels Hofmeyrb3fc8982020-05-11 00:16:42 +02007138 /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
7139 * lchans to be established on bts 1 or bts 2. */
7140 f_rslem_suspend(RSL1_PROC);
7141 f_rslem_suspend(RSL2_PROC);
7142
Neels Hofmeyr91401012019-07-11 00:42:35 +02007143 var RSL_Message rsl;
7144
7145 var charstring log_msg := " (expecting handover)"
7146 if (not expect_handover) {
7147 log_msg := " (expecting NO handover)";
7148 }
7149 log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg);
7150 f_vty_transceive(BSCVTY, handover_vty_cmd);
7151
Neels Hofmeyr91401012019-07-11 00:42:35 +02007152 timer T := 2.0;
7153 T.start;
7154
7155 alt {
7156 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
7157 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
7158 log("Rx L3 from net: ", l3);
7159 if (ischosen(l3.msgs.rrm.handoverCommand)) {
7160 var RslChannelNr new_chan_nr;
7161 var GsmArfcn arfcn;
7162 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
7163 new_chan_nr, arfcn);
7164 log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
7165 log(l3.msgs.rrm.handoverCommand);
7166
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007167 /* Verify correct TSC in handoverCommand */
7168 var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
7169 if (not match(got_tsc, expect_target_tsc)) {
7170 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
7171 expect_target_tsc, " got ", got_tsc);
7172 mtc.stop;
7173 } else {
7174 log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
7175 expect_target_tsc, ")");
7176 }
7177
Neels Hofmeyr91401012019-07-11 00:42:35 +02007178 /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
7179 * matter on which BTS it really is, we're not going to follow through an entire handover
7180 * anyway. */
7181 f_rslem_register(0, new_chan_nr, RSL1_PROC);
7182 f_rslem_resume(RSL1_PROC);
7183 f_rslem_register(0, new_chan_nr, RSL2_PROC);
7184 f_rslem_resume(RSL2_PROC);
7185
7186 if (expect_handover and not is_inter_bsc_handover) {
7187 setverdict(pass);
7188 log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected.");
7189 } else {
7190 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. "
7191 & log_label & ": " & log_descr);
7192 }
7193
7194 log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
7195 /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with
7196 * Handover Failure. */
7197 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
7198
7199 /* target BTS is told to release lchan again; don't care which BTS nor what messages. */
7200 f_sleep(0.5);
7201 RSL1.clear;
7202 RSL2.clear;
7203 log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)");
7204 break;
7205 } else {
7206 repeat;
7207 }
7208 }
7209 [] BSSAP.receive(tr_BSSMAP_HandoverRequired) {
7210 if (expect_handover and is_inter_bsc_handover) {
7211 setverdict(pass);
7212 log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected.");
7213 } else {
7214 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. "
7215 & log_label & ": " & log_descr);
7216 }
7217
7218 log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)");
7219
7220 /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to
7221 * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required,
7222 * setting a short timeout and waiting is the only way. */
7223 log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out...");
7224 f_sleep(1.5);
7225 log("f_probe_for_handover(" & log_label & "): ...done");
7226
7227 break;
7228 }
7229 [] T.timeout {
7230 if (expect_handover) {
7231 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. "
7232 & log_label & ": " & log_descr);
7233 } else {
7234 setverdict(pass);
7235 log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected.");
7236 }
7237 log("f_probe_for_handover(" & log_label & "): done (got no Handover)");
7238 break;
7239 }
7240 }
7241
7242 f_rslem_resume(RSL1_PROC);
7243 f_rslem_resume(RSL2_PROC);
7244 f_sleep(3.0);
7245 RSL.clear;
7246
7247 log("f_probe_for_handover(" & log_label & "): done clearing");
7248}
7249
7250/* Test the effect of various neighbor configuration scenarios:
7251 *
7252 * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0.
7253 * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO.
7254 */
7255private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
7256 g_pars := f_gen_test_hdlr_pars();
7257 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
7258 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007259
7260 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
7261 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
7262
7263 /* Establish lchan at bts 0 */
7264 f_establish_fully(ass_cmd, exp_compl);
7265
7266 /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */
7267 f_vty_enter_cfg_network(BSCVTY);
7268 f_vty_transceive(BSCVTY, "timer T7 1");
7269 f_vty_transceive(BSCVTY, "end");
7270}
7271
7272private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
7273 f_tc_ho_neighbor_config_start();
7274
7275 /*
7276 * bts 0 ARFCN 871 BSIC 10
7277 * bts 1 ARFCN 871 BSIC 11
7278 * bts 2 ARFCN 871 BSIC 12
7279 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7280 */
7281
7282 log("f_tc_ho_neighbor_config: 1. No 'neighbor' config");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007283 f_bts_0_cfg(BSCVTY, {"no neighbors"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007284 f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
7285 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007286 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007287
7288 f_probe_for_handover("1.b", "HO to unknown cell does not start",
7289 "handover any to arfcn 13 bsic 39",
7290 false);
7291
7292 f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error",
7293 "handover any to arfcn 871 bsic 12",
7294 false);
7295
7296 f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
7297 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007298 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007299
7300 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007301}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007302testcase TC_ho_neighbor_config_1() runs on test_CT {
7303 var MSC_ConnHdlr vc_conn;
7304 f_init(3, true, guard_timeout := 60.0);
7305 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007306 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007307 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
7308 vc_conn.done;
7309
7310 /* f_tc_ho_neighbor_config_start() */
7311 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7312 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7313
7314 /* 1.a */
7315 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7316 * handover quickly by sending a Handover Failure message. */
7317 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7318 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7319 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7320 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007321 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7322 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007323
7324 /* 1.b */
7325 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7326 f_ctrs_bsc_and_bts_add(0, "handover:error");
7327
7328 /* 1.c */
7329 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7330 f_ctrs_bsc_and_bts_add(0, "handover:error");
7331
7332 /* 1.d */
7333 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7334 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7335 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7336 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007337 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7338 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007339
7340 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007341 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007342}
7343
Neels Hofmeyr91401012019-07-11 00:42:35 +02007344private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
7345 f_tc_ho_neighbor_config_start();
7346
7347 /*
7348 * bts 0 ARFCN 871 BSIC 10
7349 * bts 1 ARFCN 871 BSIC 11
7350 * bts 2 ARFCN 871 BSIC 12
7351 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7352 */
7353
7354 log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007355 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007356 f_sleep(0.5);
7357
7358 f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
7359 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007360 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007361
7362 f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
7363 "handover any to arfcn 871 bsic 12",
7364 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007365 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007366}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007367testcase TC_ho_neighbor_config_2() runs on test_CT {
7368 var MSC_ConnHdlr vc_conn;
7369 f_init(3, true, guard_timeout := 50.0);
7370 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007371 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007372 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
7373 vc_conn.done;
7374
7375 /* f_tc_ho_neighbor_config_start() */
7376 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7377 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7378
7379 /* 2.a */
7380 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7381 * handover quickly by sending a Handover Failure message. */
7382 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7383 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7384 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7385 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007386 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7387 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007388
7389 /* 2.b */
7390 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7391 f_ctrs_bsc_and_bts_add(0, "handover:error");
7392
7393 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007394 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007395}
7396
Neels Hofmeyr91401012019-07-11 00:42:35 +02007397private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
7398 f_tc_ho_neighbor_config_start();
7399
7400 /*
7401 * bts 0 ARFCN 871 BSIC 10
7402 * bts 1 ARFCN 871 BSIC 11
7403 * bts 2 ARFCN 871 BSIC 12
7404 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7405 */
7406
7407 log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007408 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007409 f_sleep(0.5);
7410
7411 f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor",
7412 "handover any to arfcn 871 bsic 11",
7413 false);
7414 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",
7415 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007416 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007417 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007418}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007419testcase TC_ho_neighbor_config_3() runs on test_CT {
7420 var MSC_ConnHdlr vc_conn;
7421 f_init(3, true, guard_timeout := 50.0);
7422 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007423 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007424 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
7425 vc_conn.done;
7426
7427 /* f_tc_ho_neighbor_config_start() */
7428 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7429 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7430
7431 /* 3.a */
7432 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7433 f_ctrs_bsc_and_bts_add(0, "handover:error");
7434
7435 /* 3.b */
7436 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7437 * handover quickly by sending a Handover Failure message. */
7438 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7439 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7440 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7441 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007442 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7443 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007444
7445 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007446 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007447}
7448
Neels Hofmeyr91401012019-07-11 00:42:35 +02007449private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
7450 f_tc_ho_neighbor_config_start();
7451
7452 /*
7453 * bts 0 ARFCN 871 BSIC 10
7454 * bts 1 ARFCN 871 BSIC 11
7455 * bts 2 ARFCN 871 BSIC 12
7456 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7457 */
7458
7459 log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007460 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007461 f_sleep(0.5);
7462
7463 f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor",
7464 "handover any to arfcn 871 bsic 11",
7465 false);
7466 f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor",
7467 "handover any to arfcn 871 bsic 12",
7468 false);
7469 f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
7470 "handover any to arfcn 123 bsic 45",
7471 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007472 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007473}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007474testcase TC_ho_neighbor_config_4() runs on test_CT {
7475 var MSC_ConnHdlr vc_conn;
7476 f_init(3, true, guard_timeout := 50.0);
7477 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007478 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007479 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
7480 vc_conn.done;
7481
7482 /* f_tc_ho_neighbor_config_start() */
7483 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7484 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7485
7486 /* 4.a */
7487 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7488 f_ctrs_bsc_and_bts_add(0, "handover:error");
7489
7490 /* 4.b */
7491 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7492 f_ctrs_bsc_and_bts_add(0, "handover:error");
7493
7494 /* 4.c */
7495 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7496 * handover quickly by timing out after the Handover Required message */
7497 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7498 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7499 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7500 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7501
7502 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007503 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007504}
7505
Neels Hofmeyr91401012019-07-11 00:42:35 +02007506private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
7507 f_tc_ho_neighbor_config_start();
7508
7509 /*
7510 * bts 0 ARFCN 871 BSIC 10
7511 * bts 1 ARFCN 871 BSIC 11
7512 * bts 2 ARFCN 871 BSIC 12
7513 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7514 */
7515
7516 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 +02007517 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007518 f_sleep(0.5);
7519
7520 f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
7521 "handover any to arfcn 871 bsic 12",
7522 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007523 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007524}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007525testcase TC_ho_neighbor_config_5() runs on test_CT {
7526 var MSC_ConnHdlr vc_conn;
7527 f_init(3, true);
7528 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007529 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007530 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
7531 vc_conn.done;
7532
7533 /* f_tc_ho_neighbor_config_start() */
7534 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7535 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7536
7537 /* 5 */
7538 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7539 * handover quickly by timing out after the Handover Required message */
7540 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7541 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7542 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7543 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7544
7545 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007546 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007547}
7548
Neels Hofmeyr91401012019-07-11 00:42:35 +02007549private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
7550 f_tc_ho_neighbor_config_start();
7551
7552 /*
7553 * bts 0 ARFCN 871 BSIC 10
7554 * bts 1 ARFCN 871 BSIC 11
7555 * bts 2 ARFCN 871 BSIC 12
7556 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7557 */
7558
7559 log("f_tc_ho_neighbor_config: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:"
7560 & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007561 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007562 f_sleep(0.5);
7563
7564 f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
7565 "handover any to arfcn 871 bsic 12",
7566 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007567 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007568}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007569testcase TC_ho_neighbor_config_6() runs on test_CT {
7570 var MSC_ConnHdlr vc_conn;
7571 f_init(3, true);
7572 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007573 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007574 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
7575 vc_conn.done;
7576
7577 /* f_tc_ho_neighbor_config_start() */
7578 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7579 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7580
7581 /* 6.a */
7582 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7583 * handover quickly by timing out after the Handover Required message */
7584 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7585 f_ctrs_bsc_and_bts_add(0, "handover:error");
7586
7587 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007588 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007589}
7590
Neels Hofmeyr91401012019-07-11 00:42:35 +02007591private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
7592 f_tc_ho_neighbor_config_start();
7593
7594 /*
7595 * bts 0 ARFCN 871 BSIC 10
7596 * bts 1 ARFCN 871 BSIC 11
7597 * bts 2 ARFCN 871 BSIC 12
7598 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7599 */
7600
7601 log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:"
7602 & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007603 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007604 f_sleep(0.5);
7605
7606 f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
7607 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007608 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007609 f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
7610 "handover any to arfcn 123 bsic 45",
7611 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007612 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007613}
Neels Hofmeyr91401012019-07-11 00:42:35 +02007614testcase TC_ho_neighbor_config_7() runs on test_CT {
7615 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf2b88032020-06-16 00:35:04 +02007616 f_init(3, true, guard_timeout := 50.0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007617 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007618 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007619 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
7620 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007621
7622 /* f_tc_ho_neighbor_config_start() */
7623 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7624 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7625
7626 /* 7.a */
7627 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7628 * handover quickly by sending a Handover Failure message. */
7629 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7630 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7631 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7632 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007633 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7634 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007635
7636 /* 7.b */
7637 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7638 * handover quickly by timing out after the Handover Required message */
7639 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7640 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7641 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7642 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7643
7644 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007645 f_shutdown_helper(ho := true);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007646}
7647
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007648/* OS#3041: Open and close N connections in a normal fashion, and expect no
7649 * BSSMAP Reset just because of that. */
7650testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
7651 var default d;
7652 var integer i;
7653 var DchanTuple dt;
7654
7655 f_init();
7656
7657 /* Wait for initial BSSMAP Reset to pass */
7658 f_sleep(4.0);
7659
7660 d := activate(no_bssmap_reset());
7661
7662 /* Setup up a number of connections and RLSD them again from the MSC
7663 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7664 * Let's do it some more times for good measure. */
Harald Weltec3260d92018-06-11 17:48:16 +02007665 for (i := 0; i < 4; i := i+1) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007666 /* Since we're doing a lot of runs, give each one a fresh
7667 * T_guard from the top. */
7668 T_guard.start;
7669
7670 /* Setup a BSSAP connection and clear it right away. This is
7671 * the MSC telling the BSC about a planned release, it's not an
7672 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007673 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007674
7675 /* MSC disconnects (RLSD). */
7676 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
7677 }
7678
7679 /* In the buggy behavior, a timeout of 2 seconds happens between above
7680 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7681 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7682 f_sleep(4.0);
7683
7684 deactivate(d);
7685 f_shutdown_helper();
7686}
Harald Welte552620d2017-12-16 23:21:36 +01007687
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007688/* OS#3041: Open and close N connections in a normal fashion, and expect no
7689 * BSSMAP Reset just because of that. Invoke the release by a BSSMAP Clear from
7690 * the MSC. */
7691testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
7692 var default d;
7693 var integer i;
7694 var DchanTuple dt;
7695 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007696 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
7697 var BssmapCause cause := enum2int(cause_val);
7698
7699 f_init();
7700
7701 /* Wait for initial BSSMAP Reset to pass */
7702 f_sleep(4.0);
7703
7704 d := activate(no_bssmap_reset());
7705
7706 /* Setup up a number of connections and RLSD them again from the MSC
7707 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7708 * Let's do it some more times for good measure. */
7709 for (i := 0; i < 8; i := i+1) {
7710 /* Since we're doing a lot of runs, give each one a fresh
7711 * T_guard from the top. */
7712 T_guard.start;
7713
7714 /* Setup a BSSAP connection and clear it right away. This is
7715 * the MSC telling the BSC about a planned release, it's not an
7716 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007717 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007718
7719 /* Instruct BSC to clear channel */
7720 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7721
7722 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007723 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007724 }
7725
7726 /* In the buggy behavior, a timeout of 2 seconds happens between above
7727 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7728 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7729 f_sleep(4.0);
7730
7731 deactivate(d);
7732 f_shutdown_helper();
7733}
7734
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007735/* OS#3041: Open and close N connections in a normal fashion, and expect no
7736 * BSSMAP Reset just because of that. Close connections from the MS side with a
7737 * Release Ind on RSL. */
7738testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
7739 var default d;
7740 var integer i;
7741 var DchanTuple dt;
7742 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007743 var integer j;
7744
7745 f_init();
7746
7747 /* Wait for initial BSSMAP Reset to pass */
7748 f_sleep(4.0);
7749
7750 d := activate(no_bssmap_reset());
7751
7752 /* Setup up a number of connections and RLSD them again from the MSC
7753 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7754 * Let's do it some more times for good measure. */
7755 for (i := 0; i < 8; i := i+1) {
7756 /* Since we're doing a lot of runs, give each one a fresh
7757 * T_guard from the top. */
7758 T_guard.start;
7759
7760 /* Setup a BSSAP connection and clear it right away. This is
7761 * the MSC telling the BSC about a planned release, it's not an
7762 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007763 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007764
7765 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007766 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007767
7768 /* expect Clear Request on MSC side */
7769 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
7770
7771 /* Instruct BSC to clear channel */
7772 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
7773 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7774
7775 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007776 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007777 }
7778
7779 /* In the buggy behavior, a timeout of 2 seconds happens between above
7780 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7781 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7782 f_sleep(4.0);
7783
7784 deactivate(d);
7785 f_shutdown_helper();
7786}
7787
Harald Welte94e0c342018-04-07 11:33:23 +02007788/***********************************************************************
7789 * IPA style dynamic PDCH
7790 ***********************************************************************/
7791
7792private function f_dyn_ipa_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7793 template (omit) RSL_Cause nack := omit)
7794runs on test_CT {
7795 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7796 var RSL_Message rsl_unused;
7797 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7798 f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
7799 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007800 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007801 if (istemplatekind(nack, "omit")) {
7802 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007803 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007804 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007805 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007806 }
7807}
7808
7809private function f_dyn_ipa_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7810 template (omit) RSL_Cause nack := omit)
7811runs on test_CT {
7812 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7813 var RSL_Message rsl_unused;
7814 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7815 f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
7816 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007817 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_DEACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007818 if (istemplatekind(nack, "omit")) {
7819 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007820 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007821 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007822 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007823 }
7824}
7825
7826private function f_ts_dyn_mode_get(integer bts_nr, integer trx_nr, integer ts_nr)
7827runs on test_CT return charstring {
7828 var charstring cmd, resp;
7829 cmd := "show timeslot "&int2str(bts_nr)&" "&int2str(trx_nr)&" "&int2str(ts_nr);
Stefan Sperlingcff13562018-11-13 15:24:06 +01007830 return f_vty_transceive_match_regexp_retry(BSCVTY, cmd, "*\((*)\)*", 0, 4, 1.0);
Harald Welte94e0c342018-04-07 11:33:23 +02007831}
7832
7833private function f_ts_dyn_mode_assert(integer bts_nr, integer trx_nr, integer ts_nr,
7834 template charstring exp)
7835runs on test_CT {
7836 var charstring mode := f_ts_dyn_mode_get(bts_nr, trx_nr, ts_nr);
7837 if (not match(mode, exp)) {
7838 setverdict(fail, "Unexpected TS Mode: ", mode);
Daniel Willmannafce8662018-07-06 23:11:32 +02007839 mtc.stop;
Harald Welte94e0c342018-04-07 11:33:23 +02007840 }
7841}
7842
7843private function f_ts_set_chcomb(integer bts_nr, integer trx_nr, integer ts_nr, charstring chcomb)
7844runs on test_CT {
7845 f_vty_enter_cfg_ts(BSCVTY, bts_nr, trx_nr, ts_nr);
7846 f_vty_transceive(BSCVTY, "phys_chan_config " & chcomb);
7847 f_vty_transceive(BSCVTY, "end");
7848}
7849
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007850
7851private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
7852 var integer i;
7853 for (i := 0; i < 8; i := i + 1) {
7854 f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
7855 }
7856}
7857
Harald Welte94e0c342018-04-07 11:33:23 +02007858private const charstring TCHF_MODE := "TCH/F mode";
7859private const charstring TCHH_MODE := "TCH/H mode";
7860private const charstring PDCH_MODE := "PDCH mode";
7861private const charstring NONE_MODE := "NONE mode";
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007862private const charstring SDCCH8_MODE := "SDCCH8 mode";
Harald Welte94e0c342018-04-07 11:33:23 +02007863
7864/* Test IPA PDCH activation / deactivation triggered by VTY */
7865testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
7866 var RSL_Message rsl_unused;
7867
7868 /* change Timeslot 6 before f_init() starts RSL */
7869 f_init_vty();
7870 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7871 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7872
7873 f_init(1, false);
7874 f_sleep(1.0);
7875
7876 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7877
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007878 log("TCH/F_PDCH pchan starts out in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007879 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7880 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007881 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7882 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007883 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007884 log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007885 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7886
7887 /* De-activate it via VTY */
7888 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7889 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007890 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007891 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7892
7893 /* re-activate it via VTY */
7894 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn);
7895 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007896 log("TCH/F_PDCH pchan, PDCH ACT via VTY, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007897 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7898
7899 /* and finally de-activate it again */
7900 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7901 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007902 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007903 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7904
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007905 /* clean up config */
7906 f_ts_set_chcomb(0, 0, 6, "PDCH");
7907
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007908 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007909}
7910
7911/* Test IPA PDCH activation NACK */
7912testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
7913 var RSL_Message rsl_unused;
7914
7915 /* change Timeslot 6 before f_init() starts RSL */
7916 f_init_vty();
7917 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7918 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7919
7920 f_init(1, false);
7921 f_sleep(1.0);
7922
7923 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7924
7925 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7926 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007927 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7928 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007929 f_sleep(1.0);
7930 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7931
7932 /* De-activate it via VTY */
7933 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7934 f_sleep(1.0);
7935 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7936
7937 /* re-activate it via VTY, but fail that; check BSC still assumes TCH/F mode */
7938 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn, RSL_ERR_EQUIPMENT_FAIL);
7939 f_sleep(1.0);
7940 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7941
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007942 /* clean up config */
7943 f_ts_set_chcomb(0, 0, 6, "PDCH");
7944
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007945 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007946}
7947
7948
7949/***********************************************************************
7950 * Osmocom style dynamic PDCH
7951 ***********************************************************************/
7952
7953private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7954 template (omit) RSL_Cause nack := omit)
7955runs on test_CT {
7956 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7957 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007958 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007959 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7960 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007961 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT(chan_nr, ?));
Harald Welte94e0c342018-04-07 11:33:23 +02007962 if (istemplatekind(nack, "omit")) {
7963 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007964 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02007965 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007966 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007967 }
7968}
7969
7970private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7971 template (omit) RSL_Cause nack := omit)
7972runs on test_CT {
7973 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7974 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007975 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007976 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7977 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007978 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007979 if (istemplatekind(nack, "omit")) {
7980 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007981 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007982 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007983 //f_ipa_tx(ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007984 }
7985}
7986
7987/* Test Osmocom dyn PDCH activation / deactivation triggered by VTY */
7988testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
7989 var RSL_Message rsl_unused;
7990
7991 /* change Timeslot 6 before f_init() starts RSL */
7992 f_init_vty();
7993 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
7994 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7995
7996 f_init(1, false);
7997 f_sleep(1.0);
7998
7999 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8000
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008001 log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02008002 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8003 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008004 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008005
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008006 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02008007 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008008 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 +02008009 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
8010
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008011 /* clean up config */
8012 f_ts_set_chcomb(0, 0, 6, "PDCH");
8013
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008014 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008015}
8016
8017/* Test Osmocom dyn PDCH activation NACK behavior */
8018testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
8019 var RSL_Message rsl_unused;
8020
8021 /* change Timeslot 6 before f_init() starts RSL */
8022 f_init_vty();
8023 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8024 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8025
8026 f_init(1, false);
8027 f_sleep(1.0);
8028
8029 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8030
8031 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8032 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008033 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008034
8035 /* NACK this activation and expect the "show timeslot" mode still to be NONE */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008036 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte94e0c342018-04-07 11:33:23 +02008037 f_sleep(1.0);
8038 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8039
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008040 /* clean up config */
8041 f_ts_set_chcomb(0, 0, 6, "PDCH");
8042
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008043 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008044}
8045
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008046/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
8047testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
8048 var RSL_Message rsl_unused, rsl_msg;
8049 var DchanTuple dt;
8050 var BSSAP_N_CONNECT_ind rx_c_ind;
8051
8052 /* change Timeslot 6 before f_init() starts RSL */
8053 f_init_vty();
8054 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8055 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8056
8057 f_init(1, false);
8058 f_sleep(1.0);
8059
8060 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8061
8062 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8063 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8064 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008065 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008066
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008067 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008068 f_sleep(1.0);
8069 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8070 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8071
8072 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8073 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008074 var DchanTuples sdcch_cleanup := {};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008075 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008076 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008077 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008078 sdcch_cleanup := sdcch_cleanup & { dt };
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008079 }
8080
8081 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008082 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8083 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8084 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008085
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008086 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008087 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008088 dt.idx := {0, 0};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008089
8090 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008091 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8092 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008093 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
8094
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008095 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 +02008096 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8097 dt.sccp_conn_id := rx_c_ind.connectionId;
8098 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8099
8100 /* Instruct BSC to clear channel */
8101 var BssmapCause cause := 0;
8102 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008103 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008104
8105 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008106 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8107 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008108 f_sleep(1.0);
8109 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8110
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008111 /* Clean up SDCCH lchans */
8112 for (i := 0; i < lengthof(sdcch_cleanup); i := i + 1) {
8113 f_perform_clear_test_ct(sdcch_cleanup[i]);
8114 }
8115
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008116 /* clean up config */
8117 f_ts_set_chcomb(0, 0, 6, "PDCH");
8118
8119 f_shutdown_helper();
8120}
8121
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008122/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
8123testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
8124 var ASP_RSL_Unitdata rsl_ud;
8125 var integer i;
8126 var integer chreq_total, chreq_nochan;
8127
8128 f_init_vty();
8129 for (i := 1; i < 8; i := i + 1) {
8130 if (i == 2) {
8131 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8132 } else {
8133 f_ts_set_chcomb(0, 0, i, "PDCH");
8134 }
8135 }
8136 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8137
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008138 f_init(1, guard_timeout := 60.0);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008139
8140 /* The dyn TS want to activate PDCH mode, ACK that. */
8141 var RslChannelNr chan_nr;
8142 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008143 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
8144 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008145
8146 f_sleep(1.0);
8147
8148 /* Exhaust all dedicated SDCCH lchans.
8149 /* GSM 44.018 Table 9.1.8.2:
8150 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
8151 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008152 var DchanTuples chan_cleanup := {};
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008153 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008154 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 +02008155 }
8156
8157 /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008158 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 +02008159 /* Also occupy the seven other SDCCH of the dyn TS */
8160 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008161 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 +01008162 }
8163
8164 /* Clean up SDCCH lchans */
8165 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8166 f_perform_clear_test_ct(chan_cleanup[i]);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008167 }
8168
8169 /* clean up config */
8170 f_ts_reset_chcomb(0);
8171
8172 f_shutdown_helper();
8173}
8174
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008175/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
8176 SDCCH8 would end up in having no free TCH, then BSC should decide to activate
8177 it as TCH directly instead. SYS#5309. */
8178testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
8179 var RSL_Message rsl_unused, rsl_msg;
8180 var DchanTuple dt;
8181 var BSSAP_N_CONNECT_ind rx_c_ind;
8182 var integer i;
8183
8184 /* change Timeslot 6 before f_init() starts RSL */
8185 f_init_vty();
8186 for (i := 1; i < 8; i := i + 1) {
8187 if (i == 6) {
8188 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8189 } else {
8190 f_ts_set_chcomb(0, 0, i, "PDCH");
8191 }
8192 }
8193 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8194
8195 f_init(1, false);
8196 f_sleep(1.0);
8197
8198 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8199
8200 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8201 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8202 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008203 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008204
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008205 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008206 f_sleep(1.0);
8207 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8208 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8209
8210 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8211 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008212 var DchanTuples chan_cleanup := {};
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02008213 var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008214 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008215 dt := f_est_dchan(ra, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008216 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008217 }
8218
8219 /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008220 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
8221 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8222 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008223
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008224 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008225 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008226 dt.idx := {0, 0};
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008227
8228 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008229 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8230 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008231 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
8232
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008233 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 +02008234 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8235 dt.sccp_conn_id := rx_c_ind.connectionId;
8236 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8237
8238 /* Instruct BSC to clear channel */
8239 var BssmapCause cause := 0;
8240 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008241 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008242
8243 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008244 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8245 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008246 f_sleep(1.0);
8247 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8248
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008249 /* Clean up SDCCH lchans */
8250 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8251 f_perform_clear_test_ct(chan_cleanup[i]);
8252 }
8253
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008254 /* clean up config */
8255 f_ts_reset_chcomb(0);
8256 /* TODO: clean up other channels? */
8257
8258 f_shutdown_helper();
8259}
8260
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008261/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
8262testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
8263 var RSL_Message rsl_unused, rsl_msg;
8264 var DchanTuple dt;
8265 var BSSAP_N_CONNECT_ind rx_c_ind;
8266 var GsmRrMessage rr;
8267
8268 /* change Timeslot 6 before f_init() starts RSL */
8269 f_init_vty();
8270 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8271 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8272
8273 f_init(1, false);
8274 f_sleep(1.0);
8275
8276 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8277
8278 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8279 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8280 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008281 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008282
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008283 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008284 f_sleep(1.0);
8285 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8286 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8287
8288 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8289 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008290 var DchanTuples chan_cleanup := {};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008291 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008292 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008293 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008294 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008295 }
8296
8297 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008298 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8299 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8300 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008301
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008302 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008303 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008304 dt.idx := {0, 0};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008305
8306 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008307 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
8308 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008309 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
8310 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
8311 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
8312 }
8313
8314 /* FIXME? Currently the TS stays in state BORKEN: */
8315
8316 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008317 /* rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8318 * f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008319 * f_sleep(1.0);
8320 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
8321 */
8322
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008323 /* Clean up SDCCH lchans */
8324 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8325 f_perform_clear_test_ct(chan_cleanup[i]);
8326 }
8327
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008328 /* clean up config */
8329 f_ts_set_chcomb(0, 0, 6, "PDCH");
8330
8331 f_shutdown_helper();
8332}
8333
Stefan Sperling0796a822018-10-05 13:01:39 +02008334testcase TC_chopped_ipa_ping() runs on test_CT {
Stefan Sperling554123f2018-10-09 14:12:30 +02008335 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port, mp_bsc_ctrl_port};
Stefan Sperling0796a822018-10-05 13:01:39 +02008336 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8337 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8338 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008339 f_shutdown_helper();
Stefan Sperling0796a822018-10-05 13:01:39 +02008340}
8341
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008342testcase TC_chopped_ipa_payload() runs on test_CT {
8343 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port
8344 /* TODO: mp_bsc_ctrl_port does not work yet */};
8345 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8346 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8347 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008348 f_shutdown_helper();
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008349}
8350
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008351/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
8352 the BTS does autonomous MS power control loop */
8353testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
8354 var MSC_ConnHdlr vc_conn;
8355 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8356 //pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
8357 pars.exp_ms_power_params := true;
8358
8359 f_init(1, true);
8360 f_sleep(1.0);
8361 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
8362 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008363 f_shutdown_helper();
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008364}
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008365
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008366/* Verify activation and deactivation of the BCCH carrier power reduction mode */
8367testcase TC_c0_power_red_mode() runs on test_CT {
8368 f_init(1);
8369
8370 for (var integer red := 6; red >= 0; red := red - 2) {
8371 /* Configure BCCH carrier power reduction mode via the VTY */
8372 f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
8373
8374 /* Expect Osmocom specific BS Power Control message on the RSL */
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03008375 var template (present) RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008376 chan_nr := t_RslChanNr_BCCH(0),
8377 bs_power := tr_RSL_IE_BS_Power(red / 2));
8378 tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008379 var RSL_Message unused := f_exp_ipa_rx(tr_rsl_pdu);
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008380
8381 /* Additionally verify the applied value over the CTRL interface */
8382 var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
8383 if (cred != int2str(red)) {
8384 setverdict(fail, "Unexpected BCCH carrier power reduction value ",
8385 cred, " (expected ", red, ")");
8386 }
8387 }
8388
8389 f_shutdown_helper();
8390}
8391
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008392/***********************************************************************
8393 * MSC Pooling
8394 ***********************************************************************/
8395
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008396template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
Harald Weltebf397612021-01-14 20:39:46 +01008397 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 +02008398
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008399private 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 +02008400runs on MSC_ConnHdlr {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008401 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008402 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008403 f_logp(BSCVTY, "Got RSL RR Release");
8404 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008405 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008406 f_logp(BSCVTY, "Got RSL Deact SACCH");
8407 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008408 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008409 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008410 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8411 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008412 break;
8413 }
8414 }
8415}
8416
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008417private altstep as_mgcp_ack_all_dlcx() runs on MSC_ConnHdlr {
8418 var MgcpCommand mgcp_cmd;
8419 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
8420 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
8421 repeat;
8422 }
8423}
8424
8425private altstep as_rsl_ack_all_rel_req() runs on MSC_ConnHdlr {
8426 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
8427 [] RSL.receive(tr_RSL_REL_REQ(g_chan_nr, ?)) {
8428 RSL.send(ts_RSL_REL_CONF(g_chan_nr, main_dcch));
8429 repeat;
8430 }
8431}
8432
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008433friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
8434 template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02008435runs on MSC_ConnHdlr {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008436 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8437 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008438 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008439 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8440 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008441 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008442 f_logp(BSCVTY, "Got RSL RR Release");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008443 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008444 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008445 f_logp(BSCVTY, "Got RSL Deact SACCH");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008446 }
8447 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008448 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008449 /* Also drop the SCCP connection */
8450 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8451 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008452 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008453 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008454 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8455 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008456 }
8457 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008458 deactivate(ack_dlcx);
8459 deactivate(ack_rel_req);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008460}
8461
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01008462friend function f_perform_clear_no_rr_rel(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC)
8463runs on MSC_ConnHdlr {
8464 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8465 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
8466 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8467 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8468 interleave {
8469 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
8470 f_logp(BSCVTY, "Got RSL Deact SACCH");
8471 }
8472 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
8473 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8474 /* Also drop the SCCP connection */
8475 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8476 }
8477 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
8478 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
8479 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8480 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
8481 }
8482 }
8483 deactivate(ack_dlcx);
8484 deactivate(ack_rel_req);
8485}
8486
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01008487friend function f_perform_clear_no_lchan()
8488runs on MSC_ConnHdlr {
8489 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8490 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8491 BSSAP.receive(tr_BSSMAP_ClearComplete);
8492 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8493 /* Also drop the SCCP connection */
8494 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8495}
8496
Vadim Yanitskiy65d879d2022-06-23 18:15:39 +07008497friend function f_perform_clear_test_ct(DchanTuple dt)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008498 runs on test_CT
8499{
8500 /* Instruct BSC to clear channel */
8501 var BssmapCause cause := 0;
8502 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008503 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008504}
8505
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008506private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
8507 template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008508runs on MSC_ConnHdlr {
8509 timer T := 10.0;
8510 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
8511
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008512 f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008513 f_create_bssmap_exp(l3_enc);
8514
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008515 /* RSL_Emulation.f_chan_est() on rsl_pt:
8516 * This is basically code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008517 * RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
8518 */
8519 var RSL_Message rx_rsl;
8520 var GsmRrMessage rr;
8521
8522 /* request a channel to be established */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008523 rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008524 /* expect immediate assignment.
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008525 * Code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008526 * rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
8527 */
8528 timer Tt := 10.0;
8529
8530 /* request a channel to be established */
8531 Tt.start;
8532 alt {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008533 [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008534 Tt.stop;
8535 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008536 [] rsl_pt.receive {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008537 setverdict(fail, "Unexpected RSL message on DCHAN");
8538 mtc.stop;
8539 }
8540 [] Tt.timeout {
8541 setverdict(fail, "Timeout waiting for RSL on DCHAN");
8542 mtc.stop;
8543 }
8544 }
8545 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
8546 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008547 rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008548
8549
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008550 if (expect_bssmap_l3) {
8551 f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
8552 var template PDU_BSSAP exp_l3_compl;
8553 exp_l3_compl := tr_BSSMAP_ComplL3()
8554 if (g_pars.aoip == false) {
8555 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
8556 } else {
8557 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
8558 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008559
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008560 var PDU_BSSAP bssap;
8561 T.start;
8562 alt {
8563 [] BSSAP.receive(exp_l3_compl) -> value bssap {
8564 f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
8565 log("rx exp_l3_compl = ", bssap);
8566 }
8567 [] BSSAP.receive(tr_BSSMAP_ComplL3) {
8568 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
8569 }
8570 [] T.timeout {
8571 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
8572 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008573 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008574
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008575 /* start ciphering, if requested */
8576 if (ispresent(g_pars.encr)) {
8577 f_logp(BSCVTY, "start ciphering");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008578 f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008579 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008580 }
8581
8582 if (do_clear) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008583 f_perform_clear(rsl_pt, rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008584 }
8585 setverdict(pass);
8586 f_sleep(1.0);
8587}
8588
8589private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
8590 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8591 if (g_pars.mscpool.rsl_idx == 0) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008592 f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008593 } else if (g_pars.mscpool.rsl_idx == 1) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008594 f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008595 } else if (g_pars.mscpool.rsl_idx == 2) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008596 f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008597 }
8598}
8599
8600/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
8601private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
8602 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008603 f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
8604 f_perform_compl_l3(RSL, RSL_PROC, ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_IMSI_LV('001010000000002'H))) );
8605 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))) );
8606 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 +02008607}
8608testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
8609
8610 f_init(1, true);
8611 f_sleep(1.0);
8612 var MSC_ConnHdlr vc_conn;
8613 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008614
8615 f_ctrs_msc_init();
8616
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008617 vc_conn := f_start_handler(refers(f_tc_mscpool_L3Compl_on_1_msc), pars);
8618 vc_conn.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008619
8620 f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008621 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008622}
8623
8624/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
8625/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8626 * just as well using only RSL. */
8627testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
8628
8629 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8630 f_sleep(1.0);
8631
8632 /* Control which MSC gets chosen next by the round-robin, otherwise
8633 * would be randomly affected by which other tests ran before this. */
8634 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8635
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008636 f_ctrs_msc_init();
8637
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008638 var MSC_ConnHdlr vc_conn1;
8639 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8640 pars1.mscpool.rsl_idx := 0;
8641 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8642 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8643 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008644 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008645
8646 var MSC_ConnHdlr vc_conn2;
8647 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8648 pars2.mscpool.rsl_idx := 1;
8649 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8650 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8651 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008652 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008653
8654 /* Test round-robin wrap to the first MSC */
8655 var MSC_ConnHdlr vc_conn3;
8656 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8657 pars3.mscpool.rsl_idx := 2;
8658 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
8659 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8660 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008661 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008662 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008663}
8664
8665/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 0
8666 * (configured in osmo-bsc.cfg). */
8667/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8668 * just as well using only RSL. */
8669testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
8670
8671 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8672 f_sleep(1.0);
8673
8674 /* Control which MSC gets chosen next by the round-robin, otherwise
8675 * would be randomly affected by which other tests ran before this. */
8676 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8677
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008678 f_ctrs_msc_init();
8679
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008680 var MSC_ConnHdlr vc_conn1;
8681 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8682 pars1.mscpool.rsl_idx := 0;
8683 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8684 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8685 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008686 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008687
8688 var MSC_ConnHdlr vc_conn2;
8689 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8690 pars2.mscpool.rsl_idx := 1;
8691 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8692 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8693 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008694 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008695
8696 /* Test round-robin wrap to the first MSC */
8697 var MSC_ConnHdlr vc_conn3;
8698 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8699 pars3.mscpool.rsl_idx := 2;
8700 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8701 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8702 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008703 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008704 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008705}
8706
8707/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
8708 * (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
8709 * NULL-NRI setting is stronger than that. */
8710/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8711 * just as well using only RSL. */
8712testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
8713
8714 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8715 f_sleep(1.0);
8716
8717 /* Control which MSC gets chosen next by the round-robin, otherwise
8718 * would be randomly affected by which other tests ran before this. */
8719 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8720
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008721 f_ctrs_msc_init();
8722
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008723 var MSC_ConnHdlr vc_conn1;
8724 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8725 pars1.mscpool.rsl_idx := 0;
8726 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8727 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8728 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008729 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008730
8731 var MSC_ConnHdlr vc_conn2;
8732 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8733 pars2.mscpool.rsl_idx := 1;
8734 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8735 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8736 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008737 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008738
8739 /* Test round-robin wrap to the first MSC */
8740 var MSC_ConnHdlr vc_conn3;
8741 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8742 pars3.mscpool.rsl_idx := 2;
8743 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8744 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8745 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008746 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008747 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008748}
8749
8750/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
8751 * assigned to any MSC (configured in osmo-bsc.cfg). */
8752/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8753 * just as well using only RSL. */
8754testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test_CT {
8755
8756 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8757 f_sleep(1.0);
8758
8759 /* Control which MSC gets chosen next by the round-robin, otherwise
8760 * would be randomly affected by which other tests ran before this. */
8761 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8762
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008763 f_ctrs_msc_init();
8764
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008765 var MSC_ConnHdlr vc_conn1;
8766 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8767 pars1.mscpool.rsl_idx := 0;
8768 /* An NRI that is not assigned to any MSC */
8769 pars1.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(1023))));
8770 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8771 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008772 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008773
8774 var MSC_ConnHdlr vc_conn2;
8775 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8776 pars2.mscpool.rsl_idx := 1;
8777 /* An NRI that is not assigned to any MSC */
8778 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(768)), '00F110'O));
8779 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8780 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008781 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008782
8783 /* Test round-robin wrap to the first MSC */
8784 var MSC_ConnHdlr vc_conn3;
8785 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8786 pars3.mscpool.rsl_idx := 2;
8787 /* An NRI that is not assigned to any MSC */
8788 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, valueof(ts_MI_TMSI_NRI_LV(819))));
8789 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8790 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008791 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008792 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008793}
8794
8795/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
8796 * assigned to an MSC that is currently not connected (configured in osmo-bsc.cfg). */
8797/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8798 * just as well using only RSL. */
8799testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
8800
8801 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8802 f_sleep(1.0);
8803
8804 /* Control which MSC gets chosen next by the round-robin, otherwise
8805 * would be randomly affected by which other tests ran before this. */
8806 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8807
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008808 f_ctrs_msc_init();
8809
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008810 var MSC_ConnHdlr vc_conn1;
8811 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8812 pars1.mscpool.rsl_idx := 0;
8813 /* An NRI that is assigned to an unconnected MSC */
8814 pars1.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(512))));
8815 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8816 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008817 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8818 f_ctrs_msc_add(0, "mscpool:subscr:new");
8819 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008820
8821 var MSC_ConnHdlr vc_conn2;
8822 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8823 pars2.mscpool.rsl_idx := 1;
8824 /* An NRI that is assigned to an unconnected MSC */
8825 pars2.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(767))));
8826 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8827 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008828 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8829 f_ctrs_msc_add(1, "mscpool:subscr:new");
8830 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008831
8832 /* Test round-robin wrap to the first MSC */
8833 var MSC_ConnHdlr vc_conn3;
8834 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8835 pars3.mscpool.rsl_idx := 2;
8836 /* An NRI that is assigned to an unconnected MSC */
8837 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(750)), '00F110'O));
8838 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8839 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008840 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8841 f_ctrs_msc_add(0, "mscpool:subscr:new");
8842 f_ctrs_msc_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008843 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008844}
8845
8846/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
8847 * osmo-bsc.cfg). */
8848/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8849 * just as well using only RSL. */
8850testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
8851
8852 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8853 f_sleep(1.0);
8854
8855 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
8856 * this is not using round-robin. */
8857 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8858
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008859 f_ctrs_msc_init();
8860
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008861 var MSC_ConnHdlr vc_conn1;
8862 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8863 pars1.mscpool.rsl_idx := 0;
8864 /* An NRI of the second MSC's range (256-511) */
8865 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(256))));
8866 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8867 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008868 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008869
8870 var MSC_ConnHdlr vc_conn2;
8871 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8872 pars2.mscpool.rsl_idx := 1;
8873 /* An NRI of the second MSC's range (256-511) */
8874 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(260))));
8875 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8876 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008877 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008878
8879 var MSC_ConnHdlr vc_conn3;
8880 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8881 pars3.mscpool.rsl_idx := 2;
8882 /* An NRI of the second MSC's range (256-511) */
8883 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(511)), '00F110'O));
8884 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8885 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008886 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008887 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008888}
8889
8890/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
8891 * while a round-robin remains unaffected by that. */
8892/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8893 * just as well using only RSL. */
8894testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
8895
8896 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8897 f_sleep(1.0);
8898
8899 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
8900 * this is not using round-robin. */
8901 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8902
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008903 f_ctrs_msc_init();
8904
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008905 var MSC_ConnHdlr vc_conn1;
8906 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 2);
8907 pars1.mscpool.rsl_idx := 0;
8908 /* An NRI of the third MSC's range (512-767) */
8909 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(512))));
8910 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8911 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008912 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008913
8914 var MSC_ConnHdlr vc_conn2;
8915 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8916 pars2.mscpool.rsl_idx := 1;
8917 /* An NRI of the third MSC's range (512-767) */
8918 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(678))));
8919 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8920 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008921 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008922
8923 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
8924 var MSC_ConnHdlr vc_conn3;
8925 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8926 pars3.mscpool.rsl_idx := 2;
8927 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000013'H)), '00F110'O));
8928 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8929 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008930 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008931 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008932}
8933
8934/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
8935/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8936 * just as well using only RSL. */
8937testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
8938
8939 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8940 f_sleep(1.0);
8941
8942 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
8943 * instead, and hits msc 0. */
8944 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8945
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008946 f_ctrs_msc_init();
8947
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008948 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-bsc.cfg */
8949 var MSC_ConnHdlr vc_conn1;
8950 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8951 pars1.mscpool.rsl_idx := 0;
8952 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(260)), '99F999'O));
8953 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8954 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008955 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008956
8957 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
8958 var MSC_ConnHdlr vc_conn2;
8959 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8960 pars2.mscpool.rsl_idx := 1;
8961 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(555)), '00F110'O));
8962 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8963 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008964 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008965 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008966}
8967
8968/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
8969 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
8970private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
8971 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
8972 //cid_list := { cIl_allInBSS := ''O };
8973 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
8974 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
8975 var BSSAP_N_UNITDATA_req paging;
8976 var hexstring imsi := '001010000000123'H;
8977
8978 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8979
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008980 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008981 valueof(ts_BSSMAP_Paging(imsi, cid_list, omit, bssmap_chneed))));
8982 BSSAP.send(paging);
8983
8984 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
8985 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
8986 * channel number is picked here. */
8987 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
8988 f_rslem_register(0, new_chan_nr);
8989 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(imsi)));
8990 f_rslem_unregister(0, new_chan_nr);
8991
8992 /* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
8993 * causes this Paging Response to go to the first MSC (bssap_idx := 0). */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008994 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV(imsi))) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008995 f_sleep(1.0);
8996}
8997testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
8998 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
8999 f_sleep(1.0);
9000
9001 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9002 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9003 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
9004
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009005 f_ctrs_msc_init();
9006
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009007 var MSC_ConnHdlr vc_conn1;
9008 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9009 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009010 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9011 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009012 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
9013 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009014 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009015 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009016}
9017
9018/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
9019 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9020private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
9021 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9022 //cid_list := { cIl_allInBSS := ''O };
9023 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9024 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9025 var integer nri_v := 300; /* <-- second MSC's NRI */
Harald Weltebf397612021-01-14 20:39:46 +01009026 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009027 var BSSAP_N_UNITDATA_req paging;
9028
9029 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9030
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009031 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009032 valueof(ts_BSSMAP_Paging('001010000000011'H, cid_list, tmsi, bssmap_chneed))));
9033 BSSAP.send(paging);
9034
9035 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9036 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9037 * channel number is picked here. */
9038 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9039 f_rslem_register(0, new_chan_nr);
9040 RSL.receive(tr_RSL_PAGING_CMD(t_MI_TMSI(tmsi)));
9041 f_rslem_unregister(0, new_chan_nr);
9042
9043 /* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
9044 * third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
9045 * the first MSC (bssap_idx := 0). */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009046 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(nri_v))) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009047 f_sleep(1.0);
9048}
9049testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
9050 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9051 f_sleep(1.0);
9052
9053 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9054 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9055 f_vty_transceive(BSCVTY, "mscpool roundrobin next 2");
9056
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009057 f_ctrs_msc_init();
9058
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009059 var MSC_ConnHdlr vc_conn1;
9060 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9061 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009062 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9063 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009064 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
9065 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009066 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009067 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009068}
9069
9070/* For round-robin, skip an MSC that has 'no allow-attach' set. */
9071/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
9072 * just as well using only RSL. */
9073testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
9074
9075 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9076 f_sleep(1.0);
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009077 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9078 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009079
9080 /* Control which MSC gets chosen next by the round-robin, otherwise
9081 * would be randomly affected by which other tests ran before this. */
9082 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9083
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009084 f_ctrs_msc_init();
9085
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009086 var MSC_ConnHdlr vc_conn1;
9087 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9088 pars1.mscpool.rsl_idx := 0;
9089 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9090 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9091 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009092 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009093
9094 var MSC_ConnHdlr vc_conn2;
9095 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9096 pars2.mscpool.rsl_idx := 1;
9097 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9098 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9099 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009100 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009101
9102 var MSC_ConnHdlr vc_conn3;
9103 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
9104 pars3.mscpool.rsl_idx := 2;
9105 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
9106 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9107 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009108 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009109 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009110}
9111
9112/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
9113 * TMSI NRI. */
9114testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
9115
9116 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9117 f_sleep(1.0);
9118
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009119 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9120 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
9121
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009122 /* Control which MSC gets chosen next by the round-robin, otherwise
9123 * would be randomly affected by which other tests ran before this. */
9124 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9125
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009126 f_ctrs_msc_init();
9127
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009128 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
9129 var MSC_ConnHdlr vc_conn1;
9130 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
9131 pars1.mscpool.rsl_idx := 0;
9132 /* An NRI of the second MSC's range (256-511) */
9133 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_TMSI_NRI_LV(260))));
9134 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9135 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009136 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009137
9138 var MSC_ConnHdlr vc_conn2;
9139 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9140 pars2.mscpool.rsl_idx := 1;
9141 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9142 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9143 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009144 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009145
9146 var MSC_ConnHdlr vc_conn3;
9147 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 2);
9148 pars3.mscpool.rsl_idx := 2;
9149 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000003'H))));
9150 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9151 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009152 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009153 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009154}
9155
Philipp Maier783681c2020-07-16 16:47:06 +02009156/* Allow/Deny emergency calls globally via VTY */
9157private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
9158 f_vty_enter_cfg_msc(BSCVTY, 0);
9159 if (allow) {
9160 f_vty_transceive(BSCVTY, "allow-emergency allow");
9161 } else {
9162 f_vty_transceive(BSCVTY, "allow-emergency deny");
9163 }
9164 f_vty_transceive(BSCVTY, "exit");
9165 f_vty_transceive(BSCVTY, "exit");
9166}
9167
9168/* Allow/Deny emergency calls per BTS via VTY */
9169private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
9170 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9171 if (allow) {
9172 f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
9173 } else {
9174 f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
9175 }
9176 f_vty_transceive(BSCVTY, "exit");
9177 f_vty_transceive(BSCVTY, "exit");
Neels Hofmeyrb6ed80c2020-10-12 22:52:39 +00009178 f_vty_transceive(BSCVTY, "exit");
Philipp Maier783681c2020-07-16 16:47:06 +02009179}
9180
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02009181/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
9182private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
9183 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9184 if (allow) {
9185 f_vty_transceive(BSCVTY, "srvcc fast-return allow");
9186 } else {
9187 f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
9188 }
9189 f_vty_transceive(BSCVTY, "exit");
9190 f_vty_transceive(BSCVTY, "exit");
9191 f_vty_transceive(BSCVTY, "exit");
9192}
9193
Pau Espin Pedrol14475352021-07-22 15:48:16 +02009194/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
9195private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
9196 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9197 if (allow) {
9198 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
9199 } else {
9200 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
9201 }
9202 f_vty_transceive(BSCVTY, "exit");
9203 f_vty_transceive(BSCVTY, "exit");
9204 f_vty_transceive(BSCVTY, "exit");
9205}
9206
Pau Espin Pedrol35609792023-01-03 16:56:59 +01009207/* Begin assignment procedure and send an EMERGENCY SETUP (RR) */
Philipp Maier783681c2020-07-16 16:47:06 +02009208private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
9209 var PDU_ML3_MS_NW emerg_setup;
9210 var octetstring emerg_setup_enc;
9211 var RSL_Message emerg_setup_data_ind;
9212
9213 f_establish_fully(omit, omit);
9214
9215 emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
9216 emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
9217 emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
9218
9219 RSL.send(emerg_setup_data_ind);
9220}
9221
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009222/* expect EmergencySetup on BSSAP after calling f_assignment_emerg_setup() */
9223private function f_assignment_emerg_setup_exp_bssap()
9224runs on MSC_ConnHdlr {
Philipp Maier783681c2020-07-16 16:47:06 +02009225 var PDU_BSSAP emerg_setup_data_ind_bssap;
9226 var PDU_ML3_MS_NW emerg_setup;
9227 timer T := 3.0;
9228
Philipp Maier783681c2020-07-16 16:47:06 +02009229 T.start;
9230 alt {
9231 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
9232 emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
9233 if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
9234 setverdict(fail, "no emergency setup");
9235 }
9236 }
9237 [] BSSAP.receive {
9238 setverdict(fail, "unexpected BSSAP message!");
9239 }
9240 [] T.timeout {
9241 setverdict(fail, "timout waiting for EMERGENCY SETUP!");
9242 }
9243 }
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009244}
9245
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009246private function f_assignment_emerg_setup_voice()
9247runs on MSC_ConnHdlr {
9248 /* Go on with voice call assignment */
9249 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
9250 var PDU_BSSAP ass_cmd := f_gen_ass_req();
9251
9252 /* Below speechOrDataIndicator and codecList are copied from an emergency call captured during tests.
9253 * They seem a bit weird (AMR-WB, and the order differ between speechId_DataIndicator and the codecList), but
9254 * seems a good idea to see how osmo-bsc reacts to this. */
9255 ass_cmd.pdu.bssmap.assignmentRequest.channelType := {
9256 elementIdentifier := '0B'O, /* overwritten */
9257 lengthIndicator := 0, /* overwritten */
9258 speechOrDataIndicator := '0001'B, /* speech */
9259 spare1_4 := '0000'B,
9260 channelRateAndType := ChRate_TCHForH_Fpref,
9261 speechId_DataIndicator := 'c2918105'O
9262 };
9263 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({
9264 ts_CodecHR, ts_CodecAMR_WB, ts_CodecEFR, ts_CodecFR}));
9265
9266 f_rslem_dchan_queue_enable();
9267
9268 var ExpectCriteria mgcpcrit := {
9269 connid := omit,
9270 endpoint := omit,
9271 transid := omit
9272 };
9273 f_create_mgcp_expect(mgcpcrit);
9274
9275 BSSAP.send(ass_cmd);
9276
9277 var AssignmentState st := valueof(ts_AssignmentStateInit);
9278 st.voice_call := true;
9279 st.is_assignment := false;
9280 alt {
9281 [] as_modify(st);
9282 [] as_Media();
9283 [st.modify_done] BSSAP.receive(exp_compl) {
9284 setverdict(pass);
9285 }
9286 }
9287
9288 /* Voice call carries on ... */
9289 f_sleep(2.0);
9290}
9291
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009292/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
9293 * CALLS are permitted by the BSC config. */
9294private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
9295
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009296 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
9297 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
9298 * another lchan. */
9299 g_pars.ra := f_rnd_ra_emerg();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009300 f_assignment_emerg_setup();
9301 f_assignment_emerg_setup_exp_bssap();
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009302 f_assignment_emerg_setup_voice();
Philipp Maier783681c2020-07-16 16:47:06 +02009303
9304 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009305 f_perform_clear();
Philipp Maier783681c2020-07-16 16:47:06 +02009306}
9307
9308/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
9309 * forbidden by the BSC config. */
9310private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
9311 var PDU_BSSAP emerg_setup_data_ind_bssap;
9312 timer T := 3.0;
9313
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009314 f_assignment_emerg_setup();
Philipp Maier783681c2020-07-16 16:47:06 +02009315
9316 T.start;
9317 alt {
9318 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
9319 setverdict(pass);
9320 }
9321 [] RSL.receive {
9322 setverdict(fail, "unexpected RSL message!");
9323 }
9324 [] T.timeout {
9325 setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
9326 }
9327 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009328 BSSAP.receive(tr_BSSMAP_ClearRequest);
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01009329 f_perform_clear_no_rr_rel();
Philipp Maier783681c2020-07-16 16:47:06 +02009330}
9331
9332/* EMERGENCY CALL situation #1, allowed globally and by BTS */
9333testcase TC_assignment_emerg_setup_allow() runs on test_CT {
9334 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9335 var MSC_ConnHdlr vc_conn;
9336
9337 f_init(1, true);
9338 f_sleep(1.0);
9339
9340 f_vty_allow_emerg_msc(true);
9341 f_vty_allow_emerg_bts(true, 0);
9342 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9343 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009344 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009345}
9346
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +01009347/* Test MO emergency call using MobileIdentity=IMEI (possible for emergency
9348 * calls from phones without SIM card).
9349 * 3GPP TS 24.008 section 10.5.1.4, OS#5849 */
9350testcase TC_assignment_emerg_setup_allow_imei() runs on test_CT {
9351 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9352 var MSC_ConnHdlr vc_conn;
9353
9354 /* Remove IMSI set by f_gen_test_hdlr_pars(), then IMEI will be used to place the call */
9355 pars.imsi := omit;
9356
9357 f_init(1, true);
9358 f_sleep(1.0);
9359
9360 f_vty_allow_emerg_msc(true);
9361 f_vty_allow_emerg_bts(true, 0);
9362 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9363 vc_conn.done;
9364 f_shutdown_helper();
9365}
9366
Philipp Maier783681c2020-07-16 16:47:06 +02009367/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
9368testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
9369 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9370 var MSC_ConnHdlr vc_conn;
9371
9372 f_init(1, true);
9373 f_sleep(1.0);
9374
9375 f_vty_allow_emerg_msc(false);
9376 f_vty_allow_emerg_bts(true, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009377 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx): */
9378 pars.ra := f_rnd_ra_emerg();
Philipp Maier783681c2020-07-16 16:47:06 +02009379 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9380 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009381 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009382}
9383
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009384/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS.
9385 * The RACH req (and hence CHAN RQD) indicate other than emergency call.
9386 * Hence BSC only learns about it being an emergency call later during call setup.
9387 * If interested in the ra="emergency call" + deny bts policy case,
9388 * see TC_chan_rqd_emerg_deny.
9389 */
Philipp Maier783681c2020-07-16 16:47:06 +02009390testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
9391 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9392 var MSC_ConnHdlr vc_conn;
9393
9394 /* Note: This simulates a spec violation by the MS, correct MS
9395 * implementations would not try to establish an emergency call because
9396 * the system information tells in advance that emergency calls are
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009397 * not allowed */
Philipp Maier783681c2020-07-16 16:47:06 +02009398
9399 f_init(1, true);
9400 f_sleep(1.0);
9401
9402 f_vty_allow_emerg_msc(true);
9403 f_vty_allow_emerg_bts(false, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009404 /* Note: Here we implicitly leave default g_pars.ra which is different than "emergency call" */
Philipp Maier783681c2020-07-16 16:47:06 +02009405 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9406 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009407 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009408}
9409
Philipp Maier82812002020-08-13 18:48:27 +02009410/* Test what happens when an emergency call arrives while all TCH channels are
9411 * busy, the BSC is expected to terminate one call in favor of the incoming
9412 * emergency call */
9413testcase TC_emerg_premption() runs on test_CT {
9414 var ASP_RSL_Unitdata rsl_ud;
9415 var integer i;
9416 var integer chreq_total, chreq_nochan;
9417 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009418 var octetstring l3_payload := gen_l3_valid_payload();
Philipp Maier82812002020-08-13 18:48:27 +02009419
9420 f_init(1);
9421 f_sleep(1.0);
9422
9423 f_vty_allow_emerg_msc(true);
9424 f_vty_allow_emerg_bts(true, 0);
9425
9426 /* Fill up all channels on the BTS */
9427 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
9428 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
9429 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 +02009430 f_chreq_act_ack('33'O, i);
Philipp Maier82812002020-08-13 18:48:27 +02009431 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009432 IPA_RSL[0][0].clear;
Philipp Maier82812002020-08-13 18:48:27 +02009433 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
9434 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
9435
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009436 /* Send EST IND for the first TCH, so we get to test the RR release cause */
9437 var RslChannelNr first_tch := valueof(t_RslChanNr_Bm(1));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009438 f_ipa_tx(ts_RSL_EST_IND(first_tch, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009439
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009440 /* Accept BSSAP conn, so we get to test the Clear Request cause */
9441 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009442 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009443 var integer sccp_conn_id := rx_c_ind.connectionId;
9444 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
9445
Philipp Maier82812002020-08-13 18:48:27 +02009446 /* Send Channel request for emegergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009447 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier82812002020-08-13 18:48:27 +02009448
9449 /* Expect the BSC to release one (the first) TCH/F on the BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009450 f_expect_chan_rel(first_tch, expect_rr_chan_rel := true, expect_rll_rel_req := false,
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009451 expect_rr_cause := GSM48_RR_CAUSE_PREMPTIVE_REL);
Philipp Maier82812002020-08-13 18:48:27 +02009452
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009453 /* Also expect a BSSMAP Clear Request with PREEMPTION */
9454 var BSSAP_N_DATA_ind rx_clear_req;
9455 const myBSSMAP_Cause preemption := GSM0808_CAUSE_PREEMPTION;
9456 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_clear_req;
9457 log("XXX ", rx_clear_req);
9458 if (rx_clear_req.userData.pdu.bssmap.clearRequest.cause.causeValue != int2bit(enum2int(preemption), 7)) {
9459 setverdict(fail, "BSSMAP Clear Request: expected cause PREEMPTION");
9460 }
9461
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009462 /* Expect the BSC to send activate/assign the channel for the emergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009463 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009464 if (first_tch != rx_rsl.ies[0].body.chan_nr) {
9465 setverdict(fail, "different TCH lchan activated than expected");
9466 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009467 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(first_tch, 33));
9468 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Philipp Maier104f4c02020-09-11 18:12:18 +02009469
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009470 /* complete the BSSMAP Clear to satisfy the conn leak check */
9471 BSSAP.send(ts_BSSAP_DATA_req(sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(preemption))));
9472 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearComplete)) {
9473 BSSAP.send(ts_BSSAP_DISC_req(sccp_conn_id, 0));
9474 }
9475
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009476 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009477}
9478
9479/* Hopping parameters per a timeslot */
Vadim Yanitskiybc6654a2020-09-13 01:27:40 +07009480private type record length(0..64) of GsmArfcn ArfcnList;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009481private type record FHParamsTs {
9482 boolean enabled,
9483 uint6_t hsn,
9484 uint6_t maio,
9485 ArfcnList ma
9486};
9487
9488/* Hopping parameters per a transceiver */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009489private type record FHParamsTrx {
Philipp Maier798d8952021-10-19 14:43:19 +02009490 GsmBandArfcn arfcn,
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009491 FHParamsTs ts[8]
9492};
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009493
9494/* Randomly generate the hopping parameters for the given timeslot numbers */
9495private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
9496runs on test_CT return FHParamsTrx {
9497 var FHParamsTrx fhp;
9498
Philipp Maier798d8952021-10-19 14:43:19 +02009499 /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
9500 * fall in the GSM900 band. */
9501 fhp.arfcn.arfcn := f_rnd_int(3);
9502 fhp.arfcn.pcs := false;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009503
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009504 for (var integer tn := 0; tn < 8; tn := tn + 1) {
9505 if (not match(tn, tr_tn)) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009506 fhp.ts[tn].enabled := false;
9507 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009508 continue;
9509 }
9510
9511 /* Random HSN / MAIO values: 0..63 */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009512 fhp.ts[tn].hsn := f_rnd_int(64);
9513 fhp.ts[tn].maio := f_rnd_int(64);
9514 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009515
9516 /* Random Mobile Allocation (hopping channels) */
9517 var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
9518 var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
9519 for (var integer i := 1; i <= ma_len; i := i + 1) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009520 fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009521 }
9522
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009523 fhp.ts[tn].enabled := true;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009524 }
9525
9526 log("f_TC_fh_params_gen(): ", fhp);
9527 return fhp;
9528}
9529
9530/* Make sure that the given Channel Description IE matches the hopping configuration */
9531private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
9532{
9533 var template (present) ChannelDescription tr_cd;
9534 var template (present) MaioHsn tr_maio_hsn;
9535 var uint3_t tn := cd.chan_nr.tn;
9536
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009537 if (fhp.ts[tn].enabled) {
9538 tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009539 tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
9540 } else {
Philipp Maier798d8952021-10-19 14:43:19 +02009541 tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009542 }
9543
9544 if (not match(cd, tr_cd)) {
9545 setverdict(fail, "Channel Description IE does not match: ",
9546 cd, " vs expected ", tr_cd);
9547 }
9548}
9549
9550/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
9551private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
9552 in MobileAllocationLV ma)
9553{
9554 var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
9555
9556 if (not match(ma, tr_ma)) {
9557 setverdict(fail, "Mobile Allocation IE does not match (tn := ",
9558 tn, "): ", ma, " vs expected: ", tr_ma);
9559 } else {
9560 setverdict(pass);
9561 }
9562}
9563
9564private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
9565 in MobileAllocationLV ma)
9566return template MobileAllocationLV {
9567 /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009568 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009569 return { len := 0, ma := ''B };
9570 }
9571
9572 var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
9573 var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
9574 var bitstring ma_mask := ''B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009575
9576 /* Compose the full bit-mask (all channels, up to 1024 entries) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009577 for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
9578 for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
9579 if (full_mask[fhp.ts[i].ma[j]] == '1'B)
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009580 { continue; }
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009581 full_mask[fhp.ts[i].ma[j]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009582 }
9583 }
9584
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009585 /* Take ARFCN of the TRX itself into account */
Philipp Maier798d8952021-10-19 14:43:19 +02009586 full_mask[fhp.arfcn.arfcn] := '1'B;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009587
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009588 /* Compose a bit-mask for the given timeslot number */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009589 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9590 slot_mask[fhp.ts[tn].ma[i]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009591 }
9592
9593 /* Finally, compose the Mobile Allocation bit-mask */
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009594 for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009595 if (full_mask[i] != '1'B)
9596 { continue; }
9597
9598 /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
9599 if (slot_mask[i] == '1'B) {
9600 ma_mask := ma_mask & '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009601 } else {
9602 ma_mask := ma_mask & '0'B;
9603 }
9604 }
9605
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009606 /* ARFCN 0 (if present) goes to the last position of the bit-mask */
9607 if (full_mask[0] == '1'B) {
9608 /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
9609 if (slot_mask[0] == '1'B) {
9610 ma_mask := ma_mask & '1'B;
9611 } else {
9612 ma_mask := ma_mask & '0'B;
9613 }
9614 }
9615
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009616 /* Ensure that ma_mask is octet-aligned */
Vadim Yanitskiy2aa02522020-09-06 14:05:23 +07009617 var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009618 ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
9619
9620 return { len := ma_mask_len, ma := ma_mask };
9621}
9622
Philipp Maier798d8952021-10-19 14:43:19 +02009623/* Configure the appropriate band for a given arfcn, exc */
9624private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
9625{
9626 var charstring band;
9627 var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
9628
9629 select (arfcn_) {
9630 case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
9631 case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
9632 case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
9633 case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
9634 case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
9635 case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
9636 case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
9637 case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
9638 case else { return; }
9639 }
9640
9641 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9642 f_vty_transceive(BSCVTY, "band " & band);
9643 f_vty_transceive(BSCVTY, "end");
9644}
9645
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009646/* Configure the hopping parameters in accordance with the given record */
9647private function f_TC_fh_params_set(in FHParamsTrx fhp,
9648 uint8_t bts_nr := 0,
9649 uint8_t trx_nr := 0)
9650runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009651
9652 f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
9653
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009654 /* Enter the configuration node for the given BTS/TRX numbers */
9655 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9656
Philipp Maier798d8952021-10-19 14:43:19 +02009657 f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009658
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009659 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009660 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9661
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009662 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009663 f_vty_transceive(BSCVTY, "hopping enabled 0");
9664 f_vty_transceive(BSCVTY, "exit"); /* go back */
9665 continue;
9666 }
9667
9668 /* Configure HSN / MAIO values */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009669 f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
9670 f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009671
9672 /* Configure the Mobile Allocation (hopping channels) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009673 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9674 f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009675 }
9676
9677 f_vty_transceive(BSCVTY, "hopping enabled 1");
9678 f_vty_transceive(BSCVTY, "exit"); /* go back */
9679 }
9680
9681 f_vty_transceive(BSCVTY, "end");
9682}
9683
9684/* Disable frequency hopping on all timeslots */
9685private function f_TC_fh_params_unset(in FHParamsTrx fhp,
9686 uint8_t bts_nr := 0,
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009687 uint8_t trx_nr := 0,
Philipp Maier798d8952021-10-19 14:43:19 +02009688 GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009689runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009690
9691 f_TC_set_band_by_arfcn(bts_nr, arfcn);
9692
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009693 /* Enter the configuration node for the given BTS/TRX numbers */
9694 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9695
Philipp Maier798d8952021-10-19 14:43:19 +02009696 f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009697
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009698 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009699 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9700
9701 /* Delete all ARFCNs from the Mobile Allocation (if any) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009702 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9703 f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009704 }
9705
9706 f_vty_transceive(BSCVTY, "hopping enabled 0");
9707 f_vty_transceive(BSCVTY, "exit"); /* go back */
9708 }
9709
9710 f_vty_transceive(BSCVTY, "end");
9711 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9712}
9713
9714/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
9715 * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
9716testcase TC_fh_params_chan_activ() runs on test_CT {
9717 var FHParamsTrx fhp := f_TC_fh_params_gen();
9718 var RSL_Message rsl_msg;
9719 var RSL_IE_Body ie;
9720
9721 f_init_vty();
9722
9723 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9724 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9725
9726 f_init(1);
9727
9728 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9729 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009730 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9731 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009732
9733 /* Make sure that Channel Identification IE is present */
9734 if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
9735 setverdict(fail, "RSL Channel Identification IE is absent");
9736 continue;
9737 }
9738
9739 /* Make sure that hopping parameters (HSN/MAIO) match */
9740 f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
9741
9742 /* "Mobile Allocation shall be included but empty" - let's check this */
9743 if (ie.chan_ident.ma.v.len != 0) {
9744 setverdict(fail, "Mobile Allocation IE is not empty: ",
9745 ie.chan_ident.ma, ", despite it shall be");
9746 continue;
9747 }
9748 }
9749
9750 /* Disable frequency hopping */
9751 f_TC_fh_params_unset(fhp);
9752
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009753 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009754}
9755
9756/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
9757testcase TC_fh_params_imm_ass() runs on test_CT {
9758 var FHParamsTrx fhp := f_TC_fh_params_gen();
9759 var RSL_Message rsl_msg;
9760 var RSL_IE_Body ie;
9761
9762 f_init_vty();
9763
9764 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9765 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9766
9767 f_init(1);
9768
9769 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9770 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009771 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9772 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009773
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009774 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9775 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009776
9777 /* Make sure that Full Immediate Assign Info IE is present */
9778 if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
9779 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
9780 continue;
9781 }
9782
9783 /* Decode the actual Immediate Assignment message */
9784 var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
9785 if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
9786 setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
9787 continue;
9788 }
9789
9790 /* Make sure that hopping parameters (HSN/MAIO) match */
9791 f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
9792
9793 /* Make sure that the Mobile Allocation IE matches */
9794 f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
9795 rr_msg.payload.imm_ass.mobile_allocation);
9796 }
9797
9798 /* Disable frequency hopping */
9799 f_TC_fh_params_unset(fhp);
Philipp Maier82812002020-08-13 18:48:27 +02009800
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009801 f_shutdown_helper();
Philipp Maier82812002020-08-13 18:48:27 +02009802}
9803
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009804/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
9805testcase TC_fh_params_assignment_cmd() runs on test_CT {
9806 var FHParamsTrx fhp := f_TC_fh_params_gen();
9807 var RSL_Message rsl_msg;
9808 var RSL_IE_Body ie;
9809
9810 f_init_vty();
9811
9812 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9813 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9814
9815 f_init(1);
9816
9817 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02009818 vc_MGCP[0].stop;
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009819
9820 var template PDU_BSSAP ass_cmd := f_gen_ass_req();
9821 ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
9822
9823 /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
9824 * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
9825 for (var integer i := 0; i < 3; i := i + 1) {
9826 /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009827 var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009828
9829 /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
9830 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009831 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009832
9833 /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009834 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9835 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009836
9837 /* Make sure that L3 Information IE is present */
9838 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9839 setverdict(fail, "RSL L3 Information IE is absent");
9840 continue;
9841 }
9842
9843 /* Decode the L3 message and make sure it is (RR) Assignment Command */
9844 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9845 if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
9846 setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
9847 continue;
9848 }
9849
9850 /* Make sure that hopping parameters (HSN/MAIO) match */
9851 var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
9852 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9853
9854 /* Make sure that Cell Channel Description IE is present if FH is enabled */
9855 if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
Vadim Yanitskiy38d069d2020-09-02 17:18:57 +07009856 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009857 continue;
9858 }
9859
9860 /* Make sure that the Mobile Allocation IE matches (if present) */
9861 var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
9862 if (chan_desc.h and ma_present) {
9863 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9864 l3_msg.payload.ass_cmd.mobile_allocation.v);
9865 } else if (chan_desc.h and not ma_present) {
9866 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9867 continue;
9868 } else if (not chan_desc.h and ma_present) {
9869 setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
9870 continue;
9871 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009872
9873 f_perform_clear_test_ct(dt);
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009874 }
9875
9876 /* Give the IUT some time to release all channels */
9877 f_sleep(3.0);
9878
9879 /* Disable frequency hopping */
9880 f_TC_fh_params_unset(fhp);
9881
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009882 f_shutdown_helper();
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009883}
9884
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009885/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
9886private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
9887runs on test_CT {
9888 var RSL_Message rsl_msg;
9889 var RSL_IE_Body ie;
9890 var DchanTuple dt;
9891
9892 /* Establish a dedicated channel, so we can trigger handover */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009893 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyc18ff472021-11-18 20:15:37 +03009894 f_sleep(0.5);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009895
9896 /* Trigger handover from BTS0 to BTS1 */
9897 f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
9898 f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
9899
9900 /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009901 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx := {1, 0});
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009902
9903 /* ACKnowledge channel activation and expect (RR) Handover Command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009904 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33), idx := {1, 0});
9905 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009906
9907 /* Make sure that L3 Information IE is present */
9908 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9909 setverdict(fail, "RSL L3 Information IE is absent");
9910 return;
9911 }
9912
9913 /* Decode the L3 message and make sure it is (RR) Handover Command */
9914 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9915 if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
9916 setverdict(fail, "Failed to match Handover Command: ", l3_msg);
9917 return;
9918 }
9919
9920 /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
9921 var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
9922 if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
9923 setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
9924 return;
9925 }
9926
9927 /* Make sure that hopping parameters (HSN/MAIO) match */
9928 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9929
9930 /* Make sure that Cell Channel Description IE is present */
9931 if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
9932 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
9933 return;
9934 }
9935
9936 /* Make sure that the Mobile Allocation (after time) IE is present and matches */
9937 var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
9938 if (ma_present) {
9939 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9940 l3_msg.payload.ho_cmd.mobile_allocation.v);
9941 } else {
9942 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9943 return;
9944 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009945
9946 f_perform_clear_test_ct(dt);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009947}
9948testcase TC_fh_params_handover_cmd() runs on test_CT {
9949 var FHParamsTrx fhp := f_TC_fh_params_gen();
9950
9951 f_init_vty();
9952
9953 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
9954 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
9955
9956 f_vty_transceive(BSCVTY, "timeslot 0");
9957 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
9958 f_vty_transceive(BSCVTY, "exit"); /* go back */
9959
9960 f_vty_transceive(BSCVTY, "timeslot 1");
9961 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
9962 f_vty_transceive(BSCVTY, "end"); /* we're done */
9963
9964 f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
9965 f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
9966
9967 f_init(2);
9968
9969 f_TC_fh_params_handover_cmd(fhp);
9970
9971 /* Disable frequency hopping on BTS1 */
9972 f_TC_fh_params_unset(fhp, 1);
9973
9974 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
9975 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
9976
9977 f_vty_transceive(BSCVTY, "timeslot 0");
9978 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
9979 f_vty_transceive(BSCVTY, "exit"); /* go back */
9980
9981 f_vty_transceive(BSCVTY, "timeslot 1");
9982 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
9983 f_vty_transceive(BSCVTY, "end"); /* we're done */
9984
9985 f_shutdown_helper();
9986}
9987
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009988/* Verify the hopping parameters in System Information Type 4 */
9989testcase TC_fh_params_si4_cbch() runs on test_CT {
9990 var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
9991 var ASP_RSL_Unitdata rx_rsl_ud;
9992 timer T := 5.0;
9993
9994 f_init_vty();
9995
9996 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
9997 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
9998
9999 f_vty_transceive(BSCVTY, "timeslot 0");
10000 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10001 f_vty_transceive(BSCVTY, "exit"); /* go back */
10002
10003 f_vty_transceive(BSCVTY, "timeslot 1");
10004 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
10005 f_vty_transceive(BSCVTY, "end"); /* we're done */
10006
10007 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
10008 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10009
10010 f_init(1);
10011
10012 T.start;
10013 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010014 [] 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 +070010015 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
10016 var SystemInformation si := dec_SystemInformation(ie.other.payload);
10017
10018 /* Make sure that what we decoded is System Information Type 4 */
10019 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
10020 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
10021 repeat;
10022 }
10023
10024 /* Make sure that CBCH Channel Description IE is present */
10025 if (not ispresent(si.payload.si4.cbch_chan_desc)) {
10026 setverdict(fail, "CBCH Channel Description IE is absent");
10027 break;
10028 }
10029
10030 /* Finally, check the hopping parameters (HSN, MAIO) */
10031 var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
10032 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10033
10034 /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
10035 * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
10036 if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
10037 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10038 break;
10039 } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
10040 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10041 si.payload.si4.cbch_mobile_alloc.v);
10042 }
10043 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010044 [] IPA_RSL[0][0].receive { repeat; }
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010045 [] T.timeout {
10046 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
10047 }
10048 }
10049
10050 /* Disable frequency hopping */
10051 f_TC_fh_params_unset(fhp);
10052
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010053 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010054 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10055
10056 f_vty_transceive(BSCVTY, "timeslot 0");
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010057 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010058 f_vty_transceive(BSCVTY, "exit"); /* go back */
10059
10060 f_vty_transceive(BSCVTY, "timeslot 1");
10061 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10062 f_vty_transceive(BSCVTY, "end"); /* we're done */
10063
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010064 f_shutdown_helper();
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010065}
10066
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010067template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
10068 := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
10069
10070private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
10071 template (present) BSSLAP_PDU expect_bsslap)
10072{
10073 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
10074 if (not match(bsslap, expect_bsslap)) {
10075 log("EXPECTING BSSLAP: ", expect_bsslap);
10076 log("GOT BSSLAP: ", bsslap);
10077 setverdict(fail, "BSSLAP is not as expected");
10078 mtc.stop;
10079 }
10080 setverdict(pass);
10081}
10082
10083/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
10084const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
10085
10086private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
10087 var PDU_BSSAP_LE rx_bsslap;
10088 BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
10089 f_match_bsslap(rx_bsslap, expect_rx_bsslap);
10090}
10091
10092/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10093 * Request on Lb interface. Either with or without the SMLC doing a BSSLAP TA Request. */
10094private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
10095 f_sleep(1.0);
10096
10097 f_establish_fully(omit, omit);
10098 f_bssap_le_register_imsi(g_pars.imsi, omit);
10099
10100 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10101 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10102
10103 var PDU_BSSAP_LE plr;
10104 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10105
10106 if (not do_ta_request) {
10107 /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
10108 var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
10109 if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
10110 log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
10111 log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
10112 setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
10113 mtc.stop;
10114 }
10115 var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
10116 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
10117 if (not match(bsslap, expect_ta_layer3)) {
10118 log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
10119 log("GOT BSSLAP: ", bsslap);
10120 setverdict(fail, "BSSLAP is not as expected");
10121 mtc.stop;
10122 }
10123 /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
10124 * has no need to request the TA from the BSC and directly responds. */
10125 } else {
10126 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10127 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10128 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10129 }
10130
10131 /* SMLC got the TA from the BSC, now responds with geo information data. */
10132 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10133 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10134 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10135
10136 /* The LCS was using an active A-interface conn. It should still remain active after this. */
10137 f_mo_l3_transceive();
10138
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010139 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010140
10141 f_sleep(2.0);
10142 setverdict(pass);
10143}
10144
10145/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10146 * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
10147private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
10148 f_lcs_loc_req_for_active_ms(false);
10149}
10150testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
10151 var MSC_ConnHdlr vc_conn;
10152 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10153
10154 f_init(1, true);
10155 f_sleep(1.0);
10156 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
10157 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010158 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010159}
10160
10161/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10162 * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
10163private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
10164 f_lcs_loc_req_for_active_ms(true);
10165}
10166testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
10167 var MSC_ConnHdlr vc_conn;
10168 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10169
10170 f_init(1, true);
10171 f_sleep(1.0);
10172 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
10173 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010174 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010175}
10176
10177/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
10178 * conn without an active lchan. */
10179private function f_clear_A_conn() runs on MSC_ConnHdlr
10180{
10181 var BssmapCause cause := 0;
10182 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10183 BSSAP.receive(tr_BSSMAP_ClearComplete);
10184 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10185
10186 timer no_more_bssap := 5.0;
10187 no_more_bssap.start;
10188 alt {
10189 [] no_more_bssap.timeout { break; }
10190 [] BSSAP.receive(tr_BSSAP_BSSMAP) {
10191 setverdict(fail, "Expected no more BSSAP after Clear Complete");
10192 mtc.stop;
10193 }
10194 }
10195 setverdict(pass);
10196}
10197
10198/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
10199 * for LCS, for cases where there is only an A conn without an active lchan. */
10200private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
10201{
10202 f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
10203
10204 /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
10205 * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
10206 * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
10207 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10208 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10209 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10210
10211 /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
10212 f_clear_A_conn();
10213 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10214 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10215}
10216
10217/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10218 * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
10219 */
10220private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
10221 f_sleep(1.0);
10222
10223 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10224 f_bssap_le_register_imsi(g_pars.imsi, omit);
10225
10226 /* Register to receive the Paging Command */
10227 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10228 g_chan_nr := new_chan_nr;
10229 f_rslem_register(0, g_chan_nr);
10230
10231 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10232 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10233 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10234 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10235
10236 var PDU_BSSAP_LE plr;
10237 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10238
10239 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10240 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10241
10242 /* OsmoBSC needs to Page */
10243 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
10244 f_logp(BSCVTY, "got Paging Command");
10245
10246 /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
10247 * the MSC, and releases the lchan directly. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010248 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV(g_pars.imsi))), do_clear := false, expect_bssmap_l3 := false);
10249 f_expect_lchan_rel(RSL, RSL_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010250
10251 /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
10252
10253 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10254
10255 /* SMLC got the TA from the BSC, now responds with geo information data. */
10256 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10257 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10258
10259 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10260
10261 /* The lchan is gone, the A-interface conn was created for the LCS only.
10262 * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
10263 f_verify_active_A_conn_and_clear();
10264
10265 f_sleep(2.0);
10266 setverdict(pass);
10267}
10268testcase TC_lcs_loc_req_for_idle_ms() runs on test_CT {
10269 var MSC_ConnHdlr vc_conn;
10270 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10271
10272 f_init(1, true);
10273 f_sleep(1.0);
10274
10275 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10276 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10277
10278 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
10279 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010280 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010281}
10282
10283/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
10284 */
10285private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
10286 f_sleep(1.0);
10287
10288 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10289 f_bssap_le_register_imsi(g_pars.imsi, omit);
10290
10291 /* provoke an abort by omitting both IMSI and IMEI */
10292 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10293 valueof(ts_BSSMAP_Perform_Location_Request(omit,
10294 ts_CellId_CGI('262'H, '42'H, 23, 42)))));
10295 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10296
10297 /* BSC tells MSC about failure */
10298 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10299 locationEstimate := omit, positioningData := omit,
10300 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
10301
10302 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10303 f_verify_active_A_conn_and_clear();
10304
10305 f_sleep(2.0);
10306 setverdict(pass);
10307}
10308testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
10309 var MSC_ConnHdlr vc_conn;
10310 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10311
10312 f_init(1, true);
10313 f_sleep(1.0);
10314
10315 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10316 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10317
10318 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
10319 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010320 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010321}
10322
10323/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10324 * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
10325private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
10326 f_sleep(1.0);
10327
10328 f_establish_fully(omit, omit);
10329 f_bssap_le_register_imsi(g_pars.imsi, omit);
10330
10331 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10332 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10333
10334 var PDU_BSSAP_LE plr;
10335 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10336
10337 if (do_ta) {
10338 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10339 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10340 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10341 }
10342
10343 /* SMLC fails to respond, BSC runs into timeout */
10344 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
10345 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10346
10347 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10348 locationEstimate := omit, positioningData := omit,
10349 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
10350
10351 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10352 f_verify_active_A_conn_and_clear();
10353
10354 f_sleep(2.0);
10355 setverdict(pass);
10356}
10357
10358/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10359 * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
10360private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
10361 f_lcs_loc_req_for_active_ms_le_timeout(false);
10362}
10363
10364testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
10365 var MSC_ConnHdlr vc_conn;
10366 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10367
10368 f_init(1, true);
10369 f_sleep(1.0);
10370 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
10371 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010372 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010373}
10374
10375/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10376 * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
10377private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
10378 f_lcs_loc_req_for_active_ms_le_timeout(true);
10379}
10380
10381testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
10382 var MSC_ConnHdlr vc_conn;
10383 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10384
10385 f_init(1, true);
10386 f_sleep(1.0);
10387 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
10388 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010389 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010390}
10391
10392/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
10393private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
10394 f_sleep(1.0);
10395
10396 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10397 f_bssap_le_register_imsi(g_pars.imsi, omit);
10398
10399 /* Register to receive the Paging Command */
10400 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10401 g_chan_nr := new_chan_nr;
10402 f_rslem_register(0, g_chan_nr);
10403
10404 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10405 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10406 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10407 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10408
10409 var PDU_BSSAP_LE plr;
10410 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10411
10412 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10413 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10414
10415 /* OsmoBSC needs to Page */
10416 var PDU_BSSAP_LE rx_bsslap;
10417 alt {
10418 [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
10419 f_logp(BSCVTY, "got Paging Command");
10420 repeat;
10421 }
10422 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10423 /* MS does not respond to Paging, TA Req runs into timeout. */
10424 f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
10425 }
10426 }
10427
10428 /* SMLC responds with failure */
10429 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10430 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10431
10432 /* BSC tells MSC about failure */
10433 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10434 locationEstimate := omit, positioningData := omit,
10435 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
10436
10437 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10438 f_verify_active_A_conn_and_clear();
10439
10440 f_sleep(2.0);
10441 setverdict(pass);
10442}
10443testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
10444 var MSC_ConnHdlr vc_conn;
10445 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10446
10447 f_init(1, true);
10448 f_sleep(1.0);
10449
10450 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10451 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10452
10453 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
10454 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010455 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010456}
10457
10458/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
10459 * over. */
10460private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10461 f_sleep(1.0);
10462
10463 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10464 f_bssap_le_register_imsi(g_pars.imsi, omit);
10465
10466 /* Register to receive the Paging Command */
10467 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10468 g_chan_nr := new_chan_nr;
10469 f_rslem_register(0, g_chan_nr);
10470
10471 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10472 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10473 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10474 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10475
10476 var PDU_BSSAP_LE plr;
10477 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10478
10479 /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
10480 * and establish Layer 3. It should use the existing A-interface conn. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010481 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 +020010482 do_clear := false, expect_bssmap_l3 := true);
10483
10484 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10485 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10486
10487 /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
10488 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10489
10490 /* SMLC got the TA from the BSC, now responds with geo information data. */
10491 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10492 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10493 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10494
10495 /* The lchan should still exist, it was from a CM Service Request. */
10496 f_mo_l3_transceive();
10497
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010498 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010499
10500 f_sleep(2.0);
10501 setverdict(pass);
10502}
10503testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
10504 var MSC_ConnHdlr vc_conn;
10505 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10506
10507 f_init(1, true);
10508 f_sleep(1.0);
10509
10510 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10511 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10512
10513 vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
10514 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010515 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010516}
10517
10518/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
10519 * the new lchan after handover. */
10520private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10521 f_sleep(1.0);
10522
10523 f_establish_fully(omit, omit);
10524 f_bssap_le_register_imsi(g_pars.imsi, omit);
10525
10526 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10527 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10528
10529 var PDU_BSSAP_LE plr;
10530 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10531
10532 /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
10533 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
10534
10535 var HandoverState hs := {
10536 rr_ho_cmpl_seen := false,
10537 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +020010538 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010539 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010540 };
10541 /* issue hand-over command on VTY */
10542 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
10543 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
10544 f_rslem_suspend(RSL1_PROC);
10545
10546 /* From the MGW perspective, a handover is is characterized by
10547 * performing one MDCX operation with the MGW. So we expect to see
10548 * one more MDCX during handover. */
10549 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
10550
10551 alt {
10552 [] as_handover(hs);
10553 }
10554
10555 var PDU_BSSAP_LE rx_bsslap;
10556
10557 interleave {
10558 /* Expect the BSC to inform the MSC about the handover */
10559 [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
10560
10561 /* Expect the BSC to inform the SMLC about the handover */
10562 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10563 f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
10564 }
10565 }
10566
10567 /* SMLC now responds with geo information data. */
10568 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10569 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10570 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10571
10572 /* lchan still active */
10573 f_mo_l3_transceive(RSL1);
10574
10575 /* MSC decides it is done now. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010576 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010577
10578 f_sleep(2.0);
10579 setverdict(pass);
10580}
10581testcase TC_ho_during_lcs_loc_req() runs on test_CT {
10582 var MSC_ConnHdlr vc_conn;
10583 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10584
10585 f_init(2, true);
10586 f_sleep(1.0);
10587 vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
10588 vc_conn.done;
Oliver Smith39f53072022-10-27 14:44:04 +020010589 f_shutdown_helper(ho := true);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010590}
10591
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010592private function f_tc_emerg_call_and_lcs_loc_req(charstring id) runs on MSC_ConnHdlr
10593{
10594 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
10595 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
10596 * another lchan. */
Pau Espin Pedrol1809bce2023-01-03 16:54:41 +010010597 g_pars.ra := f_rnd_ra_emerg();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010598 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010599 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010600
10601 /* Here would usually be a CC Call Proceeding from the MSC, but what does the BSC care about DTAP. */
10602
10603 /* Do a Location Request in-between the CC call setup */
10604 f_bssap_le_register_imsi(g_pars.imsi, omit);
10605 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10606 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10607 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10608 /* SMLC got the TA from the BSC, now responds with geo information data. */
10609 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10610 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10611 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10612
Pau Espin Pedrol14076d32023-01-03 17:07:59 +010010613 f_assignment_emerg_setup_voice();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010614
10615 setverdict(pass);
10616 f_perform_clear();
10617}
10618
10619testcase TC_emerg_call_and_lcs_loc_req() runs on test_CT {
10620 var MSC_ConnHdlr vc_conn;
10621 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10622
10623 f_init(1, true);
10624 f_sleep(1.0);
10625 f_vty_allow_emerg_msc(true);
10626 f_vty_allow_emerg_bts(true, 0);
10627 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req), pars);
10628 vc_conn.done;
10629 f_shutdown_helper();
10630}
10631
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010632private altstep no_bssmap_clear_req() runs on MSC_ConnHdlr {
10633 [] BSSAP.receive(tr_BSSMAP_ClearRequest) {
10634 setverdict(fail, "unexpected BSSMAP Clear Request");
10635 mtc.stop;
10636 }
10637}
10638
10639private type enumerated RslRel {
10640 RSLREL_REL_IND,
10641 RSLREL_CONN_FAIL
10642};
10643
10644private function f_emerg_call_and_lcs_loc_req_early_lchan_release(RslRel rsl_rel) runs on MSC_ConnHdlr
10645{
10646 g_pars.ra := f_rnd_ra_emerg();
10647 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010648 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010649
10650 /* Start a Location Request to locate the emergency */
10651 f_bssap_le_register_imsi(g_pars.imsi, omit);
10652 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10653 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10654 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10655
10656 /* 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
10657 * do a Clear Command when the Location Response arrives. */
10658 activate(no_bssmap_clear_req());
10659
10660 /* the lchan gets interrupted while the Location Request has no response */
10661 select (rsl_rel) {
10662 case (RSLREL_REL_IND) {
10663 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
10664 f_expect_lchan_rel(RSL, RSL_PROC);
10665 }
10666 case (RSLREL_CONN_FAIL) {
10667 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
10668 }
10669 case else {
10670 setverdict(fail, "Unknown RslRel type");
10671 mtc.stop;
10672 }
10673 }
10674
10675 /* Still expect the Location Response to find its way to the MSC. */
10676 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10677 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10678 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10679
10680 setverdict(pass);
10681
10682 select (rsl_rel) {
10683 case (RSLREL_REL_IND) {
10684 f_perform_clear_no_lchan();
10685 }
10686 case (RSLREL_CONN_FAIL) {
10687 f_perform_clear();
10688 }
10689 }
10690}
10691
10692private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind(charstring id) runs on MSC_ConnHdlr
10693{
10694 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_REL_IND);
10695}
10696
10697testcase TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() runs on test_CT {
10698 var MSC_ConnHdlr vc_conn;
10699 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10700
10701 f_init(1, true);
10702 f_sleep(1.0);
10703 f_vty_allow_emerg_msc(true);
10704 f_vty_allow_emerg_bts(true, 0);
10705 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind), pars);
10706 vc_conn.done;
10707 f_shutdown_helper();
10708}
10709
10710private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail(charstring id) runs on MSC_ConnHdlr
10711{
10712 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_CONN_FAIL);
10713}
10714
10715testcase TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() runs on test_CT {
10716 var MSC_ConnHdlr vc_conn;
10717 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10718
10719 f_init(1, true);
10720 f_sleep(1.0);
10721 f_vty_allow_emerg_msc(true);
10722 f_vty_allow_emerg_bts(true, 0);
10723 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail), pars);
10724 vc_conn.done;
10725 f_shutdown_helper();
10726}
10727
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010728/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
10729private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
10730 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10731
10732 /* Also disable attach for the single connected MSC */
10733 f_vty_msc_allow_attach(BSCVTY, { false });
10734
10735 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) ));
10736 f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
10737
10738 /* No MSC is found, expecting a proper release on RSL */
10739 interleave {
10740 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
10741 f_logp(BSCVTY, "Got RSL RR Release");
10742 }
10743 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10744 f_logp(BSCVTY, "Got RSL Deact SACCH");
10745 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010746 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010747 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
10748 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010749 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010750 }
10751 }
10752 setverdict(pass);
10753}
10754testcase TC_no_msc() runs on test_CT {
10755
10756 f_init(1, true);
10757 f_sleep(1.0);
10758 var MSC_ConnHdlr vc_conn;
10759 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10760
10761 f_ctrs_bsc_init(counternames_bsc_mscpool);
10762
10763 vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
10764 vc_conn.done;
10765
10766 f_ctrs_bsc_add("mscpool:subscr:no_msc");
10767 f_ctrs_bsc_verify();
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010768 f_shutdown_helper();
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010769}
10770
Harald Welte0ea2d5e2018-04-07 21:40:29 +020010771/* Dyn PDCH todo:
10772 * activate OSMO as TCH/F
10773 * activate OSMO as TCH/H
10774 * does the BSC-located PCU socket get the updated INFO?
10775 * what if no PCU is connected at the time?
10776 * is the info correct on delayed PCU (re)connect?
10777 */
Harald Welte94e0c342018-04-07 11:33:23 +020010778
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010779private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +020010780 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020010781 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010782
10783 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
10784 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10785 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
10786 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
10787 g_pars.ass_codec_list.codecElements[0];
10788 if (isvalue(g_pars.expect_mr_s0_s7)) {
10789 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
10790 g_pars.expect_mr_s0_s7;
10791 }
10792 }
10793 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
10794 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
10795 log("expecting ASS COMPL like this: ", exp_compl);
10796
10797 f_establish_fully(ass_cmd, exp_compl);
10798
Neels Hofmeyr8746b0d2021-06-01 17:25:39 +020010799 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 +000010800
10801 var RSL_Message rsl;
10802
10803 timer T := 5.0;
10804 T.start;
10805 alt {
10806 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
10807 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
10808 log("Rx L3 from net: ", l3);
10809 if (ischosen(l3.msgs.rrm.channelModeModify)) {
10810 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10811 mtc.stop;
10812 }
10813 }
10814 [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
10815 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10816 mtc.stop;
10817 }
10818 [] T.timeout {
10819 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
10820 setverdict(pass);
10821 }
10822 }
10823 T.stop;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010824
10825 f_perform_clear();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010826}
10827
10828/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
10829 * osmo-bsc. */
10830testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
10831 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10832 var MSC_ConnHdlr vc_conn;
10833
10834 f_init(1, true);
10835 f_sleep(1.0);
10836
10837 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10838 vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
10839 vc_conn.done;
10840 f_shutdown_helper();
10841}
10842
10843/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
10844 */
10845testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
10846 f_init_vty();
10847
10848 f_init(1, false);
10849 f_sleep(1.0);
10850
10851 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
10852
10853 var ASP_RSL_Unitdata rx_rsl_ud;
10854 timer T := 5.0;
10855
10856 T.start;
10857 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010858 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010859 if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
10860 T.stop;
10861 setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
10862 mtc.stop;
10863 }
10864 repeat;
10865 }
10866 [] T.timeout {
10867 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
10868 setverdict(pass);
10869 }
10870 }
10871}
10872
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010873private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
10874 /* First fully set up a speech lchan */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010875 f_assignment_codec(id, do_perform_clear := false);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010876
10877 /* Trigger re-assignment to another lchan */
10878 var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
10879
10880 /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
10881 * one MDCX on MGCP. */
10882 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
10883
10884 /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
10885 * as the old lchan used. */
10886 g_media.bts.ipa_crcx_seen := false;
10887 g_media.bts.ipa_mdcx_seen := false;
10888
10889 /* Send different BTS side RTP port number for the new lchan */
10890 g_media.bts.bts.port_nr := 4223;
10891
10892 f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
10893
10894 /* Trigger re-assignment. */
10895 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
10896
10897 timer T := 5.0;
10898 T.start;
10899 alt {
10900 [] as_assignment(assignment_st);
10901 [] as_Media();
10902 [] T.timeout {
10903 break;
10904 }
10905 }
10906
10907 if (not assignment_st.assignment_done) {
10908 setverdict(fail, "Assignment did not complete");
10909 mtc.stop;
10910 }
10911
10912 f_check_mgcp_expectations()
10913 setverdict(pass);
10914
10915 f_sleep(2.0);
10916 log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
10917
10918 /* Instruct BSC to clear channel */
10919 var BssmapCause cause := 0;
10920 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10921 interleave {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010922 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
10923 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010924 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010925 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010926 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010927 }
10928 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
10929 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10930 }
10931 }
Neels Hofmeyr40a45d12021-09-23 22:57:12 +020010932 f_expect_dlcx_conns();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010933
10934 f_sleep(0.5);
10935}
10936
10937testcase TC_reassignment_fr() runs on test_CT {
10938 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10939 var MSC_ConnHdlr vc_conn;
10940
10941 f_init(1, true);
10942 f_sleep(1.0);
10943
Neels Hofmeyrac432fa2021-11-02 16:45:56 +010010944 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010945
10946 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10947 vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
10948 vc_conn.done;
10949
10950 /* from f_establish_fully() */
10951 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
10952 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
10953 /* from re-assignment */
10954 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
10955 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
10956 f_ctrs_bsc_and_bts_verify();
10957 f_shutdown_helper();
10958}
10959
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010960const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
10961const charstring REEST_CLEAR := "REEST_CLEAR";
10962const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
10963
10964/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
10965 * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
10966 * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
10967 * the MSC as the CM Re-Establishment is handled.
10968 *
10969 * MS bts0 bts1 bsc msc test-component
10970 * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
10971 * | | _1 wait a bit, to settle down
10972 * |<-x x--| | _1 "lose connection"
10973 * | | REEST_LOST_CONNECTION
10974 * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
10975 * | | REEST_CLEAR
10976 * | |<-0---| _1 Clear Command on first A-conn
10977 * | |--0-->| _1 Clear Complete
10978 * | |<----------------->| | _1 Release first channel
10979 * | | REEST_CLEAR_DONE
10980 * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
10981 * |<-----------------|<-------|<-1---| _2 Clear Command, Release
10982 *
10983 */
10984private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
10985 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
10986 var PDU_BSSAP ass_cmd := f_gen_ass_req();
10987
10988 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
10989 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10990
10991 f_establish_fully(ass_cmd, exp_compl);
10992
10993 /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
10994 * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
10995 * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
10996 f_sleep(2.0);
10997 COORD.send(REEST_LOST_CONNECTION);
10998
10999 alt {
11000 [] COORD.receive(REEST_CLEAR);
11001 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
11002 setverdict(fail, "Unexpected channel release");
11003 mtc.stop;
11004 }
11005 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
11006 setverdict(fail, "Unexpected channel release");
11007 mtc.stop;
11008 }
11009 }
11010 f_perform_clear()
Neels Hofmeyr969abd02021-09-23 22:24:08 +020011011 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011012 COORD.send(REEST_CLEAR_DONE);
11013}
11014
11015private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
11016 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
11017
11018 /* The MS lost the connection on the first channel, now establishes another one */
11019 COORD.receive(REEST_LOST_CONNECTION);
11020
11021 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
11022 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
11023 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
11024
11025 f_create_bssmap_exp(l3_enc);
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011026 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 +020011027 BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
11028
11029 /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
11030 COORD.send(REEST_CLEAR);
11031 COORD.receive(REEST_CLEAR_DONE);
11032
11033 f_sleep(2.0);
11034
11035 /* Answer the CM Re-Establishment with an Assignment Command. */
11036 var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
11037 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11038 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11039 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11040
11041 var AssignmentState st := valueof(ts_AssignmentStateInit);
11042 st.voice_call := true;
11043 st.is_assignment := true;
11044
11045 var ExpectCriteria mgcpcrit := {
11046 connid := omit,
11047 endpoint := omit,
11048 transid := omit
11049 };
11050 f_create_mgcp_expect(mgcpcrit);
11051
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011052 f_rslem_dchan_queue_enable(RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011053
11054 BSSAP.send(ass_cmd);
11055
11056 var PDU_BSSAP bssap;
11057
11058 alt {
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011059 [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
11060 [] as_Media_ipacc(RSL1, RSL2);
11061 [] as_Media_mgw();
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011062 [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
11063 break;
11064 }
11065 }
11066
11067 f_sleep(3.0);
11068
11069 f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011070 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011071}
11072
11073testcase TC_cm_reestablishment() runs on test_CT {
11074 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
11075 var MSC_ConnHdlr vc_conn1;
11076
11077 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
11078 var MSC_ConnHdlr vc_conn2;
11079 pars2.imsi := pars1.imsi;
11080 pars2.media_nr := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011081 pars2.expect_tsc := c_BtsParams[1].tsc;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011082
11083 f_init(2, true, guard_timeout := 40.0);
11084 f_sleep(1.0);
11085
11086 vc_conn1 := f_start_handler_create(pars1);
11087 vc_conn2 := f_start_handler_create(pars2);
11088 connect(vc_conn1:COORD, vc_conn2:COORD);
11089 f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
11090 f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
11091 vc_conn1.done;
11092 vc_conn2.done;
11093
11094 f_shutdown_helper();
11095}
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011096
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011097function f_exp_ipa_rx_nonfatal(template (present) RSL_Message t_rx,
11098 boolean ignore_other_rx := true,
11099 BtsTrxIdx idx := {0, 0},
11100 float Tval := 2.0)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011101runs on test_CT return template (omit) RSL_Message {
11102 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011103 timer T := Tval;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011104
11105 T.start;
11106 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011107 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011108 T.stop;
11109 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011110 [ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
11111 [not ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011112 log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
11113 T.stop;
11114 return omit;
11115 }
11116 [] T.timeout {
11117 return omit;
11118 }
11119 }
11120 return rx_rsl_ud.rsl;
11121}
11122
11123private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
11124 f_vty_enter_cfg_bts(pt, bts_nr);
11125 f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
11126 f_vty_transceive(pt, "exit");
11127 f_vty_transceive(pt, "exit");
11128 f_vty_transceive(pt, "exit");
11129}
11130
11131private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +030011132 template (present) RslChannelNr chan_nr := ?,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011133 template (present) uint12_t arfcn := ?,
11134 template (present) uint3_t tsc := ?)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011135{
11136 var RSL_IE_Body full_imm_ass_info;
11137 if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
11138 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
11139 mtc.stop;
11140 }
11141
11142 var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
11143 var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
11144 fn := fn,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011145 ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011146 page_mode := ?);
11147 if (not match(rr_imm_ass, expect_imm_ass)) {
11148 log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
11149 setverdict(fail, "Failed to match Immediate Assignment");
11150 mtc.stop;
11151 }
11152}
11153
11154testcase TC_imm_ass_post_chan_ack() runs on test_CT {
11155 var RSL_Message chan_act;
11156 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011157 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011158
11159 f_init(1, false);
11160 f_sleep(1.0);
11161
11162 /* (should be the default anyway, just to make things clear) */
11163 f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
11164
11165 /* RA containing reason=LU */
11166 var GsmFrameNumber fn := 2342;
11167 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011168 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011169
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011170 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011171
11172 /* First send the Chan Act ACK */
11173 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011174 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011175 var RSL_IE_Body chan_ident_ie;
11176 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11177 setverdict(fail, "RSL Channel Identification IE is absent");
11178 mtc.stop;
11179 }
11180
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011181 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011182
11183 /* Then expect the Immediate Assignment, after we ACKed the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011184 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011185
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011186 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11187 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011188
11189 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011190 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011191
11192 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011193 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011194 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011195 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11196
11197 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011198 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011199 f_shutdown_helper();
11200}
11201
11202testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
11203 var RSL_Message chan_act;
11204 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011205 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011206
11207 f_init(1, false);
11208 f_sleep(1.0);
11209
11210 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11211
11212 /* RA containing reason=LU */
11213 var GsmFrameNumber fn := 2342;
11214 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011215 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011216
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011217 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011218 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011219 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011220 var RSL_IE_Body chan_ident_ie;
11221 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11222 setverdict(fail, "RSL Channel Identification IE is absent");
11223 mtc.stop;
11224 }
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011225
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011226 /* (set bts 0 cfg back to default) */
11227 f_vty_set_imm_ass(BSCVTY);
11228
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011229 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011230 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011231 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11232 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011233
11234 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011235 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011236
11237 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011238 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011239
11240 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011241 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011242 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011243 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11244
11245 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011246 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011247 f_shutdown_helper();
11248}
11249
Neels Hofmeyr23158742021-09-07 19:08:07 +020011250testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
11251 var RSL_Message chan_act;
11252 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011253 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr23158742021-09-07 19:08:07 +020011254
11255 f_init(1, false);
11256 f_sleep(1.0);
11257
11258 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11259
11260 /* RA containing reason=LU */
11261 var GsmFrameNumber fn := 2342;
11262 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011263 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011264
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011265 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011266 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011267 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr23158742021-09-07 19:08:07 +020011268 var RSL_IE_Body chan_ident_ie;
11269 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11270 setverdict(fail, "RSL Channel Identification IE is absent");
11271 mtc.stop;
11272 }
11273
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011274 /* (set bts 0 cfg back to default) */
11275 f_vty_set_imm_ass(BSCVTY);
11276
Neels Hofmeyr23158742021-09-07 19:08:07 +020011277 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011278 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011279 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11280 chan_ident_ie.chan_ident.ch_desc.v.tsc);
11281
11282 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011283 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011284
11285 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011286 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011287
11288 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011289 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011290 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr23158742021-09-07 19:08:07 +020011291 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11292
11293 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011294 f_perform_clear_test_ct(dt);
Neels Hofmeyr23158742021-09-07 19:08:07 +020011295 f_shutdown_helper();
11296}
11297
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011298testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
11299 /* change Timeslot 6 before f_init() starts RSL */
11300 f_init_vty();
11301 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11302 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11303
11304 f_init(1, false);
11305 f_sleep(1.0);
11306
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011307 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011308 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11309 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011310 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11311 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011312
11313 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11314 f_ts_set_chcomb(0, 0, 6, "PDCH");
11315
11316 /* block all static timeslots so that the dyn TS will be used */
11317 f_disable_all_tch_f();
11318 f_disable_all_tch_h();
11319 f_disable_all_sdcch();
11320
11321 var RSL_Message chan_act;
11322 var RSL_Message imm_ass;
11323
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011324 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11325
11326 /* RA containing reason=LU */
11327 var GsmFrameNumber fn := 2342;
11328 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011329 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011330
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011331 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011332 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
11333 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011334
11335 /* Now activation as SDCCH8 */
11336 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011337 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011338
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011339 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011340 var RSL_IE_Body chan_ident_ie;
11341 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11342 setverdict(fail, "RSL Channel Identification IE is absent");
11343 mtc.stop;
11344 }
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011345
11346 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011347 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011348 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11349 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011350
11351 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011352 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011353
11354 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011355 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011356
11357 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011358 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011359 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011360 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11361
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011362 /* (set bts 0 cfg back to default) */
11363 f_vty_set_imm_ass(BSCVTY);
11364
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011365 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011366 f_perform_clear_test_ct(dt);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011367 f_shutdown_helper();
11368}
11369
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011370testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
11371 /* change Timeslot 6 before f_init() starts RSL */
11372 f_init_vty();
11373 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11374 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11375
11376 f_init(1, false);
11377 f_sleep(1.0);
11378
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011379 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011380 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11381 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011382 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11383 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011384
11385 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11386 f_ts_set_chcomb(0, 0, 6, "PDCH");
11387
11388 /* block all static timeslots so that the dyn TS will be used */
11389 f_disable_all_tch_f();
11390 f_disable_all_tch_h();
11391 f_disable_all_sdcch();
11392
11393 var RSL_Message chan_act;
11394 var RSL_Message imm_ass;
11395
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011396 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11397
11398 /* RA containing reason=LU */
11399 var GsmFrameNumber fn := 2342;
11400 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011401 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011402
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011403 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011404 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011405
11406 /* And already the Immediate Assignment even before the PDCH Deact ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011407 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011408
11409 /* continue the Osmo style PDCH Deact (usual chan rel) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011410 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011411
11412 /* Now activation as SDCCH8 */
11413 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011414 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011415
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011416 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011417 var RSL_IE_Body chan_ident_ie;
11418 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11419 setverdict(fail, "RSL Channel Identification IE is absent");
11420 mtc.stop;
11421 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011422 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011423
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011424 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11425 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011426
11427 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011428 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011429
11430 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011431 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011432 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011433 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11434
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011435 /* (set bts 0 cfg back to default) */
11436 f_vty_set_imm_ass(BSCVTY);
11437
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011438 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011439 f_perform_clear_test_ct(dt);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011440 f_shutdown_helper();
11441}
11442
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011443/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
11444testcase TC_ctrl_trx_rf_locked() runs on test_CT {
11445 var MSC_ConnHdlr vc_conn;
11446
11447 f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
11448 f_sleep(1.0);
11449
11450 /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
11451 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11452 "0,0,operational,unlocked,on,rsl-up;" &
11453 "1,0,operational,unlocked,on,rsl-up;" &
11454 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011455 "2,1,operational,unlocked,on,rsl-down;" &
11456 "2,2,operational,unlocked,on,rsl-down;" &
11457 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011458 "3,0,inoperational,locked,on,rsl-down;");
11459
11460 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock BTS 1 TRX 0");
11461 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11462 /* give it a moment to settle the FSM status */
11463 f_sleep(1.0);
11464
11465 /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
11466 * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
11467 * of "off"? But that's for a future patch if at all. */
11468 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11469 "0,0,operational,unlocked,on,rsl-up;" &
11470 "1,0,operational,locked,on,rsl-up;" &
11471 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011472 "2,1,operational,unlocked,on,rsl-down;" &
11473 "2,2,operational,unlocked,on,rsl-down;" &
11474 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011475 "3,0,inoperational,locked,on,rsl-down;");
11476
11477 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
11478 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11479 f_sleep(1.0);
11480 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11481 "0,0,operational,unlocked,on,rsl-up;" &
11482 "1,0,operational,locked,on,rsl-up;" &
11483 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011484 "2,1,operational,unlocked,on,rsl-down;" &
11485 "2,2,operational,unlocked,on,rsl-down;" &
11486 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011487 "3,0,inoperational,locked,on,rsl-down;");
11488
11489 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
11490 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
11491 f_sleep(1.0);
11492 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11493 "0,0,operational,unlocked,on,rsl-up;" &
11494 "1,0,operational,unlocked,on,rsl-up;" &
11495 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011496 "2,1,operational,unlocked,on,rsl-down;" &
11497 "2,2,operational,unlocked,on,rsl-down;" &
11498 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011499 "3,0,inoperational,locked,on,rsl-down;");
11500
11501 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
11502 f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
11503 f_sleep(1.0);
11504 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11505 "0,0,operational,unlocked,on,rsl-up;" &
11506 "1,0,operational,unlocked,on,rsl-up;" &
11507 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011508 "2,1,operational,unlocked,on,rsl-down;" &
11509 "2,2,operational,unlocked,on,rsl-down;" &
11510 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011511 "3,0,inoperational,locked,on,rsl-down;");
11512
11513 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
11514 f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
11515 f_sleep(1.0);
11516 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11517 "0,0,operational,unlocked,on,rsl-up;" &
11518 "1,0,operational,unlocked,on,rsl-up;" &
11519 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011520 "2,1,operational,unlocked,on,rsl-down;" &
11521 "2,2,operational,unlocked,on,rsl-down;" &
11522 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011523 "3,0,inoperational,locked,on,rsl-down;");
11524
11525 f_shutdown_helper();
11526}
11527
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011528const CounterNameVals counternames_cm_serv_rej := {
11529 { "cm_serv_rej", 0 },
11530 { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
11531 { "cm_serv_rej:illegal_ms", 0 },
11532 { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
11533 { "cm_serv_rej:imei_not_accepted", 0 },
11534 { "cm_serv_rej:illegal_me", 0 },
11535 { "cm_serv_rej:plmn_not_allowed", 0 },
11536 { "cm_serv_rej:loc_not_allowed", 0 },
11537 { "cm_serv_rej:roaming_not_allowed", 0 },
11538 { "cm_serv_rej:network_failure", 0 },
11539 { "cm_serv_rej:synch_failure", 0 },
11540 { "cm_serv_rej:congestion", 0 },
11541 { "cm_serv_rej:srv_opt_not_supported", 0 },
11542 { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
11543 { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
11544 { "cm_serv_rej:call_can_not_be_identified", 0 },
11545 { "cm_serv_rej:incorrect_message", 0 },
11546 { "cm_serv_rej:invalid_mandantory_inf", 0 },
11547 { "cm_serv_rej:msg_type_not_implemented", 0 },
11548 { "cm_serv_rej:msg_type_not_compatible", 0 },
11549 { "cm_serv_rej:inf_eleme_not_implemented", 0 },
11550 { "cm_serv_rej:condtional_ie_error", 0 },
11551 { "cm_serv_rej:msg_not_compatible", 0 },
11552 { "cm_serv_rej:protocol_error", 0 },
11553 { "cm_serv_rej:retry_in_new_cell", 0 }
11554};
11555
11556private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
11557{
11558 f_create_chan_and_exp();
Vadim Yanitskiya7fc5a62021-12-04 20:10:08 +030011559 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011560 BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011561 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_CM_SERV_REJ));
11562 f_perform_clear();
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011563 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011564}
11565testcase TC_cm_serv_rej() runs on test_CT {
11566 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11567 var MSC_ConnHdlr vc_conn;
11568
11569 f_init(1, true);
11570 f_sleep(1.0);
11571
11572 f_ctrs_bts_init(1, counternames_cm_serv_rej);
11573
11574 vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
11575 vc_conn.done;
11576
11577 f_ctrs_bts_add(0, "cm_serv_rej", 1);
11578 f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
11579 f_ctrs_bts_verify();
11580
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011581 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011582 f_shutdown_helper();
11583}
11584
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011585/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
11586 * Activ Ack (SYS#5627). */
11587private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
11588 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Vadim Yanitskiyf0310e32021-10-26 00:30:59 +030011589
11590 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11591 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011592
11593 var BSSMAP_FIELD_CodecType codecType;
11594 codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
11595
11596 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
11597
11598 /* First establish a signalling lchan */
11599 f_create_chan_and_exp();
11600 f_rslem_dchan_queue_enable();
11601
11602 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011603
11604 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
Oliver Smith735b47c2023-02-15 16:03:54 +010011605 activate(as_Media_mgw());
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011606
11607 var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
11608 f_rslem_register(0, chan_nr);
11609
11610 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
11611 BSSAP.send(ass_cmd);
11612
11613
11614 /* Wait for the Channel Activ for the TCH channel */
11615 var ASP_RSL_Unitdata rx_rsl_ud;
11616 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
11617
11618 /* make the original SDCCH disappear */
11619 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
11620
11621 /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
11622 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
11623
11624 interleave {
11625 [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
11626 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
11627 }
11628
11629 BSSAP.send(ts_BSSMAP_ClearCommand(0));
11630 BSSAP.receive(tr_BSSMAP_ClearComplete);
11631 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11632
11633 var MgcpCommand mgcp;
Vadim Yanitskiy6be4cf42022-06-04 21:25:47 +060011634 var MGCP_RecvFrom mrf;
11635 var template MgcpMessage msg_dlcx := { command := tr_DLCX };
11636 alt {
11637 [g_pars.aoip] MGCP.receive(tr_DLCX) -> value mgcp {
11638 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
11639 }
11640 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
11641 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
11642 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
11643 }));
11644 }
11645 }
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011646
11647 f_sleep(0.5);
11648}
11649testcase TC_lost_sdcch_during_assignment() runs on test_CT {
11650 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11651 var MSC_ConnHdlr vc_conn;
11652
Oliver Smith735b47c2023-02-15 16:03:54 +010011653 pars.fail_on_dlcx := false;
11654
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011655 f_init(1, true);
11656 f_sleep(1.0);
11657
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011658 vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
11659 vc_conn.done;
11660
11661 f_shutdown_helper();
11662}
11663
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011664const CounterNameVals counternames_bsc_bts_all_available_allocated := {
11665 { "all_allocated:sdcch", 0 },
11666 { "all_allocated:static_sdcch", 0 },
11667 { "all_allocated:tch", 0 },
11668 { "all_allocated:static_tch", 0 }
11669}
11670
11671private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
11672{
11673 /* Make sure counters settle first */
11674 f_sleep(1.0);
11675
11676 /* Take a baseline of counters */
11677 f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
11678
11679 /* Elapse some time so that we see changes in counters, hopefully where expected */
11680 f_sleep(2.0);
11681
11682 /* Get new counters */
11683 var charstring_list all_changed := {};
11684 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
11685 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
11686
11687 /* Compare with expectations */
11688 var charstring_list all_expect_changed := {};
11689 for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
11690 all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
11691 }
11692 f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
11693}
11694
11695testcase TC_ratectr_all_available_allocated() runs on test_CT {
11696 var ASP_RSL_Unitdata rsl_ud;
11697 var integer i;
11698 var integer chreq_total, chreq_nochan;
11699
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011700 f_init(1, guard_timeout := 60.0);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011701 f_sleep(1.0);
11702
11703 /* Exhaust all dedicated SDCCH lchans.
11704 /* GSM 44.018 Table 9.1.8.2:
11705 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11706 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011707 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011708 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011709 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 +020011710 }
11711
11712 /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
11713 * level.
11714 * All SDCCH are now occupied. */
11715 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11716
11717 /* Also fill up all remaining (TCH) channels */
11718 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011719 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 +020011720 }
11721
11722 /* All TCH are now also occupied */
11723 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11724 "all_allocated:tch", "all_allocated:static_tch"});
11725
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011726 /* Clean up SDCCH lchans */
11727 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11728 f_perform_clear_test_ct(chan_cleanup[i]);
11729 }
11730
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011731 f_shutdown_helper();
11732}
11733
11734testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
11735 var ASP_RSL_Unitdata rsl_ud;
11736 var integer i;
11737 var integer chreq_total, chreq_nochan;
11738
11739 f_init_vty();
11740 f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
11741 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11742 /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
11743
11744 f_init(1, guard_timeout := 60.0);
11745 f_sleep(1.0);
11746
11747 /* The dyn TS wants to activate PDCH mode, ACK that. */
11748 var RslChannelNr chan_nr;
11749 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011750 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11751 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011752
11753 /* Exhaust all dedicated SDCCH lchans.
11754 /* GSM 44.018 Table 9.1.8.2:
11755 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11756 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011757 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011758 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011759 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 +020011760 }
11761
11762 /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
11763 * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
11764 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
11765
11766 /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
11767 * Will release them later, so remember all the DchanTuples. */
11768 var DchanTuples dyn_sddch := {};
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011769 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 +020011770
11771 /* Also occupy the seven other SDCCH of the dyn TS */
11772 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011773 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 +020011774 }
11775
11776 /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
11777 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11778
11779 /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
11780 for (i := 0; i < 5; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011781 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 +020011782 }
11783
11784 /* All TCH lchans are now also occupied, both static and dynamic */
11785 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11786 "all_allocated:tch", "all_allocated:static_tch"});
11787
11788 /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
11789 * incrementing. */
11790 var BssmapCause cause := 0;
11791 var DchanTuple dt := dyn_sddch[0];
11792 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011793 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011794
11795 /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
11796 * count as occupied, so those still both increment. */
11797 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
11798 "all_allocated:tch", "all_allocated:static_tch"});
11799
11800 /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
11801 for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
11802 dt := dyn_sddch[i];
11803 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011804 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011805 }
11806
11807 /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
11808 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011809 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11810 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011811
11812 /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
11813 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
11814
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011815 /* Clean up SDCCH lchans */
11816 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11817 f_perform_clear_test_ct(chan_cleanup[i]);
11818 }
11819
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011820 /* clean up config */
11821 f_ts_reset_chcomb(0);
11822
11823 f_shutdown_helper();
11824}
11825
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011826private function f_TC_chan_alloc_algo(DchanTuple dt, BtsTrxIdx idx)
11827runs on test_CT {
11828 /* MSC sends an Assignment Request */
11829 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11830 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11831 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11832 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
11833
11834 /* Expect the BSC to allocate a TCH channel on the given BTS/TRX */
11835 var RSL_Message rsl_chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
11836 /* Send CHAN ACT NACK, so that the requested TCH channel becomes BORKEN */
11837 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(rsl_chan_act.ies[0].body.chan_nr, RSL_ERR_EQUIPMENT_FAIL), idx);
11838 /* Expect to receive an Assignment Failure */
11839 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail));
11840}
11841
11842testcase TC_chan_alloc_algo_ascending() runs on test_CT {
11843 /* We need to access BTS2, which has 4 TRXs */
11844 f_init(nr_bts := 3);
11845
11846 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020011847 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011848
11849 f_vty_enter_cfg_bts(BSCVTY, 2);
11850 f_vty_transceive(BSCVTY, "channel allocator ascending");
11851 f_vty_transceive(BSCVTY, "end");
11852
11853 /* Expect the BSC to allocate 4 x TCH/F channels on BTS2/TRX0 */
11854 for (var integer i := 0; i < 4; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011855 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011856 f_TC_chan_alloc_algo(dt, {2, 0});
11857 f_perform_clear_test_ct(dt);
11858 }
11859
11860 /* At this point all 4 x TCH/F channels are BORKEN, but they will be
11861 * resurrected upon the A-bis/OML link re-establishment. */
11862 f_shutdown_helper();
11863}
11864
11865testcase TC_chan_alloc_algo_descending() runs on test_CT {
11866 /* We need to access BTS2, which has 4 TRXs */
11867 f_init(nr_bts := 3);
11868
11869 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020011870 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011871
11872 f_vty_enter_cfg_bts(BSCVTY, 2);
11873 f_vty_transceive(BSCVTY, "channel allocator descending");
11874 f_vty_transceive(BSCVTY, "end");
11875
11876 /* Expect the BSC to allocate 5 x TCH/F channels on BTS2/TRX3 */
11877 for (var integer i := 0; i < 5; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011878 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011879 f_TC_chan_alloc_algo(dt, {2, 3});
11880 f_perform_clear_test_ct(dt);
11881 }
11882
11883 /* At this point all 5 x TCH/F channels are BORKEN, but they will be
11884 * resurrected upon the A-bis/OML link re-establishment. */
11885 f_shutdown_helper();
11886}
11887
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011888testcase TC_chan_alloc_algo_ass_dynamic() runs on test_CT {
11889 const BtsTrxIdx TRX0 := {2, 0};
11890 const BtsTrxIdx TRX3 := {2, 3};
11891
11892 /* We need to access BTS2, which has 4 TRXs */
11893 f_init(nr_bts := 3);
11894
11895 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020011896 vc_MGCP[0].stop;
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011897
11898 f_vty_enter_cfg_bts(BSCVTY, 2);
11899 f_vty_transceive(BSCVTY, "channel allocator mode assignment dynamic");
11900 f_vty_transceive(BSCVTY, "channel allocator dynamic-param ul-rxlev thresh 50 avg-num 2");
11901 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 0");
11902 f_vty_transceive(BSCVTY, "end");
11903
11904 var DchanTuple dt;
11905
11906 f_logp(BSCVTY, "Case a) Unknown Uplink RxLev, fall-back to ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011907 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011908 f_TC_chan_alloc_algo(dt, TRX0);
11909 f_perform_clear_test_ct(dt);
11910
11911 f_logp(BSCVTY, "Case b) Not enough RxLev samples, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011912 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011913 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11914 ts_RSL_IE_UplinkMeas(30, 0),
11915 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011916 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011917 f_TC_chan_alloc_algo(dt, TRX0);
11918 f_perform_clear_test_ct(dt);
11919
11920 f_logp(BSCVTY, "Case c) Uplink RxLev below the threshold, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011921 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011922 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11923 ts_RSL_IE_UplinkMeas(45, 0),
11924 ts_RSL_IE_BS_Power(0)), TRX0);
11925 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
11926 ts_RSL_IE_UplinkMeas(48, 0),
11927 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011928 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011929 f_TC_chan_alloc_algo(dt, TRX0);
11930 f_perform_clear_test_ct(dt);
11931
11932 f_logp(BSCVTY, "Case d) Uplink RxLev above the threshold, use descending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011933 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011934 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11935 ts_RSL_IE_UplinkMeas(50, 0),
11936 ts_RSL_IE_BS_Power(0)), TRX0);
11937 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
11938 ts_RSL_IE_UplinkMeas(58, 0),
11939 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011940 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011941 f_TC_chan_alloc_algo(dt, TRX3);
11942 f_perform_clear_test_ct(dt);
11943
11944 f_vty_enter_cfg_bts(BSCVTY, 2);
11945 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 90");
11946 f_vty_transceive(BSCVTY, "end");
11947
11948 f_logp(BSCVTY, "Case e) Uplink RxLev above the threshold, but C0 load is not");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011949 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011950 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11951 ts_RSL_IE_UplinkMeas(50, 0),
11952 ts_RSL_IE_BS_Power(0)), TRX0);
11953 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
11954 ts_RSL_IE_UplinkMeas(58, 0),
11955 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011956 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011957 f_TC_chan_alloc_algo(dt, TRX0);
11958 f_perform_clear_test_ct(dt);
11959
11960 f_vty_enter_cfg_bts(BSCVTY, 2);
11961 f_vty_transceive(BSCVTY, "channel allocator ascending");
11962 f_vty_transceive(BSCVTY, "end");
11963
11964 /* At this point some TCH/F channels are BORKEN, but they will be
11965 * resurrected upon the A-bis/OML link re-establishment. */
11966 f_shutdown_helper();
11967}
11968
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020011969private function f_vty_mgw_enable(integer mgw_nr := 1) runs on test_CT {
11970 var rof_charstring cmds := {
11971 "remote-ip " & mp_test_ip,
11972 "remote-port " & int2str(2427 + mgw_nr)
11973 };
11974 f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
11975 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " reconnect")
11976}
11977private function f_vty_mgw_disable(integer mgw_nr := 1) runs on test_CT {
11978 f_vty_config3(BSCVTY, {"network"}, { "no mgw " &int2str(mgw_nr) });
11979}
11980private function f_vty_mgw_block(integer mgw_nr := 1, boolean blocked := true) runs on test_CT {
11981 var charstring arg;
11982 if (blocked) {
11983 arg := "block";
11984 } else {
11985 arg := "unblock";
11986 }
11987 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " " & arg);
11988}
11989private const charstring COORD_CMD_ESTABLISHED := "COORD_CMD_ESTABLISHED";
11990private function f_TC_mgwpool_call_seq_1(charstring id) runs on MSC_ConnHdlr {
11991 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
11992 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11993 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11994 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11995
11996 f_establish_fully(ass_cmd, exp_compl);
11997 COORD.send(COORD_CMD_ESTABLISHED);
11998
11999 COORD.receive(COORD_CMD_ESTABLISHED);
12000 f_perform_clear()
12001 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12002}
12003private function f_TC_mgwpool_call_seq_2(charstring id) runs on MSC_ConnHdlr {
12004 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12005 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12006 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12007 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12008
12009
12010 COORD.receive(COORD_CMD_ESTABLISHED);
12011 f_establish_fully(ass_cmd, exp_compl);
12012 COORD.send(COORD_CMD_ESTABLISHED);
12013
12014 f_perform_clear()
12015 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12016}
12017/* Test load is spread around 2 available MGWs */
12018testcase TC_mgwpool_all_used() runs on test_CT {
12019 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12020 var MSC_ConnHdlr vc_conn1;
12021 pars1.mgwpool_idx := 0;
12022
12023 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12024 var MSC_ConnHdlr vc_conn2;
12025 pars2.mgwpool_idx := 1;
12026
12027 f_init(1, true, nr_mgw := 2);
12028 f_sleep(1.0);
12029
12030 f_vty_mgw_enable(1);
12031
12032 vc_conn1 := f_start_handler_create(pars1);
12033 vc_conn2 := f_start_handler_create(pars2);
12034 connect(vc_conn1:COORD, vc_conn2:COORD);
12035 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12036 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12037 vc_conn1.done;
12038 vc_conn2.done;
12039
12040 f_vty_mgw_disable(1);
12041
12042 f_shutdown_helper();
12043}
12044
12045/* Test blocked MGW in the pool are not selected */
12046testcase TC_mgwpool_blocked_not_used() runs on test_CT {
12047 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12048 var MSC_ConnHdlr vc_conn1;
12049 pars1.mgwpool_idx := 0;
12050
12051 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12052 var MSC_ConnHdlr vc_conn2;
12053 pars2.mgwpool_idx := 0; /* expect it in the first one, since the second will be blocked */
12054 pars2.media_nr := 2;
12055
12056 f_init(1, true, nr_mgw := 2);
12057 f_sleep(1.0);
12058
12059 f_vty_mgw_enable(1);
12060 f_vty_mgw_block(1, true);
12061
12062 vc_conn1 := f_start_handler_create(pars1);
12063 vc_conn2 := f_start_handler_create(pars2);
12064 connect(vc_conn1:COORD, vc_conn2:COORD);
12065 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12066 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12067 vc_conn1.done;
12068 vc_conn2.done;
12069
12070 f_vty_mgw_disable(1);
12071
12072 f_shutdown_helper();
12073}
12074
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012075/* Test BTS pinning to an MGW is applied */
12076testcase TC_mgwpool_pin_bts() runs on test_CT {
12077 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12078 var MSC_ConnHdlr vc_conn1;
12079 pars1.mgwpool_idx := 0;
12080
12081 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12082 var MSC_ConnHdlr vc_conn2;
12083 pars2.mgwpool_idx := 0; /* expect it in the first one, since the BTS is pinned to the first MGW */
12084 pars2.media_nr := 2;
12085
12086 f_init(1, true, nr_mgw := 2);
12087 f_sleep(1.0);
12088
12089 f_vty_mgw_enable(1);
12090 f_vty_cfg_bts(BSCVTY, 0, { "mgw pool-target 0" });
12091
12092 vc_conn1 := f_start_handler_create(pars1);
12093 vc_conn2 := f_start_handler_create(pars2);
12094 connect(vc_conn1:COORD, vc_conn2:COORD);
12095 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12096 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12097 vc_conn1.done;
12098 vc_conn2.done;
12099
12100 f_vty_cfg_bts(BSCVTY, 0, { "no mgw pool-target" } );
Vadim Yanitskiy389d7e02022-10-25 17:44:05 +070012101 f_vty_mgw_disable(1);
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012102
12103 f_shutdown_helper();
12104}
12105
Oliver Smithc9a5f532022-10-21 11:32:23 +020012106private function f_tc_ho_meas_rep_multi_band(charstring id) runs on MSC_ConnHdlr {
12107 g_pars := f_gen_test_hdlr_pars();
12108 var PDU_BSSAP ass_req := f_gen_ass_req();
12109 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12110 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12111 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12112 f_establish_fully(ass_req, exp_compl);
12113
12114 /* Send a measurement report with bad rxlev except on 3rd entry. The
12115 * measurement report is divided into two sub lists, as described in
12116 * 3GPP TS 04.08 § 10.5.2.20. */
12117 var NcellReports neighbor_rep := {
12118 /* Sub list 1: same band */
Oliver Smitha6773042022-10-24 12:56:30 +020012119 { rxlev := 0, bcch_freq := 0, bsic := 12 }, /* ARFCN 800, band 1800, LAC 98 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012120 /* Sub list 2: different band */
Oliver Smitha6773042022-10-24 12:56:30 +020012121 { rxlev := 0, bcch_freq := 1, bsic := 13 }, /* ARFCN 200, band 850, LAC 97 */
12122 { rxlev := 40, bcch_freq := 2, bsic := 14 }, /* ARFCN 1000, band 900, LAC 99 */
12123 { rxlev := 0, bcch_freq := 3, bsic := 11 } /* ARFCN 0, band 900, LAC 96 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012124 };
12125 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
12126 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
12127 l3_mr, 0));
12128
12129 /* Expect a handover to the third entry. If the BSC parsed the report
Oliver Smitha6773042022-10-24 12:56:30 +020012130 * correctly, the third entry has LAC 99. */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012131 var template BSSMAP_FIELD_CellIdentificationList cid_list := {
Oliver Smitha6773042022-10-24 12:56:30 +020012132 cIl_LAC := { ts_BSSMAP_CI_LAC(99) }
Oliver Smithc9a5f532022-10-21 11:32:23 +020012133 };
12134 alt {
12135 [] BSSAP.receive(tr_BSSMAP_HandoverRequired(cid_list := cid_list)) {
12136 setverdict(pass);
12137 }
12138 [] BSSAP.receive(tr_BSSMAP_HandoverRequired()) {
12139 setverdict(fail, "Handover has unexpected LAC in Cell Identification List. The BSC probably"
12140 & " didn't parse the multi-band measurement report correctly.");
12141 }
12142 }
12143
12144 f_ho_out_of_this_bsc(skip_meas_rep := true);
12145}
12146testcase TC_ho_meas_rep_multi_band() runs on test_CT {
12147 /* Verify that the BSC parses the measurement report correctly when
12148 * neighbors in multiple bands are configured (OS#5717). See
12149 * gsm_arfcn2band_rc() in libosmocore src/gsm/gsm_utils.c for the
12150 * ARFCN -> band mapping. The MS is connected to band 1800. */
12151 var MSC_ConnHdlr vc_conn;
12152
12153 f_init_vty();
12154 f_bts_0_cfg(BSCVTY,
12155 {"neighbor-list mode automatic",
12156 "handover 1",
12157 "handover algorithm 2",
12158 "handover2 window rxlev averaging 1",
12159 "no neighbors",
12160 "neighbor lac 99 arfcn 1000 bsic any", /* band 900 */
12161 "neighbor lac 98 arfcn 800 bsic any", /* band 1800 */
12162 "neighbor lac 97 arfcn 200 bsic any", /* band 850 */
Oliver Smitha6773042022-10-24 12:56:30 +020012163 "neighbor lac 96 arfcn 0 bsic any"}); /* band 900 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012164 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
12165
12166 f_init(1, true);
12167 f_sleep(1.0);
12168
12169 f_ctrs_bsc_and_bts_handover_init();
12170
12171 vc_conn := f_start_handler(refers(f_tc_ho_meas_rep_multi_band));
12172 vc_conn.done;
12173
12174 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
12175 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
12176 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
12177 f_ctrs_bsc_and_bts_add(0, "handover:completed");
12178 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
12179 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
12180 f_ctrs_bsc_and_bts_verify();
12181 f_shutdown_helper(ho := true);
12182}
12183
Harald Welte28d943e2017-11-25 15:00:50 +010012184control {
Harald Welte898113b2018-01-31 18:32:21 +010012185 /* CTRL interface testing */
Harald Welte4003d112017-12-09 22:35:39 +010012186 execute( TC_ctrl_msc_connection_status() );
Stefan Sperlingb041b3d2018-01-03 17:14:55 +010012187 execute( TC_ctrl_msc0_connection_status() );
Neels Hofmeyrf65ce872021-09-23 18:40:10 +020012188 /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
12189 * these in the AoIP test suite. */
12190 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12191 execute( TC_stat_num_msc_connected_1() );
12192 execute( TC_stat_num_msc_connected_2() );
12193 execute( TC_stat_num_msc_connected_3() );
12194 }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020012195 execute( TC_stat_num_bts_connected_1() );
12196 execute( TC_stat_num_bts_connected_2() );
12197 execute( TC_stat_num_bts_connected_3() );
Harald Welte96c94412017-12-09 03:12:45 +010012198 execute( TC_ctrl() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012199 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +020012200 execute( TC_ctrl_location() );
12201 }
Harald Welte898113b2018-01-31 18:32:21 +010012202
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012203 execute( TC_si_default() );
Neels Hofmeyr66aeba42020-07-06 02:21:21 +020012204 execute( TC_si2quater_2_earfcns() );
12205 execute( TC_si2quater_3_earfcns() );
12206 execute( TC_si2quater_4_earfcns() );
12207 execute( TC_si2quater_5_earfcns() );
12208 execute( TC_si2quater_6_earfcns() );
Neels Hofmeyrad132f22020-07-08 02:20:16 +020012209 execute( TC_si2quater_12_earfcns() );
12210 execute( TC_si2quater_23_earfcns() );
12211 execute( TC_si2quater_32_earfcns() );
12212 execute( TC_si2quater_33_earfcns() );
12213 execute( TC_si2quater_42_earfcns() );
12214 execute( TC_si2quater_48_earfcns() );
12215 execute( TC_si2quater_49_earfcns() );
Pau Espin Pedrol85a84432020-07-20 18:45:03 +020012216 execute( TC_si_acc_rotate() );
Alexander Couzens4ad3a352020-09-10 22:29:12 +020012217 execute( TC_si_acc_ramp_rotate() );
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012218
Harald Welte898113b2018-01-31 18:32:21 +010012219 /* RSL DCHAN Channel ACtivation / Deactivation */
Harald Welteae026692017-12-09 01:03:01 +010012220 execute( TC_chan_act_noreply() );
Harald Welte4003d112017-12-09 22:35:39 +010012221 execute( TC_chan_act_counter() );
Harald Welteae026692017-12-09 01:03:01 +010012222 execute( TC_chan_act_ack_noest() );
Philipp Maier9c60a622020-07-09 15:08:46 +020012223 execute( TC_chan_act_ack_noest_emerg() );
Philipp Maier606f07d2020-08-12 17:21:58 +020012224 execute( TC_chan_rqd_emerg_deny() );
Harald Welteae026692017-12-09 01:03:01 +010012225 execute( TC_chan_act_ack_est_ind_noreply() );
12226 execute( TC_chan_act_ack_est_ind_refused() );
Harald Welte618ef642017-12-14 14:58:20 +010012227 execute( TC_chan_act_nack() );
Harald Welte799c97b2017-12-14 17:50:30 +010012228 execute( TC_chan_exhaustion() );
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +070012229 execute( TC_chan_deact_silence() );
Harald Welte4003d112017-12-09 22:35:39 +010012230 execute( TC_chan_rel_rll_rel_ind() );
12231 execute( TC_chan_rel_conn_fail() );
12232 execute( TC_chan_rel_hard_clear() );
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +020012233 execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
12234 execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
Harald Welte99787102019-02-04 10:41:36 +010012235 execute( TC_chan_rel_hard_clear_csfb() );
Harald Welted8c36cd2017-12-09 23:05:31 +010012236 execute( TC_chan_rel_hard_rlsd() );
Harald Welte550daf92018-06-11 19:22:13 +020012237 execute( TC_chan_rel_hard_rlsd_ms_dead() );
Harald Welte85804d42017-12-10 14:11:58 +010012238 execute( TC_chan_rel_a_reset() );
Pau Espin Pedrolc675b612020-01-09 19:55:40 +010012239 execute( TC_chan_rel_sccp_tiar_timeout() );
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +020012240 execute( TC_chan_rel_rr_cause() );
Harald Welte6f521d82017-12-11 19:52:02 +010012241
Harald Weltecfe2c962017-12-15 12:09:32 +010012242 execute( TC_outbound_connect() );
Harald Welte898113b2018-01-31 18:32:21 +010012243
12244 /* Assignment related */
Harald Welte16a4adf2017-12-14 18:54:01 +010012245 execute( TC_assignment_cic_only() );
Harald Welte235ebf12017-12-15 14:18:16 +010012246 execute( TC_assignment_csd() );
12247 execute( TC_assignment_ctm() );
12248 execute( TC_assignment_sign() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012249 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12250 execute( TC_assignment_aoip_tla_v6() );
12251 }
Harald Welte235ebf12017-12-15 14:18:16 +010012252 execute( TC_assignment_fr_a5_0() );
12253 execute( TC_assignment_fr_a5_1() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012254 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte8f67d1d2018-05-25 20:38:42 +020012255 execute( TC_assignment_fr_a5_1_codec_missing() );
12256 }
Harald Welte235ebf12017-12-15 14:18:16 +010012257 execute( TC_assignment_fr_a5_3() );
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +020012258 execute( TC_assignment_fr_a5_4() );
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +020012259 execute( TC_assignment_fr_a5_4_fail() );
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +020012260 execute( TC_assignment_fr_a5_not_sup() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012261 execute( TC_ciph_mode_a5_0() );
12262 execute( TC_ciph_mode_a5_1() );
Oliver Smith50b98122021-07-09 15:00:28 +020012263 execute( TC_ciph_mode_a5_2_0() );
Oliver Smith1dff88d2021-07-09 08:45:51 +020012264 execute( TC_ciph_mode_a5_2_1() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012265 execute( TC_ciph_mode_a5_3() );
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +020012266 execute( TC_ciph_mode_a5_4() );
Harald Welte16a4adf2017-12-14 18:54:01 +010012267
Harald Welte60aa5762018-03-21 19:33:13 +010012268 execute( TC_assignment_codec_fr() );
Neels Hofmeyr559d5d02021-04-16 16:50:49 +020012269 execute( TC_assignment_codec_fr_by_mode_modify() );
Harald Welte60aa5762018-03-21 19:33:13 +010012270 execute( TC_assignment_codec_hr() );
12271 execute( TC_assignment_codec_efr() );
12272 execute( TC_assignment_codec_amr_f() );
12273 execute( TC_assignment_codec_amr_h() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012274
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012275 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier8a581d22019-03-26 18:32:48 +010012276 execute( TC_assignment_codec_amr_f_S1() );
12277 execute( TC_assignment_codec_amr_h_S1() );
12278 execute( TC_assignment_codec_amr_f_S124() );
12279 execute( TC_assignment_codec_amr_h_S124() );
12280 execute( TC_assignment_codec_amr_f_S0() );
12281 execute( TC_assignment_codec_amr_f_S02() );
12282 execute( TC_assignment_codec_amr_f_S024() );
12283 execute( TC_assignment_codec_amr_f_S0247() );
12284 execute( TC_assignment_codec_amr_h_S0() );
12285 execute( TC_assignment_codec_amr_h_S02() );
12286 execute( TC_assignment_codec_amr_h_S024() );
12287 execute( TC_assignment_codec_amr_h_S0247() );
12288 execute( TC_assignment_codec_amr_f_S01234567() );
12289 execute( TC_assignment_codec_amr_f_S0234567() );
12290 execute( TC_assignment_codec_amr_f_zero() );
12291 execute( TC_assignment_codec_amr_f_unsupp() );
12292 execute( TC_assignment_codec_amr_h_S7() );
Neels Hofmeyr21863562020-11-26 00:34:33 +000012293 execute( TC_assignment_codec_amr_f_start_mode_auto() );
12294 execute( TC_assignment_codec_amr_h_start_mode_auto() );
Neels Hofmeyr3eb94562020-11-26 02:40:26 +000012295 execute( TC_assignment_codec_amr_f_start_mode_4() );
12296 execute( TC_assignment_codec_amr_h_start_mode_4() );
Neels Hofmeyr454d7922020-11-26 02:24:57 +000012297 execute( TC_assignment_codec_amr_startmode_cruft() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012298 }
Harald Welte60aa5762018-03-21 19:33:13 +010012299
Philipp Maierac09bfc2019-01-08 13:41:39 +010012300 execute( TC_assignment_codec_fr_exhausted_req_hr() );
12301 execute( TC_assignment_codec_fr_exhausted_req_fr() );
12302 execute( TC_assignment_codec_fr_exhausted_req_fr_hr() );
12303 execute( TC_assignment_codec_fr_exhausted_req_hr_fr() );
12304 execute( TC_assignment_codec_hr_exhausted_req_fr() );
12305 execute( TC_assignment_codec_hr_exhausted_req_hr() );
12306 execute( TC_assignment_codec_hr_exhausted_req_hr_fr() );
12307 execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
12308 execute( TC_assignment_codec_req_hr_fr() );
12309 execute( TC_assignment_codec_req_fr_hr() );
Pau Espin Pedrol14475352021-07-22 15:48:16 +020012310 execute( TC_assignment_sdcch_exhausted_req_signalling() );
12311 execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
12312 execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
Philipp Maierac09bfc2019-01-08 13:41:39 +010012313
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +020012314 execute( TC_assignment_codec_hr_osmux_on() );
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +020012315 execute( TC_assignment_osmux() );
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020012316 execute( TC_assignment_osmux_cn() );
12317 execute( TC_assignment_osmux_bts() );
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +020012318
Harald Welte898113b2018-01-31 18:32:21 +010012319 /* RLL Establish Indication on inactive DCHAN / SAPI */
Harald Welte5cd20ed2017-12-13 21:03:20 +010012320 execute( TC_rll_est_ind_inact_lchan() );
12321 execute( TC_rll_est_ind_inval_sapi1() );
12322 execute( TC_rll_est_ind_inval_sapi3() );
12323 execute( TC_rll_est_ind_inval_sacch() );
12324
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +070012325 /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
12326 execute( TC_tch_dlci_link_id_sapi() );
12327
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012328 /* SAPI N Reject triggered by RLL establishment failures */
12329 execute( TC_rll_rel_ind_sapi_n_reject() );
12330 execute( TC_rll_err_ind_sapi_n_reject() );
12331 execute( TC_rll_timeout_sapi_n_reject() );
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +070012332 execute( TC_rll_sapi_n_reject_dlci_cc() );
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012333
Harald Welte898113b2018-01-31 18:32:21 +010012334 /* Paging related tests */
Harald Welte6f521d82017-12-11 19:52:02 +010012335 execute( TC_paging_imsi_nochan() );
12336 execute( TC_paging_tmsi_nochan() );
12337 execute( TC_paging_tmsi_any() );
12338 execute( TC_paging_tmsi_sdcch() );
12339 execute( TC_paging_tmsi_tch_f() );
12340 execute( TC_paging_tmsi_tch_hf() );
12341 execute( TC_paging_imsi_nochan_cgi() );
12342 execute( TC_paging_imsi_nochan_lac_ci() );
12343 execute( TC_paging_imsi_nochan_ci() );
12344 execute( TC_paging_imsi_nochan_lai() );
12345 execute( TC_paging_imsi_nochan_lac() );
12346 execute( TC_paging_imsi_nochan_all() );
Harald Welte751d3eb2018-01-31 15:51:06 +010012347 execute( TC_paging_imsi_nochan_plmn_lac_rnc() );
12348 execute( TC_paging_imsi_nochan_rnc() );
12349 execute( TC_paging_imsi_nochan_lac_rnc() );
12350 execute( TC_paging_imsi_nochan_lacs() );
12351 execute( TC_paging_imsi_nochan_lacs_empty() );
Stefan Sperling049a86e2018-03-20 15:51:00 +010012352 execute( TC_paging_imsi_nochan_cgi_unknown_cid() );
Harald Welte10985002017-12-12 09:29:15 +010012353 execute( TC_paging_imsi_a_reset() );
Harald Weltee65d40e2017-12-13 00:09:06 +010012354 execute( TC_paging_imsi_load() );
Philipp Maier779a7922018-02-16 11:00:37 +010012355 execute( TC_paging_counter() );
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +010012356 execute( TC_paging_resp_unsol() );
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +020012357 execute( TC_paging_500req() );
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +020012358 execute( TC_paging_450req_no_paging_load_ind() );
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +010012359 execute( TC_paging_imsi_nochan_ci_resp_invalid_mi() );
Harald Welte4e9b9cc2017-12-14 18:31:02 +010012360
12361 execute( TC_rsl_drop_counter() );
Stefan Sperling830dc9d2018-02-12 21:08:28 +010012362 execute( TC_rsl_unknown_unit_id() );
12363
12364 execute( TC_oml_unknown_unit_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012365
12366 execute( TC_classmark() );
Harald Welteeddf0e92020-06-21 19:42:15 +020012367 execute( TC_common_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012368 execute( TC_unsol_ass_fail() );
Harald Welteea99a002018-01-31 20:46:43 +010012369 execute( TC_unsol_ass_compl() );
Harald Weltefbf9b5e2018-01-31 20:41:23 +010012370 execute( TC_unsol_ho_fail() );
Harald Weltee3bd6582018-01-31 22:51:25 +010012371 execute( TC_err_82_short_msg() );
Harald Weltee9e02e42018-01-31 23:36:25 +010012372 execute( TC_err_84_unknown_msg() );
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012373
Harald Welte261af4b2018-02-12 21:20:39 +010012374 execute( TC_ho_int() );
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +020012375 execute( TC_ho_int_a5_0() );
12376 execute( TC_ho_int_a5_1() );
12377 execute( TC_ho_int_a5_3() );
12378 execute( TC_ho_int_a5_4() );
Neels Hofmeyr5f144212020-11-03 15:41:58 +000012379 execute( TC_ho_int_radio_link_failure() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012380
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012381 /* TC_ho_out_of_this_bsc is run last, see comment below */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +020012382 execute( TC_ho_out_fail_no_msc_response() );
12383 execute( TC_ho_out_fail_rr_ho_failure() );
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +020012384 execute( TC_ho_out_fail_no_result_after_ho_cmd() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012385
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012386 execute( TC_ho_into_this_bsc() );
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +020012387 execute( TC_ho_into_this_bsc_a5_0() );
12388 execute( TC_ho_into_this_bsc_a5_1() );
12389 execute( TC_ho_into_this_bsc_a5_3() );
12390 execute( TC_ho_into_this_bsc_a5_4() );
Neels Hofmeyr93182e02022-02-17 21:59:07 +010012391 execute( TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() );
12392 execute( TC_ho_into_this_bsc_a5_1_3() );
Neels Hofmeyr907b23b2022-02-17 21:58:47 +010012393 execute( TC_ho_into_this_bsc_a5_mismatch() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012394 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12395 execute( TC_ho_into_this_bsc_tla_v6() );
12396 }
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +020012397 execute( TC_srvcc_eutran_to_geran() );
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +030012398 execute( TC_srvcc_eutran_to_geran_a5_3() );
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +010012399 execute( TC_srvcc_eutran_to_geran_src_sai() );
Pau Espin Pedrol35801c32021-04-19 13:03:20 +020012400 execute( TC_srvcc_eutran_to_geran_ho_out() );
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +020012401 execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
12402 execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012403 execute( TC_ho_in_fail_msc_clears() );
12404 execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
12405 execute( TC_ho_in_fail_no_detect() );
12406 execute( TC_ho_in_fail_no_detect2() );
Oliver Smith7a8594a2023-02-13 14:30:49 +010012407 execute( TC_ho_in_fail_mgw_mdcx_timeout() );
Oliver Smith4eed06f2023-02-15 15:43:19 +010012408 execute( TC_ho_in_fail_ipa_crcx_timeout() );
Neels Hofmeyra23f3b12022-03-02 19:57:12 +010012409 execute( TC_ho_into_this_bsc_sccp_cr_without_bssap() );
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012410
Neels Hofmeyr91401012019-07-11 00:42:35 +020012411 execute( TC_ho_neighbor_config_1() );
12412 execute( TC_ho_neighbor_config_2() );
12413 execute( TC_ho_neighbor_config_3() );
12414 execute( TC_ho_neighbor_config_4() );
12415 execute( TC_ho_neighbor_config_5() );
12416 execute( TC_ho_neighbor_config_6() );
12417 execute( TC_ho_neighbor_config_7() );
12418
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012419 execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() );
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010012420 execute( TC_bssmap_clear_does_not_cause_bssmap_reset() );
Neels Hofmeyrfd445c32018-03-09 15:39:31 +010012421 execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() );
Harald Welte94e0c342018-04-07 11:33:23 +020012422
12423 execute( TC_dyn_pdch_ipa_act_deact() );
12424 execute( TC_dyn_pdch_ipa_act_nack() );
12425 execute( TC_dyn_pdch_osmo_act_deact() );
12426 execute( TC_dyn_pdch_osmo_act_nack() );
Pau Espin Pedrol37a4c152021-11-16 19:02:23 +010012427 execute( TC_dyn_ts_sdcch8_act_deact() );
12428 execute( TC_dyn_ts_sdcch8_all_subslots_used() );
12429 execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
12430 execute( TC_dyn_ts_sdcch8_act_nack() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012431
Stefan Sperling0796a822018-10-05 13:01:39 +020012432 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +020012433 execute( TC_chopped_ipa_payload() );
Stefan Sperling0796a822018-10-05 13:01:39 +020012434
Pau Espin Pedrol8f773632019-11-05 11:46:53 +010012435 /* Power control related */
12436 execute( TC_assignment_verify_ms_power_params_ie() );
Vadim Yanitskiy4b233042021-06-30 00:58:43 +020012437 execute( TC_c0_power_red_mode() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012438
12439 /* MSC pooling */
12440 /* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
12441 * RESET->RESET-ACK is unconditionally negotiated for all configured MSCs, they always all appear as connected
12442 * to osmo-bsc. The MSC pooling tests however require disconnecting selected MSCs, and hence don't work out as
12443 * intended on SCCPlite. So for now, run these only for SCCP/M3UA. */
12444 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12445 execute( TC_mscpool_L3Compl_on_1_msc() );
12446 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
12447 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
12448 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
12449 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
12450 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
12451 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
12452 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
12453 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
12454 execute( TC_mscpool_paging_and_response_imsi() );
12455 execute( TC_mscpool_paging_and_response_tmsi() );
12456 execute( TC_mscpool_no_allow_attach_round_robin() );
12457 execute( TC_mscpool_no_allow_attach_valid_nri() );
12458 }
12459
Harald Welte99f3ca02018-06-14 13:40:29 +020012460 execute( TC_early_conn_fail() );
12461 execute( TC_late_conn_fail() );
Oliver Smithaf03bef2021-08-24 15:34:51 +020012462 execute( TC_stats_conn_fail() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012463
Philipp Maier783681c2020-07-16 16:47:06 +020012464 /* Emergency call handling (deny / allow) */
12465 execute( TC_assignment_emerg_setup_allow() );
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +010012466 execute( TC_assignment_emerg_setup_allow_imei() );
Philipp Maier783681c2020-07-16 16:47:06 +020012467 execute( TC_assignment_emerg_setup_deny_msc() );
12468 execute( TC_assignment_emerg_setup_deny_bts() );
Philipp Maier82812002020-08-13 18:48:27 +020012469 execute( TC_emerg_premption() );
12470
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +070012471 /* Frequency hopping parameters handling */
12472 execute( TC_fh_params_chan_activ() );
12473 execute( TC_fh_params_imm_ass() );
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070012474 execute( TC_fh_params_assignment_cmd() );
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070012475 execute( TC_fh_params_handover_cmd() );
Vadim Yanitskiyca974032020-09-01 07:20:39 +070012476 execute( TC_fh_params_si4_cbch() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012477
12478 if (mp_enable_lcs_tests) {
12479 execute( TC_lcs_loc_req_for_active_ms() );
12480 execute( TC_lcs_loc_req_for_active_ms_ta_req() );
12481 execute( TC_lcs_loc_req_for_idle_ms() );
12482 execute( TC_lcs_loc_req_no_subscriber() );
12483 execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
12484 execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
12485 execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
12486 execute( TC_cm_service_during_lcs_loc_req() );
12487 execute( TC_ho_during_lcs_loc_req() );
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020012488 execute( TC_emerg_call_and_lcs_loc_req() );
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020012489 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() );
12490 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012491 }
Neels Hofmeyrbf037052020-10-28 22:52:02 +000012492
12493 execute( TC_no_msc() );
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000012494
12495 execute( TC_refuse_chan_act_to_vamos() );
12496 execute( TC_refuse_mode_modif_to_vamos() );
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000012497
12498 execute( TC_reassignment_fr() );
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020012499
12500 execute( TC_cm_reestablishment() );
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020012501
12502 execute( TC_imm_ass_post_chan_ack() );
12503 execute( TC_imm_ass_pre_chan_ack() );
Neels Hofmeyr23158742021-09-07 19:08:07 +020012504 execute( TC_imm_ass_pre_ts_ack() );
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020012505 execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020012506 execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020012507
12508 execute( TC_ctrl_trx_rf_locked() );
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012509
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012510 execute( TC_ratectr_all_available_allocated() );
12511 execute( TC_ratectr_all_available_allocated_dyn() );
12512
Neels Hofmeyrb7581872021-11-07 14:02:49 +010012513 execute( TC_cm_serv_rej() );
12514
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012515 execute( TC_lost_sdcch_during_assignment() );
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012516
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012517 /* Channel allocator */
12518 execute( TC_chan_alloc_algo_ascending() );
12519 execute( TC_chan_alloc_algo_descending() );
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012520 execute( TC_chan_alloc_algo_ass_dynamic() );
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012521
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012522 /* MGW pool */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +010012523 execute( TC_mgwpool_all_used() );
12524 execute( TC_mgwpool_blocked_not_used() );
12525 execute( TC_mgwpool_pin_bts() );
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012526
Oliver Smithc9a5f532022-10-21 11:32:23 +020012527 execute( TC_ho_meas_rep_multi_band() );
12528
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012529 /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
12530 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
12531 execute( TC_ho_out_of_this_bsc() );
Harald Welte28d943e2017-11-25 15:00:50 +010012532}
12533
12534}