blob: aa627b7b19e8452a49abc64af86570ab2e3cbb09 [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
Neels Hofmeyr38632aa2023-04-05 03:50:51 +0200649 var boolean g_handler_mode := false;
650
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200651 /* Osmux is enabled through VTY */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200652 var boolean g_osmux_enabled_cn := false;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +0200653 var boolean g_osmux_enabled_bts := false;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200654
Pau Espin Pedrolc675b612020-01-09 19:55:40 +0100655 /*Configure T(tias) over VTY, seconds */
656 var integer g_bsc_sccp_timer_ias := 7 * 60;
657 /*Configure T(tiar) over VTY, seconds */
658 var integer g_bsc_sccp_timer_iar := 15 * 60;
659
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +0200660 /* global test case guard timer (actual timeout value is set in f_init()) */
Harald Welteae026692017-12-09 01:03:01 +0100661 timer T_guard := 30.0;
662
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200663 var CounterNameValsList g_ctr_msc;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000664 var CounterNameValsList g_ctr_bsc;
665 var CounterNameValsList g_ctr_bts;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200666
667 /* System Information bytes as received during RSL startup, for each RSL[idx]. */
668 var SystemInformationConfig_list g_system_information := {};
Harald Welte28d943e2017-11-25 15:00:50 +0100669}
670
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200671type record of charstring phys_chan_configs;
Harald Welte28d943e2017-11-25 15:00:50 +0100672modulepar {
Harald Welte21b46bd2017-12-17 19:46:32 +0100673 /* IP address at which the BSC can be reached */
Harald Welte696ddb62017-12-08 14:01:43 +0100674 charstring mp_bsc_ip := "127.0.0.1";
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100675 /* port number to which to establish the IPA OML connections */
676 integer mp_bsc_oml_port := 3002;
Harald Welte21b46bd2017-12-17 19:46:32 +0100677 /* port number to which to establish the IPA RSL connections */
Harald Welte696ddb62017-12-08 14:01:43 +0100678 integer mp_bsc_rsl_port := 3003;
Harald Welte21b46bd2017-12-17 19:46:32 +0100679 /* port number to which to establish the IPA CTRL connection */
Harald Welte96c94412017-12-09 03:12:45 +0100680 integer mp_bsc_ctrl_port := 4249;
Daniel Willmannebdecc02020-08-12 15:30:17 +0200681 /* port number to which to listen for STATSD metrics */
682 integer mp_bsc_statsd_port := 8125;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100683 /* IP address at which the test binds */
684 charstring mp_test_ip := "127.0.0.1";
Harald Weltea4ca4462018-02-09 00:17:14 +0100685
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200686 RAN_Configurations mp_bssap_cfg := {
687 {
688 transport := BSSAP_TRANSPORT_AoIP,
689 sccp_service_type := "mtp3_itu",
690 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
691 own_pc := 185, /* 0.23.1 first MSC emulation */
692 own_ssn := 254,
693 peer_pc := 187, /* 0.23.3 osmo-bsc */
694 peer_ssn := 254,
695 sio := '83'O,
Harald Weltecb0cc432020-06-21 19:42:31 +0200696 rctx := 1
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200697 },
698 {
699 transport := BSSAP_TRANSPORT_AoIP,
700 sccp_service_type := "mtp3_itu",
701 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
702 own_pc := 2, /* 0.0.2 second MSC emulation */
703 own_ssn := 254,
704 peer_pc := 187, /* 0.23.3 osmo-bsc */
705 peer_ssn := 254,
706 sio := '83'O,
707 rctx := 2
708 },
709 {
710 transport := BSSAP_TRANSPORT_AoIP,
711 sccp_service_type := "mtp3_itu",
712 sctp_addr := { 23907, "127.0.0.1", 2905, "127.0.0.1" },
713 own_pc := 3, /* 0.0.3 third MSC emulation */
714 own_ssn := 254,
715 peer_pc := 187, /* 0.23.3 osmo-bsc */
716 peer_ssn := 254,
717 sio := '83'O,
718 rctx := 3
719 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100720 };
Pau Espin Pedrol58cf6822019-05-28 18:11:33 +0200721
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200722 /* Must match per BTS config in osmo-bsc.cfg */
723 phys_chan_configs phys_chan_config := {
724 "CCCH+SDCCH4+CBCH",
725 "TCH/F",
726 "TCH/F",
727 "TCH/F",
728 "TCH/F",
Vadim Yanitskiy343c9eb2021-07-16 18:36:01 +0600729 "TCH/H",
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200730 "PDCH",
731 "PDCH"
732 };
733
Harald Welte47cd0e32020-08-21 12:39:11 +0200734 BSSAP_LE_Configuration mp_bssap_le_cfg := {
735 sccp_service_type := "mtp3_itu",
736 sctp_addr := { 23908, "127.0.0.1", 2905, "127.0.0.1" },
Neels Hofmeyrac086c12020-09-18 23:46:42 +0200737 own_pc := 190, /* 0.23.6 SMLC emulation */
Harald Welte47cd0e32020-08-21 12:39:11 +0200738 own_ssn := 252, /* SMLC side SSN */
739 peer_pc := 187, /* 0.23.3 osmo-bsc */
740 peer_ssn := 250, /* BSC side SSN */
741 sio := '83'O,
742 rctx := 6
743 };
Neels Hofmeyrcfe44062020-10-15 02:28:08 +0200744 boolean mp_enable_lcs_tests := true;
Harald Welte47cd0e32020-08-21 12:39:11 +0200745
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100746 /* Value set in osmo-bsc.cfg "ms max power" */
747 uint8_t mp_exp_ms_power_level := 7;
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600748
749 /* Whether to check for memory leaks */
750 boolean mp_verify_talloc_count := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100751}
752
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200753friend function f_gen_test_hdlr_pars(integer bssap_idx := 0) return TestHdlrParams {
Philipp Maier48604732018-10-09 15:00:37 +0200754
755 var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200756 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier48604732018-10-09 15:00:37 +0200757 pars.aoip := true;
758 } else {
759 pars.aoip := false;
760 }
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100761 pars.exp_ms_power_level := mp_exp_ms_power_level;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200762 pars.mscpool.bssap_idx := bssap_idx;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600763 pars.expect_tsc := c_BtsParams[0].tsc;
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300764 pars.imsi := f_rnd_imsi('00101'H);
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +0100765 pars.imei := f_rnd_imei('00101'H);
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300766
767 log(testcasename(), ": using IMSI ", pars.imsi);
Neels Hofmeyrb5b7a6e2021-06-04 19:03:45 +0200768
Philipp Maier48604732018-10-09 15:00:37 +0200769 return pars;
770}
771
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200772/* Convenience functions for rate counters using g_ctr_msc. */
773
774private function f_ctrs_msc_init(integer mscs_count := NUM_MSC, CounterNameVals counternames := counternames_msc_mscpool) runs on test_CT {
775 g_ctr_msc := f_counter_name_vals_get_n(IPA_CTRL, "msc", mscs_count, counternames);
776 log("initial msc rate counters: ", g_ctr_msc);
777}
778
779private function f_ctrs_msc_add(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr9656e922020-06-30 01:27:01 +0200780 f_counter_name_vals_list_add(g_ctr_msc, msc_nr, countername, val);
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200781}
782
783/* f_ctrs_msc_init();
784 * f_do_thing(on_msc := 0);
785 * f_do_thing(on_msc := 0);
786 * f_do_other(on_msc := 1);
787 * f_ctrs_msc_add(0, "thing", 2);
788 * f_ctrs_msc_add(1, "other");
789 * f_ctrs_msc_verify();
790 */
791private function f_ctrs_msc_verify() runs on test_CT {
792 log("verifying msc rate counters: ", g_ctr_msc);
793 f_counter_name_vals_expect_n(IPA_CTRL, "msc", g_ctr_msc);
794}
795
796/* convenience: f_ctrs_msc_add() and f_ctrs_msc_verify() in one call.
797 * f_ctrs_msc_init();
798 * f_do_thing(on_msc := 0);
799 * f_do_thing(on_msc := 0);
800 * f_do_thing(on_msc := 0);
801 * f_ctrs_msc_expect(0, "thing", 3);
802 */
803private function f_ctrs_msc_expect(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
804 f_ctrs_msc_add(msc_nr, countername, val);
805 f_ctrs_msc_verify();
806}
807
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000808/* Convenience functions for rate counters using g_ctr_bts, always also including g_ctr_bsc. */
809
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100810private 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 +0000811 g_ctr_bts := f_counter_name_vals_get_n(IPA_CTRL, "bts", bts_count, counternames);
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100812 log("initial bts rate counters: ", g_ctr_bts);
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100813}
814
815function f_ctrs_bsc_and_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
816 f_ctrs_bts_init(bts_count, counternames);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000817 f_ctrs_bsc_init(counternames);
818}
819
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100820private function f_ctrs_bsc_and_bts_handover_init(integer bts_count := NUM_BTS) runs on test_CT {
821 var CounterNameVals bts_names := counternames_bsc_bts_handover & counternames_bts_handover;
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100822 f_ctrs_bts_init(bts_count, bts_names);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100823 f_ctrs_bsc_init(counternames_bsc_bts_handover);
824}
825
826private function f_ctrs_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000827 f_counter_name_vals_list_add(g_ctr_bts, bts_nr, countername, val);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100828}
829
830private function f_ctrs_bsc_and_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
831 f_ctrs_bts_add(bts_nr, countername, val);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000832 f_ctrs_bsc_add(countername, val);
833}
834
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100835function f_ctrs_bts_verify() runs on test_CT {
836 f_counter_name_vals_expect_n(IPA_CTRL, "bts", g_ctr_bts);
837}
838
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000839/* f_ctrs_bsc_and_bts_init();
840 * f_do_thing(on_bts := 0);
841 * f_do_thing(on_bts := 0);
842 * f_do_other(on_bts := 1);
843 * f_ctrs_bsc_and_bts_add(0, "thing", 2);
844 * f_ctrs_bsc_and_bts_add(1, "other");
845 * f_ctrs_bsc_and_bts_verify();
846 */
847private function f_ctrs_bsc_and_bts_verify() runs on test_CT {
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100848 f_ctrs_bts_verify();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000849 f_ctrs_bsc_verify();
850}
851
852/* convenience: f_ctrs_bsc_and_bts_add() and f_ctrs_bsc_and_bts_verify() in one call.
853 * f_ctrs_bsc_and_bts_init();
854 * f_do_thing(on_bts := 0);
855 * f_do_thing(on_bts := 0);
856 * f_do_thing(on_bts := 0);
857 * f_ctrs_bsc_and_bts_expect(0, "thing", 3);
858 */
859private function f_ctrs_bsc_and_bts_expect(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
860 f_ctrs_bsc_and_bts_add(bts_nr, countername, val);
861 f_ctrs_bsc_and_bts_verify();
862}
863
864
865/* Convenience functions for rate counters using g_ctr_bsc. */
866
867private function f_ctrs_bsc_init(CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
868 g_ctr_bsc := f_counter_name_vals_get_n(IPA_CTRL, "bsc", 1, counternames);
869 log("initial bsc rate counters: ", g_ctr_bsc);
870}
871
872private function f_ctrs_bsc_add(charstring countername, integer val := 1) runs on test_CT {
873 f_counter_name_vals_list_add(g_ctr_bsc, 0, countername, val);
874}
875
876/* f_ctrs_bsc_init();
877 * f_do_thing();
878 * f_do_thing();
879 * f_do_other();
880 * f_ctrs_bsc_add("thing", 2);
881 * f_ctrs_bsc_add("other");
882 * f_ctrs_bsc_verify();
883 */
884private function f_ctrs_bsc_verify() runs on test_CT {
885 f_counter_name_vals_expect_n(IPA_CTRL, "bsc", g_ctr_bsc);
886}
887
888/* convenience: f_ctrs_bsc_add() and f_ctrs_bsc_verify() in one call.
889 * f_ctrs_bsc_init();
890 * f_do_thing();
891 * f_ctrs_bsc_expect("thing", 1);
892 */
893private function f_ctrs_bsc_expect(charstring countername, integer val := 1) runs on test_CT {
894 f_ctrs_bsc_add(countername, val);
895 f_ctrs_bsc_verify();
896}
897
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200898
Oliver Smith39f53072022-10-27 14:44:04 +0200899friend function f_shutdown_helper(boolean ho := false) runs on test_CT {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100900 /* Run the subscr and conn leak test only when the VTY is initialized */
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600901 if (BSCVTY.checkstate("Mapped") and mp_verify_talloc_count) {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100902 f_verify_talloc_count(BSCVTY, {"struct bsc_subscr", "struct gsm_subscriber_connection"});
903 }
904
Oliver Smith39f53072022-10-27 14:44:04 +0200905 /* Reset handover related configuration */
906 if (ho) {
907 f_bts_0_cfg(BSCVTY,
908 {"no neighbors",
909 "neighbor-list mode manual-si5",
910 "neighbor-list add arfcn 100",
911 "neighbor-list add arfcn 200",
912 "si5 neighbor-list add arfcn 10",
913 "si5 neighbor-list add arfcn 20",
914 "handover algorithm 1"});
915 }
916
Daniel Willmann637ef6c2018-07-25 10:49:09 +0200917 all component.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100918 setverdict(pass);
Daniel Willmannafce8662018-07-06 23:11:32 +0200919 mtc.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100920}
921
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200922private function f_legacy_bssap_reset(integer bssap_idx := 0) runs on test_CT {
Harald Weltea4ca4462018-02-09 00:17:14 +0100923 var BSSAP_N_UNITDATA_ind ud_ind;
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200924 var boolean reset_received := false;
Harald Weltea4ca4462018-02-09 00:17:14 +0100925 timer T := 5.0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200926 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 +0200927 ts_BSSMAP_Reset(0, g_osmux_enabled_cn)));
Harald Weltea4ca4462018-02-09 00:17:14 +0100928 T.start;
929 alt {
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200930 [] 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 +0200931 tr_BSSMAP_ResetAck(g_osmux_enabled_cn))) {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200932 log("BSSMAP: Received RESET-ACK in response to RESET, we're ready to go!");
Harald Weltea4ca4462018-02-09 00:17:14 +0100933 }
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200934 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200935 log("BSSMAP: Respoding to inbound RESET with RESET-ACK");
Harald Weltea4ca4462018-02-09 00:17:14 +0100936 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200937 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200938 reset_received := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100939 repeat;
940 }
941 [] BSSAP.receive { repeat; }
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200942 [] T.timeout {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200943 log("BSSMAP: Timeout waiting for RESET-ACK after sending RESET");
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200944 /* If we received a RESET after ours was sent, it
945 may be a race condition where the other peer beacame
946 available after we sent it, but we are in a desired
947 state anyway, so go forward. */
948 if (not reset_received) {
949 setverdict(fail);
950 }
951 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100952 }
Harald Welte28d943e2017-11-25 15:00:50 +0100953}
954
Harald Welteae026692017-12-09 01:03:01 +0100955type record IPA_Client {
Harald Welte21b46bd2017-12-17 19:46:32 +0100956 /* IPA Emulation component reference */
Harald Welteae026692017-12-09 01:03:01 +0100957 IPA_Emulation_CT vc_IPA,
Harald Welte21b46bd2017-12-17 19:46:32 +0100958 /* Unit-ID and other CCM parameters to use for IPA client emulation */
Harald Welteae026692017-12-09 01:03:01 +0100959 IPA_CCM_Parameters ccm_pars,
Harald Welte21b46bd2017-12-17 19:46:32 +0100960 /* String identifier for this IPA Client */
Harald Welte624f9632017-12-16 19:26:04 +0100961 charstring id,
Harald Welte21b46bd2017-12-17 19:46:32 +0100962 /* Associated RSL Emulation Component (if any). Only used in "Handler mode" */
Harald Welte624f9632017-12-16 19:26:04 +0100963 RSL_Emulation_CT vc_RSL optional
Harald Welte28d943e2017-11-25 15:00:50 +0100964}
965
Harald Welte21b46bd2017-12-17 19:46:32 +0100966/*! Start the IPA/RSL related bits for one IPA_Client.
967 * \param clnt IPA_Client for which to establish
968 * \param bsc_host IP address / hostname of the BSC
969 * \param bsc_port TCP port number of the BSC
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600970 * \param idx BTS/TRX index values
Harald Welte21b46bd2017-12-17 19:46:32 +0100971 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600972function f_ipa_rsl_start(inout IPA_Client clnt, charstring bsc_host, PortNumber bsc_port,
973 BtsTrxIdx idx := {0, 0}, boolean handler_mode := false)
Harald Welte28d943e2017-11-25 15:00:50 +0100974runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +0100975 timer T := 10.0;
976
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600977 clnt.id := "IPA-BTS" & int2str(idx.bts) & "-TRX" & int2str(idx.trx) & "-RSL";
Harald Welte71389132021-12-09 21:58:18 +0100978 clnt.vc_IPA := IPA_Emulation_CT.create(clnt.id & "-IPA") alive;
Harald Welteae026692017-12-09 01:03:01 +0100979 clnt.ccm_pars := c_IPA_default_ccm_pars;
980 clnt.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600981 clnt.ccm_pars.unit_id := int2str(1234 + idx.bts) & "/0/" & int2str(idx.trx);
Harald Welte624f9632017-12-16 19:26:04 +0100982 if (handler_mode) {
Harald Welte71389132021-12-09 21:58:18 +0100983 clnt.vc_RSL := RSL_Emulation_CT.create(clnt.id & "-RSL") alive;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600984 connect(clnt.vc_RSL:CCHAN_PT, self:RSL_CCHAN[idx.bts]);
Harald Welte624f9632017-12-16 19:26:04 +0100985 }
Harald Welteae026692017-12-09 01:03:01 +0100986
987 map(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200988 connect(clnt.vc_IPA:CFG_PORT, self:IPA_CFG_PORT[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100989 if (handler_mode) {
990 connect(clnt.vc_IPA:IPA_RSL_PORT, clnt.vc_RSL:IPA_PT);
991 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600992 connect(clnt.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100993 }
Harald Welteae026692017-12-09 01:03:01 +0100994
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600995 var integer local_port := 10000 + idx.bts * 1000 + idx.trx;
996 clnt.vc_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", local_port, clnt.ccm_pars));
Harald Welte624f9632017-12-16 19:26:04 +0100997 if (handler_mode) {
998 clnt.vc_RSL.start(RSL_Emulation.main());
999 return;
1000 }
Harald Welteae026692017-12-09 01:03:01 +01001001
1002 /* wait for IPA RSL link to connect and send ID ACK */
1003 T.start;
1004 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001005 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) {
Harald Welteae026692017-12-09 01:03:01 +01001006 T.stop;
Harald Welteae026692017-12-09 01:03:01 +01001007 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001008 [] IPA_RSL[idx.bts][idx.trx].receive(ASP_IPA_Event:?) { repeat }
1009 [] IPA_RSL[idx.bts][idx.trx].receive { repeat }
Harald Welteae026692017-12-09 01:03:01 +01001010 [] T.timeout {
Harald Welte96c94412017-12-09 03:12:45 +01001011 setverdict(fail, "Timeout RSL waiting for ASP_IPA_EVENT_ID_ACK");
Daniel Willmannafce8662018-07-06 23:11:32 +02001012 mtc.stop;
Harald Welteae026692017-12-09 01:03:01 +01001013 }
1014 }
1015}
1016
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001017function f_ipa_rsl_stop(inout IPA_Client clnt, BtsTrxIdx idx := {0, 0}) runs on test_CT {
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001018 var IPL4asp_Types.Result res := {
1019 errorCode := omit,
1020 connId := omit,
1021 os_error_code := omit,
1022 os_error_text := omit
1023 };
1024
Harald Welte12055472018-03-17 20:10:08 +01001025 if (not isbound(clnt) or not isbound(clnt.vc_IPA)) {
1026 return;
1027 }
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001028
1029 /* Alive components don't finish sockets (TCP FIN) when they are
1030 * stopped. Hence, we need to manually call close() on them to make sure
1031 * the IUT knows about it. */
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001032 f_ipa_cfg_disconnect(IPA_CFG_PORT[idx.bts][idx.trx], res);
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001033
Harald Welte12055472018-03-17 20:10:08 +01001034 clnt.vc_IPA.stop;
1035 if (isbound(clnt.vc_RSL)) {
1036 clnt.vc_RSL.stop;
1037 }
1038}
1039
Harald Welte21b46bd2017-12-17 19:46:32 +01001040/* Wait for the OML connection to be brought up by the external osmo-bts-omldummy */
Harald Weltea5d2ab22017-12-09 14:21:42 +01001041function f_wait_oml(integer bts_nr, charstring status, float secs_max) runs on test_CT {
1042 timer T := secs_max;
1043 T.start;
1044 while (true) {
1045 if (f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-connection-state") == status) {
1046 T.stop;
Harald Weltebd868bd2017-12-10 18:28:40 +01001047 /* the 'degraded' state exists from OML connection time, and we have to wait
1048 * until all MO's are initialized */
1049 T.start(1.0);
1050 T.timeout;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001051 return;
1052 }
Harald Weltef0d6ac62017-12-17 17:02:21 +01001053 f_sleep(0.1);
Harald Weltea5d2ab22017-12-09 14:21:42 +01001054 if (not T.running) {
Max99253902018-11-16 17:57:39 +01001055 setverdict(fail, "Timeout waiting for BTS" & int2str(bts_nr) & " oml-connection-state ", status);
Daniel Willmannafce8662018-07-06 23:11:32 +02001056 mtc.stop;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001057 }
1058 }
1059}
1060
Harald Welte21b46bd2017-12-17 19:46:32 +01001061/* global altstep for global guard timer; also takes care of responding RESET witH RESET-ACK */
Harald Welteae026692017-12-09 01:03:01 +01001062altstep as_Tguard() runs on test_CT {
Harald Welte60e823a2017-12-10 14:10:59 +01001063 var BSSAP_N_UNITDATA_ind ud_ind;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001064 [] T_guard.timeout {
1065 setverdict(fail, "Timeout of T_guard");
Daniel Willmannafce8662018-07-06 23:11:32 +02001066 mtc.stop;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001067 }
Harald Welte60e823a2017-12-10 14:10:59 +01001068 /* always respond with RESET ACK to RESET */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001069 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Harald Welte60e823a2017-12-10 14:10:59 +01001070 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001071 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Harald Welte69c1c262017-12-13 21:02:08 +01001072 repeat;
Harald Welte60e823a2017-12-10 14:10:59 +01001073 }
Harald Welte28d943e2017-11-25 15:00:50 +01001074}
1075
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001076altstep no_bssmap_reset() runs on test_CT {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001077 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001078 setverdict(fail, "unexpected BSSMAP Reset");
Daniel Willmannafce8662018-07-06 23:11:32 +02001079 mtc.stop;
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001080 }
1081}
1082
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001083function f_init_mgcp(integer mgw_nr, charstring id) runs on test_CT {
1084 id := id & "-MGCP-" & int2str(mgw_nr);
Daniel Willmann191e0d92018-01-17 12:44:35 +01001085
1086 var MGCPOps ops := {
1087 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
1088 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
1089 };
1090 var MGCP_conn_parameters mgcp_pars := {
1091 callagent_ip := mp_bsc_ip,
Harald Welte9e4273e2018-01-29 22:01:22 +01001092 callagent_udp_port := -1,
Daniel Willmann191e0d92018-01-17 12:44:35 +01001093 mgw_ip := mp_test_ip,
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001094 mgw_udp_port := 2427 + mgw_nr,
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02001095 /* Enable it for SCCPlite, since we have 2 MGCP sockets towards MGW (UDP one +
Pau Espin Pedrol36eeaf72022-10-20 16:50:31 +02001096 the one with MGCP over IPA forwarded from MSC one) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001097 multi_conn_mode := (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER)
Daniel Willmann191e0d92018-01-17 12:44:35 +01001098 };
1099
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001100 vc_MGCP[mgw_nr] := MGCP_Emulation_CT.create(id) alive;
1101 vc_MGCP[mgw_nr].start(MGCP_Emulation.main(ops, mgcp_pars, id));
Daniel Willmann191e0d92018-01-17 12:44:35 +01001102}
1103
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001104/* Enable or disable (current default) Osmux. When enabling, BSSMAP Reset
1105 * contains extra IE (OsmuxSupport) and osmo-bsc will handle AssignReq with
1106 * OsmuxCID IE.
1107 */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001108private function f_vty_allow_osmux_cn(boolean allow) runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001109 f_vty_enter_cfg_msc(BSCVTY, 0);
1110 if (allow) {
1111 f_vty_transceive(BSCVTY, "osmux on");
1112 } else {
1113 f_vty_transceive(BSCVTY, "osmux off");
1114 }
1115 f_vty_transceive(BSCVTY, "exit");
1116 f_vty_transceive(BSCVTY, "exit");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001117}
1118
Max2253c0b2018-11-06 19:28:05 +01001119function f_init_vty(charstring id := "foo") runs on test_CT {
Harald Welte94e0c342018-04-07 11:33:23 +02001120 if (BSCVTY.checkstate("Mapped")) {
1121 /* skip initialization if already executed once */
1122 return;
1123 }
Harald Weltebc03c762018-02-12 18:09:38 +01001124 map(self:BSCVTY, system:BSCVTY);
1125 f_vty_set_prompts(BSCVTY);
1126 f_vty_transceive(BSCVTY, "enable");
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01001127 f_cs7_inst_0_cfg(BSCVTY, {"sccp-timer ias " & int2str(g_bsc_sccp_timer_ias),
1128 "sccp-timer iar " & int2str(g_bsc_sccp_timer_iar)});
Harald Weltebc03c762018-02-12 18:09:38 +01001129}
1130
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +02001131friend function f_logp(TELNETasp_PT pt, charstring log_msg)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001132{
1133 // log on TTCN3 log output
1134 log(log_msg);
1135 // log in stderr log
Neels Hofmeyr8bdafe52021-12-14 17:25:48 +01001136 if (pt.checkstate("Mapped")) {
1137 f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
1138 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001139}
1140
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001141private function f_sysinfo_seen(integer rsl_idx, RSL_Message rsl) runs on test_CT
1142{
1143 if (rsl_idx >= lengthof(g_system_information)) {
1144 g_system_information[rsl_idx] := SystemInformationConfig_omit
1145 }
1146 f_sysinfo_dec_raw(g_system_information[rsl_idx], rsl);
1147}
1148
1149altstep as_catch_RSL_sysinfo(integer rsl_idx) runs on test_CT {
1150 var ASP_RSL_Unitdata rx_rsl_ud;
1151
1152 /* For handler_mode := false, receiving the RSL bootstrap messages directly on IPA_RSL */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001153 [] 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 +02001154 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1155 repeat;
1156 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001157 [] 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 +02001158 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1159 repeat;
1160 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001161 [] 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 +02001162 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1163 repeat;
1164 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001165 [] 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 +02001166 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1167 repeat;
1168 }
1169
1170 /* For handler_mode := true, receiving the RSL bootstrap messages via RSL_Emulation */
1171 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
1172 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1173 repeat;
1174 }
1175 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
1176 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1177 repeat;
1178 }
1179 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
1180 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1181 repeat;
1182 }
1183 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
1184 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1185 repeat;
1186 }
1187}
1188
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001189/* TODO: use BooleanList from COMMON/src/General_Types.ttcn */
1190private type record of boolean my_BooleanList;
1191
1192private function f_vty_msc_allow_attach(TELNETasp_PT pt, my_BooleanList allow_attach_list)
1193{
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001194 var charstring config := f_vty_transceive_ret(pt, "show running-config");
1195
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001196 for (var integer msc_nr := 0; msc_nr < sizeof(allow_attach_list); msc_nr := msc_nr+1) {
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001197 if (f_strstr(config, "\nmsc " & int2str(msc_nr) & "\n") < 0) {
1198 /* There is no 'msc N' for this msc_nr in the running config, so don't create an empty msc by
1199 * stepping into that config node. */
1200 log("msc ", msc_nr, " is not configured, skipping");
1201 continue;
1202 }
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001203 f_vty_enter_cfg_msc(pt, msc_nr);
1204 if (allow_attach_list[msc_nr]) {
1205 /* strict := false: ignore if osmo-bsc does not support this config option (latest build) */
1206 f_vty_transceive(pt, "allow-attach", strict := false);
1207 } else {
1208 f_vty_transceive(pt, "no allow-attach", strict := false);
1209 }
1210 f_vty_transceive(pt, "exit");
1211 f_vty_transceive(pt, "exit");
1212 }
1213}
1214
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02001215private function f_bssap_idx_init(integer bssap_idx) runs on test_CT {
1216 /* Call a function of our 'parent component' RAN_Adapter_CT to start the
1217 * MSC-side BSSAP emulation */
1218 if (g_handler_mode) {
1219 var RanOps ranops := MSC_RanOps;
1220 ranops.use_osmux := g_osmux_enabled_cn;
1221 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", ranops);
1222 connect(self:SCCPLITE_IPA_CTRL, g_bssap[bssap_idx].vc_RAN:CTRL_CLIENT);
1223 f_ran_adapter_start(g_bssap[bssap_idx]);
1224 } else {
1225 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", omit);
1226 connect(self:BSSAP, g_bssap[bssap_idx].vc_SCCP:SCCP_SP_PORT);
1227 f_ran_adapter_start(g_bssap[bssap_idx]);
1228 f_legacy_bssap_reset();
1229 }
1230}
1231
1232private function f_bssap_idx_disconnect(integer bssap_idx) runs on test_CT {
1233 f_ran_adapter_cleanup(g_bssap[bssap_idx]);
1234}
1235
Harald Welte21b46bd2017-12-17 19:46:32 +01001236/* global initialization function
1237 * \param nr_bts Number of BTSs we should start/bring up
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001238 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false).
1239 * \param nr_msc Number of virtual MSCs to bring up to connect to osmo-bsc.
1240 */
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001241function f_init(integer nr_bts := NUM_BTS, boolean handler_mode := false,
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001242 integer nr_msc := 1, integer nr_mgw := 1, float guard_timeout := 30.0) runs on test_CT {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001243 var integer bssap_idx;
Harald Welte28d943e2017-11-25 15:00:50 +01001244
Harald Welteae026692017-12-09 01:03:01 +01001245 if (g_initialized) {
1246 return;
Harald Welte28d943e2017-11-25 15:00:50 +01001247 }
Harald Welteae026692017-12-09 01:03:01 +01001248 g_initialized := true;
1249
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +02001250 T_guard.start(guard_timeout);
Daniel Willmanne68f9272018-11-27 15:15:28 +01001251 activate(as_Tguard());
1252
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001253 f_init_vty("VirtMSC");
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001254 f_vty_allow_osmux_cn(g_osmux_enabled_cn);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001255
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001256 var my_BooleanList allow_attach := { false, false, false };
Daniel Willmannebdecc02020-08-12 15:30:17 +02001257 f_init_statsd("VirtMSC", vc_STATSD, mp_test_ip, mp_bsc_statsd_port);
1258
Neels Hofmeyr9db8e0e2021-08-23 20:45:58 +02001259 /* Make sure each MSC's internal state is "DISCONNECTED" at first */
1260 for (bssap_idx := 0; bssap_idx < NUM_MSC; bssap_idx := bssap_idx+1) {
1261 f_vty_transceive(BSCVTY, "msc " & int2str(bssap_idx) & " bssmap reset", strict := false);
1262 }
1263
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02001264 g_handler_mode := handler_mode;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001265 for (bssap_idx := 0; bssap_idx < nr_msc; bssap_idx := bssap_idx+1) {
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001266 allow_attach[bssap_idx] := true;
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02001267 f_bssap_idx_init(bssap_idx);
Harald Welte67089ee2018-01-17 22:19:03 +01001268 }
Harald Welted5833a82018-05-27 16:52:56 +02001269
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02001270 if (mp_enable_lcs_tests) {
1271 if (handler_mode) {
1272 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", SMLC_BssapLeOps);
1273 } else {
1274 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", omit);
1275 connect(self:BSSAP_LE, g_bssap_le.vc_SCCP:SCCP_SP_PORT);
1276 }
1277 f_bssap_le_adapter_start(g_bssap_le);
Harald Welte47cd0e32020-08-21 12:39:11 +02001278 }
Harald Welte47cd0e32020-08-21 12:39:11 +02001279
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001280 /* start the test with exactly all enabled MSCs allowed to attach */
1281 f_vty_msc_allow_attach(BSCVTY, allow_attach);
1282
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01001283 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Harald Welte28d943e2017-11-25 15:00:50 +01001284
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001285 g_nr_mgw := nr_mgw;
1286 for (var integer i := 0; i < g_nr_mgw; i := i+1) {
1287 f_init_mgcp(i, "VirtMGW");
1288 }
Daniel Willmann191e0d92018-01-17 12:44:35 +01001289
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001290 for (var integer i := 0; i < nr_bts; i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001291 f_init_bts(i, c_BtsParams[i].trx_num, handler_mode);
Harald Welte696ddb62017-12-08 14:01:43 +01001292 }
Neels Hofmeyr9c0f9c82022-01-23 01:20:28 +01001293
1294 /* Emit a marker to appear in the SUT's own logging output */
1295 f_logp(BSCVTY, testcasename() & "() start");
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001296}
Harald Welte696ddb62017-12-08 14:01:43 +01001297
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001298function f_init_bts(integer bts_idx := 0,
1299 integer trx_num := NUM_TRX_CFG,
1300 boolean handler_mode := false)
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001301runs on test_CT {
1302 /* wait until osmo-bts-omldummy has respawned */
1303 f_wait_oml(bts_idx, "degraded", 5.0);
1304
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001305 /* start RSL connection(s) */
1306 for (var integer trx_idx := 0; trx_idx < trx_num; trx_idx := trx_idx + 1) {
1307 f_ipa_rsl_start(bts[bts_idx][trx_idx].rsl,
1308 mp_bsc_ip, mp_bsc_rsl_port,
1309 {bts_idx, trx_idx}, handler_mode);
1310 }
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001311 /* wait until BSC tells us "connected" */
1312 f_wait_oml(bts_idx, "connected", 5.0);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001313
1314 /* Set up BTS with VTY commands: */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01001315 f_vty_enter_cfg_bts(BSCVTY, bts_idx);
1316 if (g_osmux_enabled_bts) {
1317 f_vty_transceive(BSCVTY, "osmux on");
1318 } else {
1319 f_vty_transceive(BSCVTY, "osmux off");
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001320 }
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01001321 f_vty_transceive(BSCVTY, "end");
Harald Welte28d943e2017-11-25 15:00:50 +01001322}
1323
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001324function f_init_bts_and_check_sysinfo(integer bts_idx := 0,
1325 integer trx_num := NUM_TRX_CFG,
1326 boolean handler_mode := false,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001327 template SystemInformationConfig expect_si)
1328runs on test_CT {
1329 var default sysinfo := activate(as_catch_RSL_sysinfo(bts_idx));
1330
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001331 f_init_bts(bts_idx, trx_num, handler_mode);
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001332
1333 /* Give some time to (hopefully/most likely) collect all system informations from RSL startup.
1334 * We could stop as soon as all expected SI are received, but then we might miss SI that we don't expect and
1335 * that might be sent afterwards. So rather give a generous timeout and be quite sure to catch all SI.
1336 */
1337 f_sleep(5.0);
1338 log("RSL ", bts_idx, " SYSTEM INFORMATION: ", g_system_information[bts_idx]);
1339
1340 deactivate(sysinfo);
1341
1342 if (match(g_system_information[bts_idx], expect_si)) {
1343 setverdict(pass);
1344 } else {
1345 log("RSL ", bts_idx, ": EXPECTED SI: ", expect_si);
1346 log("RSL ", bts_idx, ": GOT SI: ", g_system_information[bts_idx]);
1347 setverdict(fail, "received SI does not match expectations");
1348 return;
1349 }
1350}
1351
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001352/* expect to receive a RSL message matching a specified template on a given BTS / TRX */
1353function f_exp_ipa_rx(template (present) RSL_Message t_rx,
1354 BtsTrxIdx idx := {0, 0},
1355 float Tval := 2.0)
Harald Welteae026692017-12-09 01:03:01 +01001356runs on test_CT return RSL_Message {
1357 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001358 timer T := Tval;
Harald Welteae026692017-12-09 01:03:01 +01001359
1360 T.start;
1361 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001362 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Harald Welteae026692017-12-09 01:03:01 +01001363 T.stop;
1364 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001365 [] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
Harald Welteb2917702017-12-10 15:48:52 +01001366 [] T.timeout {
1367 setverdict(fail, "Timeout expecting ", t_rx);
Daniel Willmannafce8662018-07-06 23:11:32 +02001368 mtc.stop;
Harald Welteb2917702017-12-10 15:48:52 +01001369 }
Harald Welteae026692017-12-09 01:03:01 +01001370 }
1371 return rx_rsl_ud.rsl;
1372}
1373
Harald Welte21b46bd2017-12-17 19:46:32 +01001374/* helper function to transmit RSL on a given BTS/stream */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001375function f_ipa_tx(template (value) RSL_Message t_tx,
1376 BtsTrxIdx idx := {0, 0},
1377 IpaStreamId sid := IPAC_PROTO_RSL_TRX0)
Harald Welteae026692017-12-09 01:03:01 +01001378runs on test_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001379 IPA_RSL[idx.bts][idx.trx].send(ts_ASP_RSL_UD(t_tx, sid));
Harald Welteae026692017-12-09 01:03:01 +01001380}
1381
1382
Harald Welte4003d112017-12-09 22:35:39 +01001383/* verify we get a CHAN_ACT after CHAN RQD */
Harald Welteae026692017-12-09 01:03:01 +01001384testcase TC_chan_act_noreply() runs on test_CT {
1385 var BSSAP_N_UNITDATA_ind ud_ind;
Harald Welte930d0a72018-03-22 22:08:40 +01001386 var RSL_Message rsl_unused;
Harald Welte28d943e2017-11-25 15:00:50 +01001387
Harald Welte89d42e82017-12-17 16:42:41 +01001388 f_init(1);
Harald Welte28d943e2017-11-25 15:00:50 +01001389
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001390 f_ipa_tx(ts_RSL_CHAN_RQD('23'O, 23));
1391 rsl_unused := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001392 f_shutdown_helper();
Harald Welte28d943e2017-11-25 15:00:50 +01001393}
1394
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001395const CounterNameVals counternames_bts_chreq := {
1396 { "chreq:total", 0 },
1397 { "chreq:attempted_emerg", 0 },
1398 { "chreq:attempted_call", 0 },
1399 { "chreq:attempted_location_upd", 0 },
1400 { "chreq:attempted_pag", 0 },
1401 { "chreq:attempted_pdch", 0 },
1402 { "chreq:attempted_other", 0 },
1403 { "chreq:attempted_unknown", 0 },
1404 { "chreq:successful", 0 },
1405 { "chreq:successful_emerg", 0 },
1406 { "chreq:successful_call", 0 },
1407 { "chreq:successful_location_upd", 0 },
1408 { "chreq:successful_pag", 0 },
1409 { "chreq:successful_pdch", 0 },
1410 { "chreq:successful_other", 0 },
1411 { "chreq:successful_unknown", 0 },
1412 { "chreq:no_channel", 0 },
1413 { "chreq:max_delay_exceeded", 0 }
1414};
1415
1416/* verify the "chreq:*" counters */
1417private function f_chan_act_counter(OCT1 ra, charstring chreq_ctr_suffix) runs on test_CT
1418{
1419 var GsmFrameNumber fn := 23;
1420
1421 f_logp(BSCVTY, "f_chan_act_counter(" & chreq_ctr_suffix & ")");
1422
1423 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001424 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn));
1425 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001426 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1427
1428 f_ctrs_bts_add(0, "chreq:total");
1429 f_ctrs_bts_add(0, "chreq:attempted_" & chreq_ctr_suffix);
1430 f_ctrs_bts_verify();
1431
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001432 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
1433 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001434
1435 f_ctrs_bts_add(0, "chreq:successful");
1436 f_ctrs_bts_add(0, "chreq:successful_" & chreq_ctr_suffix);
1437 f_ctrs_bts_verify();
1438
1439 /* test is done, release RSL Conn Fail Ind to clean up */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001440 f_ipa_tx(ts_RSL_CONN_FAIL_IND(chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1441 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
1442 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001443 f_sleep(1.0);
1444}
1445
Harald Welte4003d112017-12-09 22:35:39 +01001446testcase TC_chan_act_counter() runs on test_CT {
1447 var BSSAP_N_UNITDATA_ind ud_ind;
1448 var integer chreq_total;
Harald Welte930d0a72018-03-22 22:08:40 +01001449 var RSL_Message rsl_unused;
Harald Welte4003d112017-12-09 22:35:39 +01001450
Harald Welte89d42e82017-12-17 16:42:41 +01001451 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001452
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001453 f_vty_allow_emerg_bts(true, 0);
1454
1455 f_ctrs_bts_init(1, counternames_bts_chreq);
1456
1457 /* emergency call: RA & 0xe0 == 0xa0 --> CHREQ_T_EMERG_CALL */
1458 f_chan_act_counter('a3'O, "emerg");
1459
1460 /* voice TCH/H: RA & 0xf0 == 0x40 --> CHREQ_T_VOICE_CALL_TCH_H */
1461 f_chan_act_counter('43'O, "call");
1462
1463 /* LU: RA & 0xf0 == 0x00 --> CHREQ_T_LOCATION_UPD */
1464 f_chan_act_counter('03'O, "location_upd");
1465
1466 /* Paging: RA & 0xf0 == 0x20 --> CHREQ_T_PAG_R_TCH_F */
1467 f_chan_act_counter('23'O, "pag");
1468 /* Paging: RA & 0xf0 == 0x30 --> CHREQ_T_PAG_R_TCH_FH */
1469 f_chan_act_counter('33'O, "pag");
1470
1471 /* LU: RA & 0xfc == 0x78 --> CHREQ_T_PDCH_TWO_PHASE */
1472 /* no PCU, so PDCH not allowed. Skip this test for now. */
1473 /* f_chan_act_counter('7b'O, "pdch"); */
1474
1475 /* LU: RA & 0xf0 == 0x10 --> CHREQ_T_SDCCH */
1476 f_chan_act_counter('13'O, "other");
Harald Welte4003d112017-12-09 22:35:39 +01001477
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001478 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001479}
1480
Harald Welteae026692017-12-09 01:03:01 +01001481/* CHAN RQD -> CHAN ACT -> CHAN ACT ACK -> RF CHAN REL */
Philipp Maier9c60a622020-07-09 15:08:46 +02001482private function f_TC_chan_act_ack_noest(OCT1 ra := '23'O) runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +01001483 var RSL_Message rx_rsl;
1484
Harald Welteae026692017-12-09 01:03:01 +01001485 /* Send CHAN RQD and wait for allocation; acknowledge it */
Philipp Maier9c60a622020-07-09 15:08:46 +02001486 var RslChannelNr chan_nr := f_chreq_act_ack(ra);
Harald Welteae026692017-12-09 01:03:01 +01001487
1488 /* expect BSC to disable the channel again if there's no RLL EST IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001489 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := T3101_MAX);
Harald Welteae026692017-12-09 01:03:01 +01001490
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001491 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001492}
1493
Philipp Maier9c60a622020-07-09 15:08:46 +02001494/* Normal variant */
1495testcase TC_chan_act_ack_noest() runs on test_CT {
Philipp Maieraf58db22020-08-12 17:24:40 +02001496 f_init(1);
Philipp Maier9c60a622020-07-09 15:08:46 +02001497 f_TC_chan_act_ack_noest();
1498}
1499
1500/* Emergency call variant */
1501testcase TC_chan_act_ack_noest_emerg() runs on test_CT {
1502 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
Philipp Maieraf58db22020-08-12 17:24:40 +02001503 f_init(1);
1504 f_vty_allow_emerg_bts(true, 0);
Philipp Maier9c60a622020-07-09 15:08:46 +02001505 f_TC_chan_act_ack_noest(ra := 'A5'O);
1506}
1507
Philipp Maier606f07d2020-08-12 17:21:58 +02001508/* Emergency call variant, but emergency calls are not allowed */
1509testcase TC_chan_rqd_emerg_deny() runs on test_CT {
1510 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
1511
1512 var RSL_Message rx_rsl;
1513 var GsmRrMessage rr;
1514
1515 f_init(1);
1516 f_vty_allow_emerg_bts(false, 0);
1517
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001518 IPA_RSL[0][0].clear;
1519 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier606f07d2020-08-12 17:21:58 +02001520
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001521 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Philipp Maier606f07d2020-08-12 17:21:58 +02001522 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
1523 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1524 setverdict(pass);
1525 } else {
1526 setverdict(fail, "immediate assignment not rejected");
1527 }
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01001528
1529 f_shutdown_helper();
Philipp Maier606f07d2020-08-12 17:21:58 +02001530}
1531
Harald Welteae026692017-12-09 01:03:01 +01001532/* Test behavior if MSC never answers to CR */
1533testcase TC_chan_act_ack_est_ind_noreply() runs on test_CT {
Harald Weltef77aef62018-01-28 15:35:42 +01001534 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
1535 var IpaStreamId sid := IPAC_PROTO_RSL_TRX0;
Harald Welteae026692017-12-09 01:03:01 +01001536 var RSL_Message rx_rsl;
Harald Weltef77aef62018-01-28 15:35:42 +01001537 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001538 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welteae026692017-12-09 01:03:01 +01001539
Harald Welte89d42e82017-12-17 16:42:41 +01001540 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001541
1542 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001543 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001544
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001545 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welteae026692017-12-09 01:03:01 +01001546
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001547 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload)));
Harald Welteae026692017-12-09 01:03:01 +01001548
1549 /* expect BSC to disable the channel again if there's no response from MSC */
Harald Weltef77aef62018-01-28 15:35:42 +01001550 /* MS waits 20s (T3210) at LU; 10s (T3230) at CM SERV REQ and 5s (T3220) AT detach */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001551 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001552 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001553}
1554
1555/* Test behavior if MSC answers with CREF to CR */
1556testcase TC_chan_act_ack_est_ind_refused() runs on test_CT {
1557 var BSSAP_N_CONNECT_ind rx_c_ind;
1558 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001559 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welteae026692017-12-09 01:03:01 +01001560
Harald Welte89d42e82017-12-17 16:42:41 +01001561 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001562
1563 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001564 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001565
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001566 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welteae026692017-12-09 01:03:01 +01001567
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001568 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Harald Welteae026692017-12-09 01:03:01 +01001569 BSSAP.send(ts_BSSAP_DISC_req(rx_c_ind.connectionId, 0));
1570
1571 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001572 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001573 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001574}
1575
Harald Welte618ef642017-12-14 14:58:20 +01001576/* CHAN RQD -> CHAN ACT -> CHAN ACT NACK -> RF CHAN REL */
1577testcase TC_chan_act_nack() runs on test_CT {
1578 var RSL_Message rx_rsl;
1579 var integer chact_nack;
1580
Harald Welte89d42e82017-12-17 16:42:41 +01001581 f_init(1);
Harald Welte618ef642017-12-14 14:58:20 +01001582
1583 chact_nack := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack");
1584
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001585 f_ipa_tx(ts_RSL_CHAN_RQD('33'O, 33));
1586 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Harald Welte618ef642017-12-14 14:58:20 +01001587 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1588
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001589 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte618ef642017-12-14 14:58:20 +01001590
1591 /* wait for some time to hope the NACK arrives before the CTRL GET below */
1592 f_sleep(0.5);
1593
1594 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack", chact_nack+1);
1595
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001596 f_shutdown_helper();
Harald Welte618ef642017-12-14 14:58:20 +01001597}
1598
Harald Welte799c97b2017-12-14 17:50:30 +01001599/* Test for channel exhaustion due to RACH overload */
1600testcase TC_chan_exhaustion() runs on test_CT {
1601 var ASP_RSL_Unitdata rsl_ud;
1602 var integer i;
1603 var integer chreq_total, chreq_nochan;
1604
Harald Welte89d42e82017-12-17 16:42:41 +01001605 f_init(1);
Harald Welte799c97b2017-12-14 17:50:30 +01001606
1607 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
1608 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
1609
Neels Hofmeyr85fa37f2021-10-06 13:50:38 +02001610 /* GSM 44.018 Table 9.1.8.2:
Pau Espin Pedrolfe200d72018-12-10 12:41:04 +01001611 * RA = '33'O -> Establishment cause = 0011xxxx (MS dual rate capable and asks for "TCH/H or TCH/F").
1612 * With current setup, expect 4xSDCCH + 4xTCH/F + 1xTCH/H to succeed */
Philipp Maiercb6cc482018-03-26 13:08:00 +02001613 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 +01001614 var RslChannelNr chan_nr := f_chreq_act_ack('33'O, i);
Harald Welte799c97b2017-12-14 17:50:30 +01001615 }
1616
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001617 IPA_RSL[0][0].clear;
Harald Welte799c97b2017-12-14 17:50:30 +01001618
Harald Weltedd8cbf32018-01-28 12:07:52 +01001619 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001620 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
Harald Welte799c97b2017-12-14 17:50:30 +01001621
1622 /* now expect additional channel activations to fail */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001623 f_ipa_tx(ts_RSL_CHAN_RQD('42'O, 42));
Harald Welte799c97b2017-12-14 17:50:30 +01001624
1625 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001626 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV))) {
Harald Welte799c97b2017-12-14 17:50:30 +01001627 setverdict(fail, "Received CHAN ACT ACK without resources?!?");
1628 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001629 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) -> value rsl_ud {
Harald Welte799c97b2017-12-14 17:50:30 +01001630 var GsmRrMessage rr;
1631 /* match on IMM ASS REJ */
1632 rr := dec_GsmRrMessage(rsl_ud.rsl.ies[1].body.full_imm_ass_info.payload);
1633 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1634 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001635 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS+1);
Harald Welte799c97b2017-12-14 17:50:30 +01001636 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel",
1637 chreq_nochan+1);
1638 setverdict(pass);
1639 } else {
1640 repeat;
1641 }
1642 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001643 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte799c97b2017-12-14 17:50:30 +01001644 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001645 f_shutdown_helper();
Harald Welte799c97b2017-12-14 17:50:30 +01001646}
1647
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001648/* Test channel deactivation due to silence from MS */
1649testcase TC_chan_deact_silence() runs on test_CT {
1650 var RslChannelNr chan_nr;
1651
1652 f_init(1);
1653
1654 /* Request for a dedicated channel */
1655 chan_nr := f_chreq_act_ack('23'O);
1656
1657 /* Wait some time until the channel is released */
1658 f_sleep(2.0);
1659
1660 /* Expect CHANnel RELease */
1661 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001662 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001663 log("Received CHANnel RELease");
1664 setverdict(pass);
1665 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001666 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001667 /* See OS#3709, OsmoBSC should not send Immediate
1668 * Assignment Reject since a dedicated channel was
1669 * already allocated, and Immediate Assignment was
1670 * already sent. */
1671 setverdict(fail, "Unexpected Immediate Assignment!");
1672 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001673 [] IPA_RSL[0][0].receive {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001674 setverdict(fail, "Unexpected RSL message!");
1675 }
1676 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001677 f_shutdown_helper();
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001678}
1679
Harald Weltecfe2c962017-12-15 12:09:32 +01001680/***********************************************************************
1681 * Assignment Testing
1682 ***********************************************************************/
1683
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02001684/* Verify that the BSC refuses any BSSAP connection from the MSC (They are all BSC->MSC direction,
1685 * except for the inter-BSC handover, MT side) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001686testcase TC_outbound_connect(integer bssap_idx := 0) runs on test_CT {
Harald Welte89d42e82017-12-17 16:42:41 +01001687 f_init(1);
Harald Weltecfe2c962017-12-15 12:09:32 +01001688
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001689 BSSAP.send(ts_BSSAP_CONNECT_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
1690 2342, ts_BSSMAP_AssignmentReq));
Harald Weltecfe2c962017-12-15 12:09:32 +01001691 BSSAP.receive(tr_BSSAP_DISC_ind(2342, ?, ?));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001692 f_shutdown_helper();
Harald Weltecfe2c962017-12-15 12:09:32 +01001693}
1694
Harald Welte16a4adf2017-12-14 18:54:01 +01001695/* Test behavior if MSC answers with CREF to CR */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001696testcase TC_assignment_cic_only(integer bssap_idx := 0) runs on test_CT {
Harald Welte16a4adf2017-12-14 18:54:01 +01001697 var BSSAP_N_CONNECT_ind rx_c_ind;
1698 var RSL_Message rx_rsl;
1699 var DchanTuple dt;
1700
Harald Welte89d42e82017-12-17 16:42:41 +01001701 f_init(1);
Harald Welte16a4adf2017-12-14 18:54:01 +01001702
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001703 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001704 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte17b27da2018-05-25 20:33:53 +02001705 /* send assignment without AoIP IEs */
1706 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(ts_BSSMAP_IE_CIC(0, 1))));
1707 } else {
Pau Espin Pedrol35609792023-01-03 16:56:59 +01001708 /* Send assignment without CIC in IPA case */
Harald Welte17b27da2018-05-25 20:33:53 +02001709 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
1710 valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
1711 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(omit, tla)));
1712 }
Harald Welte16a4adf2017-12-14 18:54:01 +01001713 alt {
1714 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1715 setverdict(fail, "AoIP BSC cannot accept ASSIGNMENT without AoIP Transport IE");
1716 }
Harald Welte235ebf12017-12-15 14:18:16 +01001717 /* TODO: Actually expect GSM0808_CAUSE_REQ_A_IF_TYPE_NOT_SUPP */
Harald Welte16a4adf2017-12-14 18:54:01 +01001718 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1719 setverdict(pass);
1720 }
1721 [] BSSAP.receive { repeat; }
1722 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001723 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001724 f_shutdown_helper();
Harald Welte16a4adf2017-12-14 18:54:01 +01001725}
1726
Harald Welteed848512018-05-24 22:27:58 +02001727/* generate an assignment request for either AoIP or SCCPlite */
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001728function 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 +02001729 var PDU_BSSAP ass_cmd;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001730 var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001731 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welteed848512018-05-24 22:27:58 +02001732 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001733 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001734 if (osmux_enabled) {
1735 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla, osmux_cid));
1736 } else {
1737 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla));
1738 }
Harald Welteed848512018-05-24 22:27:58 +02001739 } else {
1740 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrol096d73d2019-06-06 12:49:17 +02001741 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(cic, omit));
Harald Welteed848512018-05-24 22:27:58 +02001742 }
1743 return ass_cmd;
1744}
1745
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02001746function f_gen_handover_req(integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4",
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001747 template (value) BSSMAP_IE_CellIdentifier cell_id_source := ts_CellID_LAC_CI(1, 1),
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001748 template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit,
1749 template (omit) TestHdlrEncrParams enc := omit) return PDU_BSSAP {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001750 var PDU_BSSAP ho_req;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001751
1752 var BSSMAP_IE_EncryptionInformation encryptionInformation :=
1753 valueof(ts_BSSMAP_IE_EncrInfo('0000000000000000'O,'01'O));
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03001754 var template (omit) BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := omit;
1755 var template (omit) BSSMAP_IE_KC128 kc128 := omit;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001756 if (ispresent(enc)) {
1757 var TestHdlrEncrParams v_enc := valueof(enc);
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01001758 encryptionInformation := valueof(ts_BSSMAP_IE_EncrInfo(v_enc.enc_key, v_enc.enc_alg_permitted));
1759 if (ispresent(v_enc.enc_alg_chosen)) {
1760 chosenEncryptionAlgorithm := valueof(
1761 ts_BSSMAP_IE_ChosenEncryptionAlgorithm(int2oct(enum2int(
1762 f_cipher_mode_bssmap_to_rsl(v_enc.enc_alg_chosen)), 1)));
1763 }
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001764 if (ispresent(v_enc.enc_kc128)) {
1765 kc128 := ts_BSSMAP_IE_Kc128(v_enc.enc_kc128);
1766 }
1767 }
1768
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001769 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001770 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001771 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001772 ho_req := valueof(ts_BSSMAP_HandoverRequest(omit, tla,
1773 cell_id_source := cell_id_source,
1774 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001775 encryptionInformation := encryptionInformation,
1776 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
Neels Hofmeyr9fe13202022-03-04 00:05:43 +01001777 kC128 := kc128,
1778 /* on AoIP, allow "all" codecs (until we add more concise
1779 * tests) */
1780 codecList := ts_BSSMAP_IE_CodecList(
1781 {ts_CodecAMR_F, ts_CodecAMR_H,
1782 ts_CodecEFR, ts_CodecFR, ts_CodecHR})));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001783 } else {
1784 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001785 ho_req := valueof(ts_BSSMAP_HandoverRequest(cic, omit,
1786 cell_id_source := cell_id_source,
1787 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001788 encryptionInformation := encryptionInformation,
1789 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
1790 kC128 := kc128));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001791 }
1792 return ho_req;
1793}
1794
Harald Welteed848512018-05-24 22:27:58 +02001795/* generate an assignment complete template for either AoIP or SCCPlite */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001796function f_gen_exp_compl(integer bssap_idx := 0)
1797runs on MSC_ConnHdlr return template PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001798 var template PDU_BSSAP exp_compl;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001799 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001800 var template BSSMAP_IE_Osmo_OsmuxCID exp_osmux_cid := omit;
1801 if (g_pars.use_osmux_cn) {
1802 var template (present) INT1 exp_cid := ?;
1803 if (isbound(g_media.mgcp_conn[0].local_osmux_cid) and isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1804 exp_cid := (g_media.mgcp_conn[0].local_osmux_cid, g_media.mgcp_conn[1].local_osmux_cid);
1805 } else if (isbound(g_media.mgcp_conn[0].local_osmux_cid)) {
1806 exp_cid := g_media.mgcp_conn[0].local_osmux_cid;
1807 } else if (isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1808 exp_cid := g_media.mgcp_conn[1].local_osmux_cid;
1809 }
1810 exp_osmux_cid := tr_OsmuxCID(exp_cid);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001811 }
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001812 exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, exp_osmux_cid);
Harald Welteed848512018-05-24 22:27:58 +02001813 } else {
1814 /* CIC is optional "*" as the MSC allocated it */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001815 exp_compl := tr_BSSMAP_AssignmentComplete(*, omit, omit);
Harald Welteed848512018-05-24 22:27:58 +02001816 }
1817 return exp_compl;
1818}
1819
Harald Welte235ebf12017-12-15 14:18:16 +01001820/* Run everything required up to sending a caller-specified assignment command and expect response */
1821function f_assignment_exp(PDU_BSSAP ass_cmd, template PDU_BSSAP exp, charstring fail_text)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001822runs on test_CT return DchanTuple {
Harald Welte235ebf12017-12-15 14:18:16 +01001823 var BSSAP_N_CONNECT_ind rx_c_ind;
1824 var RSL_Message rx_rsl;
1825 var DchanTuple dt;
1826
Harald Welte89d42e82017-12-17 16:42:41 +01001827 f_init(1);
Harald Welte235ebf12017-12-15 14:18:16 +01001828
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001829 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte235ebf12017-12-15 14:18:16 +01001830 /* send assignment without AoIP IEs */
1831 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
1832 alt {
1833 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1834 if (ischosen(exp.pdu.bssmap.assignmentComplete)) {
1835 setverdict(pass);
1836 } else {
1837 setverdict(fail, fail_text);
1838 }
1839 }
1840 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1841 if (ischosen(exp.pdu.bssmap.assignmentFailure)) {
1842 setverdict(pass);
1843 } else {
1844 setverdict(fail, fail_text);
1845 }
1846 }
1847 [] BSSAP.receive { repeat; }
1848 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001849 return dt;
Harald Welte235ebf12017-12-15 14:18:16 +01001850}
Oliver Smithdd002752023-02-21 13:35:00 +01001851
1852private function f_tc_assignment_csd(charstring id) runs on MSC_ConnHdlr {
1853 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welteed848512018-05-24 22:27:58 +02001854 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Oliver Smithbc392a82023-04-17 14:06:42 +02001855 var SDP_FIELD_PayloadType pt_csd := PT_CSD;
Oliver Smithdd002752023-02-21 13:35:00 +01001856
Harald Welte235ebf12017-12-15 14:18:16 +01001857 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smithdd002752023-02-21 13:35:00 +01001858 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecCSData}));
1859
1860 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := GSM0808_DATA_RATE_TRANSP_4k8;
1861
1862 f_establish_fully(ass_cmd, exp_compl);
Oliver Smithbc392a82023-04-17 14:06:42 +02001863
1864 if (g_media.bts.rtp_pt != enum2int(pt_csd)) {
1865 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("unexpected RTP payload type: ", g_media.bts.rtp_pt));
1866 }
1867
Oliver Smithdd002752023-02-21 13:35:00 +01001868 f_perform_clear();
1869}
1870testcase TC_assignment_csd() runs on test_CT {
1871 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.10.0 */
1872 var MSC_ConnHdlr vc_conn;
1873 var TestHdlrParams pars := f_gen_test_hdlr_pars();
1874 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
1875
1876 f_init(1, true);
1877 f_sleep(1.0);
1878 vc_conn := f_start_handler(refers(f_tc_assignment_csd), pars);
1879 vc_conn.done;
1880 } else {
1881 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
1882 var PDU_BSSAP ass_cmd := f_gen_ass_req();
1883 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
1884 //exp_fail.pdu.bssmap.assignmentFailure.cause.causeValue := int2bit(enum2int(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL), 7);
1885 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for CSD");
1886 f_perform_clear_test_ct(dt);
1887 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001888 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001889}
1890
1891testcase TC_assignment_ctm() runs on test_CT {
1892 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001893 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001894 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
1895 //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 +01001896 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
1897 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001898 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001899}
1900
Harald Welte4003d112017-12-09 22:35:39 +01001901type record DchanTuple {
1902 integer sccp_conn_id,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001903 RslChannelNr rsl_chan_nr,
1904 BtsTrxIdx idx
Harald Weltea5d2ab22017-12-09 14:21:42 +01001905}
1906
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +02001907type record of DchanTuple DchanTuples;
1908
Harald Welted6939652017-12-13 21:02:46 +01001909/* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001910private function f_chreq_act_ack(OCT1 ra := '23'O,
1911 GsmFrameNumber fn := 23,
1912 BtsTrxIdx idx := {0, 0})
Harald Welted6939652017-12-13 21:02:46 +01001913runs on test_CT return RslChannelNr {
1914 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001915 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
1916 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Harald Welted6939652017-12-13 21:02:46 +01001917 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001918 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10), idx);
1919 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Harald Welted6939652017-12-13 21:02:46 +01001920 return chan_nr;
1921}
1922
Harald Welte4003d112017-12-09 22:35:39 +01001923/* helper function to establish a dedicated channel via BTS and MSC */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001924function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1925 BtsTrxIdx idx := {0, 0})
Harald Welte4003d112017-12-09 22:35:39 +01001926runs on test_CT return DchanTuple {
1927 var BSSAP_N_CONNECT_ind rx_c_ind;
Harald Welte4003d112017-12-09 22:35:39 +01001928 var DchanTuple dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001929
Harald Welte4003d112017-12-09 22:35:39 +01001930 /* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001931 dt.rsl_chan_nr := f_chreq_act_ack(ra, fn, idx);
Harald Welte4003d112017-12-09 22:35:39 +01001932
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001933 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 +01001934
1935 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1936 dt.sccp_conn_id := rx_c_ind.connectionId;
1937 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1938
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001939 dt.idx := idx;
Harald Welte4003d112017-12-09 22:35:39 +01001940 return dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001941}
1942
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001943/* 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 +06001944function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1945 BtsTrxIdx idx := {0, 0})
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001946runs on test_CT return DchanTuple {
1947 var BSSAP_N_CONNECT_ind rx_c_ind;
1948 var DchanTuple dt;
1949
1950 /* Send CHAN RQD */
1951 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001952 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001953
1954 /* The dyn TS first deactivates PDCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001955 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 +02001956 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001957 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001958
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001959 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001960 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1961
1962 /* Now activates the signalling channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001963 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10), idx);
1964 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001965
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001966 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 +02001967
1968 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1969 dt.sccp_conn_id := rx_c_ind.connectionId;
1970 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1971
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001972 dt.idx := idx;
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001973 return dt;
1974}
1975
Harald Welte641fcbe2018-06-14 10:58:35 +02001976/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001977private function f_exp_chan_rel_and_clear(DchanTuple dt)
1978runs on test_CT {
Harald Welte641fcbe2018-06-14 10:58:35 +02001979 var RSL_Message rx_rsl;
1980 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001981 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 +02001982 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001983 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), dt.idx);
Harald Welte641fcbe2018-06-14 10:58:35 +02001984
1985 /* expect Clear Complete from BSC */
1986 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
1987
1988 /* MSC disconnects as instructed. */
1989 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
1990}
1991
Harald Welte4003d112017-12-09 22:35:39 +01001992/* Test behavior of channel release after unilateral RLL REL IND (DISC from MS) */
1993testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001994 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01001995 var DchanTuple dt;
Harald Welte96c94412017-12-09 03:12:45 +01001996
Harald Welte89d42e82017-12-17 16:42:41 +01001997 f_init(1);
Harald Welte96c94412017-12-09 03:12:45 +01001998
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001999 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002000
2001 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002002 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Harald Welte4003d112017-12-09 22:35:39 +01002003
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002004 /* expect Clear Request on MSC side */
2005 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2006
2007 /* Instruct BSC to clear channel */
2008 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2009 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2010
Harald Welte4003d112017-12-09 22:35:39 +01002011 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002012 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002013
2014 /* wait for SCCP emulation to do its job */
2015 f_sleep(1.0);
Harald Welte4003d112017-12-09 22:35:39 +01002016
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002017 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002018}
2019
2020/* Test behavior of channel release after CONN FAIL IND from BTS */
2021testcase TC_chan_rel_conn_fail() runs on test_CT {
2022 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002023 var DchanTuple dt;
2024
Harald Welte89d42e82017-12-17 16:42:41 +01002025 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002026
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002027 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002028
Vadim Yanitskiy01d0a902022-12-14 22:41:42 +07002029 /* Sending CONN FAIL IND immediately may trigger a race condition.
2030 * Give the BSC some time to process a new SCCP connection (OS#5823). */
2031 f_sleep(0.2);
2032
Harald Welte4003d112017-12-09 22:35:39 +01002033 /* simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002034 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte4003d112017-12-09 22:35:39 +01002035 /* TODO: different cause values? */
2036
Harald Welte4003d112017-12-09 22:35:39 +01002037 /* expect Clear Request from BSC */
2038 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2039
2040 /* Instruct BSC to clear channel */
2041 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2042 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2043
Harald Welte6ff76ea2018-01-28 13:08:01 +01002044 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002045 f_exp_chan_rel_and_clear(dt);
Harald Welte4003d112017-12-09 22:35:39 +01002046
2047 /* wait for SCCP emulation to do its job */
2048 f_sleep(1.0);
2049
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002050 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002051}
2052
Harald Welte99f3ca02018-06-14 13:40:29 +02002053/* Test behavior of early CONN FAIL IND from BTS (before EST IND!) */
2054/* See also https://www.osmocom.org/issues/3182 */
2055testcase TC_early_conn_fail() runs on test_CT {
2056 var RSL_Message rx_rsl;
2057 var DchanTuple dt;
2058
2059 f_init(1);
2060
2061 /* BTS->BSC: Send CHAN RQD and wait for allocation; acknowledge it */
Harald Weltec46ea3c2020-10-10 18:46:12 +02002062 dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_ra_cs(), 23);
Harald Welte99f3ca02018-06-14 13:40:29 +02002063
2064 /* BTS->BSC: simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002065 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002066
2067 /* BTS->BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002068 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002069
2070 /* BTS<-BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002071 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002072
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002073 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002074}
2075
2076/* Test behavior of late CONN FAIL IND from BTS (ater REL IND!) */
2077/* See also https://www.osmocom.org/issues/3182 */
2078testcase TC_late_conn_fail() runs on test_CT {
2079 var RSL_Message rx_rsl;
2080 var DchanTuple dt;
2081
2082 f_init(1);
2083
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002084 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99f3ca02018-06-14 13:40:29 +02002085
2086 /* BSC<-MSC: Instruct BSC to clear connection */
2087 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(0)));
2088
2089 /* BTS->BSC: expect BSC to deactivate SACCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002090 rx_rsl := f_exp_ipa_rx(tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002091
2092 /* BTS->BSC: simulate a late CONN FAIL IND from BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002093 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002094
2095 /* BTS<-BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002096 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002097 /* BTS->BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002098 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002099
2100 /* BSC->MSC: expect Clear Complete from BSC */
2101 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2102
2103 /* BSC<-MSC: MSC disconnects as requested. */
2104 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2105
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002106 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002107}
2108
Oliver Smithaf03bef2021-08-24 15:34:51 +02002109private function f_TC_stats_conn_fail(charstring id) runs on MSC_ConnHdlr {
2110 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
2111 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2112
2113 f_statsd_reset();
2114
Oliver Smith15890b42023-03-08 14:12:28 +01002115 /* Establish SDCCH (invalid DataIndicator for exp_fail) */
Oliver Smithaf03bef2021-08-24 15:34:51 +02002116 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smith15890b42023-03-08 14:12:28 +01002117 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := 'ff'O;
Oliver Smithaf03bef2021-08-24 15:34:51 +02002118 f_establish_fully(ass_cmd, exp_fail);
2119
2120 /* Expect stats to be 0 */
2121 var StatsDExpects expect := {
2122 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
2123 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
2124 };
2125 f_statsd_expect(expect);
2126
2127 /* Simulate CONN FAIL IND on SDCCH */
2128 RSL.send(ts_ASP_RSL_UD(
2129 ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
2130 IPAC_PROTO_RSL_TRX0));
2131
Neels Hofmeyr58be48a2021-09-07 18:39:21 +02002132 f_sleep(1.0);
2133
Oliver Smithaf03bef2021-08-24 15:34:51 +02002134 /* Expect stats to be 1 */
2135 expect := {
2136 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
2137 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
2138 };
2139 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002140 BSSAP.receive(tr_BSSMAP_ClearRequest);
2141 f_perform_clear();
Oliver Smithaf03bef2021-08-24 15:34:51 +02002142}
2143testcase TC_stats_conn_fail() runs on test_CT {
2144 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2145 var MSC_ConnHdlr vc_conn;
2146
2147 f_init(1, true);
2148 f_sleep(1.0);
2149
2150 vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
2151 vc_conn.done;
2152
2153 f_shutdown_helper();
2154}
2155
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002156function f_expect_chan_rel(RslChannelNr rsl_chan_nr,
2157 BtsTrxIdx idx := {0, 0},
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002158 boolean expect_deact_sacch := true,
2159 boolean expect_rr_chan_rel := true,
2160 boolean expect_rll_rel_req := true,
Harald Welte99787102019-02-04 10:41:36 +01002161 boolean handle_rll_rel := true,
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002162 template CellSelIndValue expect_cells := omit,
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002163 template (present) RR_Cause expect_rr_cause := ?
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002164 ) runs on test_CT {
Harald Welte91d54a52018-01-28 15:35:07 +01002165
2166 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002167 var boolean got_deact_sacch := false;
2168 var boolean got_rr_chan_rel := false;
2169 var boolean got_rll_rel_req := false;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002170 var ASP_RSL_Unitdata ud;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002171 var RSL_IE_Body l3_ie;
2172 var PDU_ML3_NW_MS l3;
2173 var RR_Cause got_cause;
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002174 log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
2175 " expect_rll_rel_req=", expect_rll_rel_req);
Harald Welte91d54a52018-01-28 15:35:07 +01002176 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002177 [] 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 +01002178 got_deact_sacch := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002179 repeat;
2180 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002181 [] 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 +01002182 got_rr_chan_rel := true;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002183
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002184 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2185 setverdict(fail, "cannot find L3");
2186 mtc.stop;
2187 }
2188 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2189
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002190 if (not istemplatekind(expect_cells, "omit")) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002191 var CellSelIndValue cells := dec_CellSelIndValue(
2192 l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
2193
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002194 log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
2195 if (match(cells, expect_cells)) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002196 setverdict(pass);
2197 } else {
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002198 log("EXPECTED CELLS: ", expect_cells);
2199 setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002200 }
2201 }
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002202
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002203 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2204 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2205 if (match(got_cause, expect_rr_cause)) {
2206 setverdict(pass);
2207 } else {
2208 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2209 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002210 }
Harald Welte99787102019-02-04 10:41:36 +01002211 repeat;
2212 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002213 [] 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 +01002214 got_rll_rel_req := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002215 /* FIXME: Why are we getting this for LinkID SACCH? */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002216 if (handle_rll_rel) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002217 f_ipa_tx(ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002218 }
Harald Welte91d54a52018-01-28 15:35:07 +01002219 repeat;
2220 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002221 [] 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 +01002222 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002223 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
Harald Welte91d54a52018-01-28 15:35:07 +01002224 }
2225 /* ignore any user data */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002226 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002227 repeat;
2228 }
2229 }
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002230
2231 log("f_expect_chan_rel() summary: got_deact_sacch=", got_deact_sacch, " got_rr_chan_rel=", got_rr_chan_rel,
2232 " got_rll_rel_req=", got_rll_rel_req);
2233
2234 if (expect_deact_sacch != got_deact_sacch) {
2235 setverdict(fail, "f_expect_chan_rel(): expect_deact_sacch=", expect_deact_sacch, " got_deact_sacch=", got_deact_sacch);
2236 }
2237 if (expect_rr_chan_rel != got_rr_chan_rel) {
2238 setverdict(fail, "f_expect_chan_rel(): expect_rr_chan_rel=", expect_rr_chan_rel, " got_rr_chan_rel=", got_rr_chan_rel);
2239 }
2240 if (expect_rll_rel_req != got_rll_rel_req) {
2241 setverdict(fail, "f_expect_chan_rel(): expect_rll_rel_req=", expect_rll_rel_req, " got_rll_rel_req=", got_rll_rel_req);
2242 }
Harald Welte91d54a52018-01-28 15:35:07 +01002243}
2244
Harald Welte4003d112017-12-09 22:35:39 +01002245/* Test behavior of channel release after hard Clear Command from MSC */
2246testcase TC_chan_rel_hard_clear() runs on test_CT {
2247 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002248 var DchanTuple dt;
Harald Welte4003d112017-12-09 22:35:39 +01002249
Harald Welte89d42e82017-12-17 16:42:41 +01002250 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002251
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002252 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002253
2254 /* Instruct BSC to clear channel */
2255 var BssmapCause cause := 0;
2256 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2257
2258 /* expect Clear Complete from BSC on A */
2259 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2260 /* release the SCCP connection */
2261 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2262 }
2263
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002264 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002265 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002266}
2267
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002268function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
2269 var BSSAP_N_DATA_ind rx_di;
2270 var DchanTuple dt;
2271
2272 f_init(1);
2273
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002274 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002275 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2276 /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
2277 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
2278
2279 /* Instruct BSC to clear channel */
2280 var BssmapCause cause := 0;
2281 if (tx_csfb_ind) {
2282 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2283 } else {
2284 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2285 }
2286
2287 /* expect Clear Complete from BSC on A */
2288 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2289 /* release the SCCP connection */
2290 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2291 }
2292
2293 /* 1 neighbor is added by default in osmo-bts.cfg and
2294 SystemInformationConfig_default, use that: */
2295 var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
2296
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002297 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 +02002298 f_shutdown_helper();
2299}
2300
2301/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
2302 from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
2303 PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2304 EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
2305 Indicator or not shouldn't matter at all. */
2306testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
2307 f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
2308}
2309
2310/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
2311 MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
2312 Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2313 EUTRAN neighbor list sent later on by BSC in RR Channel. */
2314testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
2315 f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
2316}
2317
2318/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
2319 MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
2320 Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
2321 CSFB Indicator should not be used anymore, and hence, there should be no
2322 EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
2323 Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
Harald Welte99787102019-02-04 10:41:36 +01002324testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
2325 var BSSAP_N_DATA_ind rx_di;
2326 var DchanTuple dt;
2327
2328 f_init(1);
2329
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002330 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99787102019-02-04 10:41:36 +01002331
2332 /* Instruct BSC to clear channel */
2333 var BssmapCause cause := 0;
2334 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2335
2336 /* expect Clear Complete from BSC on A */
2337 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2338 /* release the SCCP connection */
2339 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2340 }
2341
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002342 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002343 f_shutdown_helper();
Harald Welte99787102019-02-04 10:41:36 +01002344}
2345
Harald Welted8c36cd2017-12-09 23:05:31 +01002346/* Test behavior of channel release after hard RLSD from MSC */
2347testcase TC_chan_rel_hard_rlsd() runs on test_CT {
Harald Welted8c36cd2017-12-09 23:05:31 +01002348 var DchanTuple dt;
Harald Welted8c36cd2017-12-09 23:05:31 +01002349
Harald Welte89d42e82017-12-17 16:42:41 +01002350 f_init(1);
Harald Welted8c36cd2017-12-09 23:05:31 +01002351
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002352 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welted8c36cd2017-12-09 23:05:31 +01002353
2354 /* release the SCCP connection */
2355 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2356
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002357 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002358 f_shutdown_helper();
Harald Welted8c36cd2017-12-09 23:05:31 +01002359}
2360
Harald Welte550daf92018-06-11 19:22:13 +02002361/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
2362testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
2363 var DchanTuple dt;
2364
2365 f_init(1);
2366
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002367 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte550daf92018-06-11 19:22:13 +02002368
2369 /* release the SCCP connection */
2370 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2371
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002372 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002373 f_shutdown_helper();
Harald Welte550daf92018-06-11 19:22:13 +02002374}
2375
Harald Welte85804d42017-12-10 14:11:58 +01002376/* Test behavior of channel release after BSSMAP RESET from MSC */
2377testcase TC_chan_rel_a_reset() runs on test_CT {
Harald Welte85804d42017-12-10 14:11:58 +01002378 var DchanTuple dt;
Harald Welte85804d42017-12-10 14:11:58 +01002379
Harald Welte89d42e82017-12-17 16:42:41 +01002380 f_init(1);
Harald Welte85804d42017-12-10 14:11:58 +01002381
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002382 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte85804d42017-12-10 14:11:58 +01002383
2384 /* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002385 IPA_RSL[0][0].clear;
Harald Welte85804d42017-12-10 14:11:58 +01002386
2387 /* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002388 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 +01002389 interleave {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002390 [] 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 +01002391 [] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
2392 }
2393
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002394 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002395 f_shutdown_helper();
Harald Welte85804d42017-12-10 14:11:58 +01002396}
2397
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002398/* Verify T(iar) triggers and releases the channel */
2399testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
2400 var DchanTuple dt;
2401
2402 /* Set T(iar) in BSC low enough that it will trigger before other side
2403 has time to keep alive with a T(ias). Keep recommended ratio of
2404 T(iar) >= T(ias)*2 */
2405 g_bsc_sccp_timer_ias := 2;
2406 g_bsc_sccp_timer_iar := 5;
2407
2408 f_init(1);
2409
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002410 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002411 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002412 f_shutdown_helper();
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002413}
2414
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002415private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause,
2416 template (present) RR_Cause expect_rr_cause)
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002417runs on test_CT
2418{
2419 var DchanTuple dt;
2420
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002421 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002422 var BssmapCause cause := 0;
2423 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
2424 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2425 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2426 }
2427
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002428 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 +02002429}
2430
2431/* Test that Clear Command cause codes affect the RR Channel Release cause code */
2432testcase TC_chan_rel_rr_cause() runs on test_CT {
2433 f_init(1);
2434
2435 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
2436 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
2437 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
2438 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
2439 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
2440 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
Vadim Yanitskiye18aebb2021-01-03 13:10:43 +01002441
2442 f_shutdown_helper();
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002443}
2444
Harald Welte5cd20ed2017-12-13 21:03:20 +01002445/* Test behavior if RSL EST IND for non-active channel */
2446testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
2447 timer T := 2.0;
2448
Harald Welte89d42e82017-12-17 16:42:41 +01002449 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002450
Harald Welte5cd20ed2017-12-13 21:03:20 +01002451 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002452 var octetstring l3_payload := gen_l3_valid_payload();
2453 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002454
2455 T.start;
2456 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002457 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002458 setverdict(fail, "MSC received COMPL L3 for non-active lchan");
2459 }
2460 [] BSSAP.receive {}
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002461 [] IPA_RSL[0][0].receive {}
Harald Welte5cd20ed2017-12-13 21:03:20 +01002462 [] T.timeout {}
2463 }
2464
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002465 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002466}
2467
2468/* Test behavior if RSL EST IND for invalid SAPI */
2469testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
2470 var RslChannelNr chan_nr;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002471 var octetstring l3_payload;
Harald Welte5cd20ed2017-12-13 21:03:20 +01002472
Harald Welte89d42e82017-12-17 16:42:41 +01002473 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002474
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002475 chan_nr := f_chreq_act_ack();
2476 l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002477
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002478 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002479
2480 timer T := 2.0;
2481 T.start;
2482 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002483 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002484 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
2485 }
2486 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002487 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002488 [] T.timeout {}
2489 }
2490
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002491 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002492}
2493
2494/* Test behavior if RSL EST IND for invalid SAPI */
2495testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
2496 timer T := 2.0;
2497
Harald Welte89d42e82017-12-17 16:42:41 +01002498 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002499
2500 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002501 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002502
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002503 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002504
2505 T.start;
2506 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002507 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002508 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
2509 }
2510 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002511 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002512 [] T.timeout {}
2513 }
2514
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002515 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002516}
2517
2518/* Test behavior if RSL EST IND for invalid SACCH */
2519testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
2520 timer T := 2.0;
2521
Harald Welte89d42e82017-12-17 16:42:41 +01002522 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002523
2524 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002525 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002526
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002527 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002528
2529 T.start;
2530 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002531 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002532 setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
2533 }
2534 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002535 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002536 [] T.timeout {}
2537 }
2538
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002539 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002540}
2541
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002542/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
2543private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
2544 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
2545 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2546
2547 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
2548 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
2549
2550 f_establish_fully(ass_cmd, exp_compl);
2551
2552 /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
2553 RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
2554 /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
2555 BSSAP.receive(PDU_BSSAP:{
2556 discriminator := '1'B,
2557 spare := '0000000'B,
2558 dlci := 'C3'O,
2559 lengthIndicator := ?,
2560 pdu := { dtap := '0904'O }
2561 });
2562
2563 /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
2564 for (var integer i := 0; i < 32; i := i + 1) {
2565 var octetstring l3 := '09'O & f_rnd_octstring(14);
2566 var template (value) RslLinkId link_id;
2567 var template (value) OCT1 dlci;
2568
2569 if (i mod 2 == 0) {
2570 /* SAPI0 on FACCH or SDCCH */
2571 link_id := ts_RslLinkID_DCCH(0);
2572 dlci := '80'O;
2573 } else {
2574 /* SAPI3 on SACCH */
2575 link_id := ts_RslLinkID_SACCH(3);
2576 dlci := 'C3'O;
2577 }
2578
2579 /* Send MO message: RSL -> BSSAP */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002580 f_mo_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002581 /* Send MT message: BSSAP -> RSL */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002582 f_mt_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002583 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002584 f_perform_clear();
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002585}
2586testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
2587 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2588 var MSC_ConnHdlr vc_conn;
2589
2590 f_init(1, true);
2591 f_sleep(1.0);
2592
2593 vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
2594 vc_conn.done;
2595
2596 f_shutdown_helper();
2597}
2598
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002599private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002600 template (present) myBSSMAP_Cause cause := ?,
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002601 template (present) BIT2 cc := ?,
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002602 float T_val := 2.0)
2603runs on test_CT {
2604 var BSSAP_N_DATA_ind rx_di;
2605 timer T;
2606
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002607 var template (present) BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
2608 var template (present) PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002609
2610 T.start(T_val);
2611 alt {
2612 [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
2613 var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
2614 if (not match(rx_cause, tr_cause)) {
2615 setverdict(fail, "Rx unexpected Cause IE: ",
2616 rx_cause, " vs expected ", tr_cause);
2617 }
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002618
2619 /* Who ever on the earth decided to define this field as two separate bits?!? */
2620 var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
2621 & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
2622 if (not match(rx_cc, cc)) {
2623 setverdict(fail, "Rx unexpected Control Channel type: ",
2624 rx_cc, " vs expected ", cc);
2625 }
2626
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002627 setverdict(pass);
2628 }
2629 [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
2630 setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
2631 }
2632 [] T.timeout {
2633 setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
2634 }
2635 }
2636}
2637
2638/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
2639testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002640 var RSL_Message rx_rsl;
2641 var DchanTuple dt;
2642
2643 f_init(1);
2644
2645 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002646 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002647
2648 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002649 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 +07002650 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002651 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 +07002652
2653 /* MS sends unexpected RELease INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002654 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002655 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2656 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
2657
2658 /* Clean up the connection */
2659 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002660 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002661
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002662 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002663}
2664
2665/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
2666testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002667 var RSL_Message rx_rsl;
2668 var DchanTuple dt;
2669
2670 f_init(1);
2671
2672 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002673 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002674
2675 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002676 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(gen_l3_valid_payload(), '03'O)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002677 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002678 rx_rsl := f_exp_ipa_rx(tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002679
2680 /* BTS sends unexpected ERROR INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002681 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002682 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2683 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
2684
2685 /* Clean up the connection */
2686 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002687 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002688
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002689 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002690}
2691
2692/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
2693testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002694 var RSL_Message rx_rsl;
2695 var DchanTuple dt;
2696
2697 f_init(1);
2698
2699 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002700 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002701
2702 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002703 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(gen_l3_valid_payload(), '03'O)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002704 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002705 rx_rsl := f_exp_ipa_rx(tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002706
2707 /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
2708 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
2709
2710 /* Clean up the connection */
2711 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002712 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002713
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002714 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002715}
2716
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002717/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
2718testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002719 var RSL_Message rx_rsl;
2720 var DchanTuple dt;
2721
2722 f_init(1);
2723
2724 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002725 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002726
2727 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002728 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 +07002729 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002730 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 +07002731
2732 /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002733 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Pau Espin Pedrol121f27f2022-01-12 12:02:10 +01002734 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, '10'B);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002735
2736 /* Clean up the connection */
2737 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002738 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002739
2740 f_shutdown_helper();
2741}
2742
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002743testcase TC_si_default() runs on test_CT {
2744 f_init(0);
2745 f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002746 f_shutdown_helper();
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002747}
Harald Welte4003d112017-12-09 22:35:39 +01002748
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002749/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
2750 * the entire value range. This function provides the same EARFCN numbers for the same earfcn_index */
2751private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uint16_t
2752{
2753 select (earfcn_index) {
2754 case (0) {
2755 /* E-ARFCN 111 is already added in the osmo-bsc.cfg */
2756 return 111;
2757 }
2758 case (1) {
2759 return 1;
2760 }
2761 case (2) {
2762 return 0;
2763 }
2764 case (3) {
2765 return 65535;
2766 }
2767 case else {
2768 return 23 * (earfcn_index - 3);
2769 }
2770 }
2771}
2772
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002773function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
2774 template CellSelIndValue expect_cells := omit) runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002775
2776 f_init(0);
2777
2778 /* E-ARFCN 111 is already added in the osmo-bsc.cfg, so only add more arfcns if total_earfcns > 1 */
2779 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002780 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2781 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002782 }
2783
2784 f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
2785
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002786 if (not istemplatekind(expect_cells, "omit")) {
2787 /* Also check that RR Channel Release contains these EARFCNs.
2788 * (copied code from TC_chan_rel_hard_clear_csfb) */
2789 var BSSAP_N_DATA_ind rx_di;
2790 var DchanTuple dt;
2791
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002792 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrold0046312021-04-19 16:35:58 +02002793 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2794 * yet when generating the EUTRAN neigh list in RR CHannel Release) */
2795 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002796
2797 /* Instruct BSC to clear channel */
2798 var BssmapCause cause := 0;
2799 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2800
2801 /* expect Clear Complete from BSC on A */
2802 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2803 /* release the SCCP connection */
2804 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2805 }
2806
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002807 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := expect_cells);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002808 }
2809
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002810 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002811 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 +02002812 }
2813}
2814
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002815private function f_tr_si2quater_earfcns(integer count) return template SI2quaterRestOctetsList
2816{
2817 var template SI2quaterRestOctetsList si2quater := {};
2818 var integer si2quater_count := (count + 2) / 3;
2819
2820 for (var integer i := 0; i < count; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002821 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002822 var integer index := i / 3;
2823 var integer earfcn_index := i mod 3;
2824 if (index >= lengthof(si2quater)) {
2825 si2quater[index] := tr_SI2quaterRestOctets_EUTRAN(index := index, count := si2quater_count - 1);
2826 }
2827 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);
2828 }
2829
2830 return si2quater;
2831}
2832
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002833private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
2834{
2835 var template CellSelIndValue_EUTRAN_Descrs cells := {};
2836
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002837 /* the lte neighbors must match the config & vty to pass this test */
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002838 for (var integer i := 0; i < count; i := i + 1) {
2839 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002840 cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002841 }
2842
2843 return tr_CellSelIndValue_EUTRAN(cells);
2844}
2845
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002846private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
2847{
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002848 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrol8ab62e42020-12-18 16:19:11 +01002849 sic.si2quater := f_tr_si2quater_earfcns(n);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002850 var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
2851 f_test_si2quater(n, sic, cells);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002852}
2853
2854testcase TC_si2quater_2_earfcns() runs on test_CT {
2855 f_tc_si2quater_n_earfcns(2);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002856 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002857}
2858
2859testcase TC_si2quater_3_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002860 f_tc_si2quater_n_earfcns(3);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002861 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002862}
2863
2864testcase TC_si2quater_4_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002865 f_tc_si2quater_n_earfcns(4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002866 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002867}
2868
2869testcase TC_si2quater_5_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002870 f_tc_si2quater_n_earfcns(5);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002871 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002872}
2873
2874testcase TC_si2quater_6_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002875 f_tc_si2quater_n_earfcns(6);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002876 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002877}
2878
2879testcase TC_si2quater_12_earfcns() runs on test_CT {
2880 f_tc_si2quater_n_earfcns(12);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002881 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002882}
2883
2884testcase TC_si2quater_23_earfcns() runs on test_CT {
2885 f_tc_si2quater_n_earfcns(23);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002886 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002887}
2888
2889testcase TC_si2quater_32_earfcns() runs on test_CT {
2890 f_tc_si2quater_n_earfcns(32);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002891 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002892}
2893
2894testcase TC_si2quater_33_earfcns() runs on test_CT {
2895 f_tc_si2quater_n_earfcns(33);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002896 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002897}
2898
2899testcase TC_si2quater_42_earfcns() runs on test_CT {
2900 f_tc_si2quater_n_earfcns(42);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002901 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002902}
2903
2904testcase TC_si2quater_48_earfcns() runs on test_CT {
2905 f_tc_si2quater_n_earfcns(48);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002906 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002907}
2908
2909/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
2910 * 48 EARFCNs. */
2911testcase TC_si2quater_49_earfcns() runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002912 var template SystemInformationConfig sic := SystemInformationConfig_default;
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002913 sic.si2quater := f_tr_si2quater_earfcns(48); /* 48, not 49! */
2914 f_init(0);
2915
2916 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002917 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2918 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002919 }
2920
2921 /* The 49th EARFCN no longer fits, expect VTY error */
2922 f_vty_enter_cfg_bts(BSCVTY, 0);
2923 var charstring vty_error;
2924 vty_error := f_vty_transceive_ret(BSCVTY,
2925 "si2quater neighbor-list add earfcn 70 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3")
2926 f_vty_transceive(BSCVTY, "end");
2927
2928 if (f_strstr(vty_error, "Unable to add ARFCN 70") >= 0) {
2929 log("Got expected VTY error: ", vty_error);
2930 setverdict(pass);
2931 } else {
2932 setverdict(fail, "Expected the 49th EUTRAN ARFCN to be rejected by vty config, got: ", vty_error);
2933 }
2934
2935 f_init_bts_and_check_sysinfo(0, expect_si := sic);
2936
2937 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002938 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 +02002939 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002940 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002941}
2942
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002943private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
2944{
2945 var uint8_t count := 0;
2946 for (var integer i := 5; i < 16; i := i + 1) {
2947 if (acc[i] == '0'B) { /* the list marks barred, we count allowed */
2948 count := count + 1;
2949 }
2950 }
2951 return count;
2952}
2953
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002954private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return SystemInformationType1
2955{
2956 var ASP_RSL_Unitdata rx_rsl_ud;
2957 var SystemInformationType1 last_si1;
2958
2959 timer T := 30.0;
2960 T.start;
2961 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002962 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
2963 tr_RSL_BCCH_INFO,
2964 tr_RSL_NO_SACCH_FILL,
2965 tr_RSL_SACCH_FILL))) -> value rx_rsl_ud {
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002966 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
2967 if (g_system_information[rsl_idx].si1 == omit) {
2968 repeat;
2969 }
2970 last_si1 := g_system_information[rsl_idx].si1;
2971 g_system_information[rsl_idx].si1 := omit;
2972 T.stop;
2973 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002974 [] IPA_RSL[rsl_idx][0].receive { repeat; }
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002975 [] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
2976 }
2977 return last_si1;
2978}
2979
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002980/* verify ACC rotate feature */
2981testcase TC_si_acc_rotate() runs on test_CT {
2982 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002983 var SystemInformationType1 last_si1;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002984 var AccessControlClass acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002985 var uint8_t count;
2986 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2987
2988 f_init(0, guard_timeout := 60.0);
2989
2990 f_bts_0_cfg(BSCVTY, {"rach access-control-class 5 barred",
2991 "access-control-class-rotate 3",
2992 "access-control-class-rotate-quantum 1"});
2993
2994 /* Init and get first sysinfo */
2995 f_init_bts_and_check_sysinfo(0, expect_si := ?);
2996
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002997 for (var integer i:= 0; i < 20; i := i + 1) {
2998 last_si1 := f_recv_next_si1(0);
2999 acc := last_si1.rach_control.acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003000 count := f_acc09_count_allowed(acc);
3001 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3002
3003 if (count != 3) {
3004 log("RSL: EXPECTED SI ACC len=3");
3005 setverdict(fail, "received SI does not match expectations");
3006 break;
3007 }
3008
3009 for (var integer j := 0; j < 10; j := j + 1) {
3010 if (acc[16 - 1 - j] == '0'B) { /* the list marks barred, we count allowed */
3011 times_allowed[j] := times_allowed[j] + 1;
3012 }
3013 }
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003014 }
3015
3016 for (var integer j := 0; j < 10; j := j + 1) {
3017 log("ACC", j, " allowed ", times_allowed[j], " times" );
3018 if (j != 5 and times_allowed[j] < 3) {
3019 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " < 1 times");
3020 } else if (j == 5 and times_allowed[j] > 0) {
3021 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " > 0 times");
3022 }
3023 }
3024
3025 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3026 "rach access-control-class 5 allowed"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003027 f_shutdown_helper();
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003028}
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02003029
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003030/* verify ACC startup ramp+rotate feature */
3031testcase TC_si_acc_ramp_rotate() runs on test_CT {
3032 var template SystemInformationConfig sic := SystemInformationConfig_default;
3033 var SystemInformationType1 last_si1;
3034 var AccessControlClass acc;
3035 var ASP_RSL_Unitdata rx_rsl_ud;
3036 var uint8_t count;
3037 var uint8_t prev_count;
3038 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3039
3040 f_init(0, guard_timeout := 80.0);
3041
3042 f_bts_0_cfg(BSCVTY, {"rach access-control-class 4 barred",
3043 "access-control-class-rotate 0",
3044 "access-control-class-rotate-quantum 1",
3045 "access-control-class-ramping",
3046 "access-control-class-ramping-step-interval 5",
3047 "access-control-class-ramping-step-size 5"});
3048
3049 /* Init and get first sysinfo */
3050 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3051 last_si1 := g_system_information[0].si1;
3052 acc := last_si1.rach_control.acc;
3053 count := f_acc09_count_allowed(acc);
3054 /* Adm subset size was set to 0 above, so wait until all ACC are barred */
3055 while (count > 0) {
3056 last_si1 := f_recv_next_si1(0);
3057 acc := last_si1.rach_control.acc;
3058 count := f_acc09_count_allowed(acc);
3059 log("RSL: wait len()=0: GOT SI1 ACC len=", count, ": ", acc);
3060 }
3061
3062 /* Increase adm subset size, we should see ramping start up */
3063 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10"});
3064 prev_count := 0;
3065 while (true) {
3066 last_si1 := f_recv_next_si1(0);
3067 acc := last_si1.rach_control.acc;
3068 count := f_acc09_count_allowed(acc);
3069 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3070
3071 if (prev_count > count) {
3072 setverdict(fail, "ACC allowed count dropped while expecting grow: ", prev_count, " -> ", count);
3073 break;
3074 }
3075
3076 if (count == 9) {
3077 break; /* Maximum reached (10 - 1 perm barred), done here */
3078 }
3079
3080 prev_count := count;
3081 }
3082
3083 setverdict(pass);
3084
3085 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3086 "rach access-control-class 4 allowed",
3087 "no access-control-class-ramping"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003088 f_shutdown_helper();
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003089}
3090
Harald Welte4003d112017-12-09 22:35:39 +01003091testcase TC_ctrl_msc_connection_status() runs on test_CT {
3092 var charstring ctrl_resp;
3093
Harald Welte89d42e82017-12-17 16:42:41 +01003094 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003095
3096 /* See https://osmocom.org/issues/2729 */
3097 f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003098 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01003099}
3100
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003101testcase TC_ctrl_msc0_connection_status() runs on test_CT {
3102 var charstring ctrl_resp;
3103
3104 f_init(1);
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003105
3106 f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003107 f_shutdown_helper();
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003108}
3109
Neels Hofmeyr0bc470d2021-08-21 13:37:13 +02003110/* Verify correct stats on the number of configured and connected MSCs */
3111private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
3112 g_pars := f_gen_test_hdlr_pars();
3113 var StatsDExpects expect := {
3114 { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
3115 { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
3116 };
3117 f_statsd_expect(expect);
3118}
3119
3120private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
3121{
3122 var MSC_ConnHdlr vc_conn;
3123
3124 f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
3125 f_sleep(1.0);
3126 vc_conn := f_start_handler(tc_fn);
3127 vc_conn.done;
3128
3129 /* Also verify stat exposed on CTRL interface */
3130 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
3131 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
3132
3133 f_shutdown_helper();
3134}
3135
3136/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
3137private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
3138 f_tc_stat_num_msc_connected_msc_connhdlr(1);
3139}
3140testcase TC_stat_num_msc_connected_1() runs on test_CT {
3141 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
3142}
3143
3144/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
3145private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
3146 f_tc_stat_num_msc_connected_msc_connhdlr(2);
3147}
3148testcase TC_stat_num_msc_connected_2() runs on test_CT {
3149 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
3150}
3151
3152/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
3153private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
3154 f_tc_stat_num_msc_connected_msc_connhdlr(3);
3155}
3156testcase TC_stat_num_msc_connected_3() runs on test_CT {
3157 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
3158}
3159
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003160/* Verify correct stats on the number of configured and connected MSCs */
3161private 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 +06003162 var integer num_trx_connected := 0;
3163 var integer num_trx_total := 0;
3164
3165 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3166 var integer trx_num := c_BtsParams[i].trx_num;
3167 num_trx_total := num_trx_total + trx_num;
3168 if (i < expect_num_bts_connected) {
3169 num_trx_connected := num_trx_connected + trx_num;
3170 }
3171 }
3172
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003173 var StatsDExpects expect := {
3174 { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
3175 { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3176 { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003177 { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := num_trx_connected, max := num_trx_connected },
3178 { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := num_trx_total, max := num_trx_total }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003179 };
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003180
3181 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003182 f_statsd_expect(expect);
3183}
3184
3185private 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 +06003186 var integer num_trx_connected := 0;
3187 var integer num_trx_total := 0;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003188 var MSC_ConnHdlr vc_conn;
3189
3190 f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
3191 f_sleep(1.0);
3192 vc_conn := f_start_handler(tc_fn);
3193 vc_conn.done;
3194
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003195 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3196 var integer trx_num := c_BtsParams[i].trx_num;
3197 num_trx_total := num_trx_total + trx_num;
3198 if (i < nr_bts) {
3199 num_trx_connected := num_trx_connected + trx_num;
3200 }
3201 }
3202
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003203 /* Also verify stat exposed on CTRL interface */
3204 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
3205 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 +06003206 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(num_trx_connected));
3207 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 +02003208
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003209 /* Verify rf_states exposed on CTRL interface */
3210 var charstring expect_net_rf_states := "";
3211 for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003212 var charstring expect_bts_rf_states := "";
3213
3214 for (var integer j := 0; j < c_BtsParams[i].trx_num; j := j + 1) {
3215 expect_bts_rf_states := expect_bts_rf_states &
3216 int2str(i) & "," & int2str(j) & ",";
3217 if (i < NUM_BTS) {
3218 /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
3219 expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
3220 } else {
3221 /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
3222 expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
3223 }
3224 /* The RF policy is still global in osmo-bsc, i.e. always "on" */
3225 expect_bts_rf_states := expect_bts_rf_states & "on,";
3226 if (i < nr_bts) {
3227 /* For BTS where RSL is connected, the RSL state will be "up" */
3228 expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
3229 } else {
3230 expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
3231 }
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003232 }
3233
3234 f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
3235 expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
3236 }
3237 f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
3238
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003239 f_shutdown_helper();
3240}
3241
3242/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
3243private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
3244 f_tc_stat_num_bts_connected_msc_connhdlr(1);
3245}
3246testcase TC_stat_num_bts_connected_1() runs on test_CT {
3247 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
3248}
3249
3250/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
3251private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
3252 f_tc_stat_num_bts_connected_msc_connhdlr(2);
3253}
3254testcase TC_stat_num_bts_connected_2() runs on test_CT {
3255 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
3256}
3257
3258/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
3259private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
3260 f_tc_stat_num_bts_connected_msc_connhdlr(3);
3261}
3262testcase TC_stat_num_bts_connected_3() runs on test_CT {
3263 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
3264}
3265
Harald Welte4003d112017-12-09 22:35:39 +01003266testcase TC_ctrl() runs on test_CT {
3267 var charstring ctrl_resp;
3268
Harald Welte89d42e82017-12-17 16:42:41 +01003269 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003270
3271 /* all below values must match the osmo-bsc.cfg config file used */
3272
Harald Welte6a129692018-03-17 17:30:14 +01003273 f_ctrl_get_exp(IPA_CTRL, "mcc", "001");
3274 f_ctrl_get_exp(IPA_CTRL, "mnc", "01");
Oliver Smith75aa0202019-08-19 14:17:50 +02003275 f_ctrl_get_exp(IPA_CTRL, "number-of-bts", "4");
Harald Welte4003d112017-12-09 22:35:39 +01003276
3277 var integer bts_nr := 0;
3278 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "location-area-code", "1");
3279 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "cell-identity", "0");
3280 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "oml-connection-state", "connected");
3281 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "gprs-mode", "gprs");
3282 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "rf_state", "operational,unlocked,on");
3283 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "arfcn", "871");
3284 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "max-power-reduction", "20");
3285
3286 var integer uptime := str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime"));
3287 f_sleep(2.0);
3288 if (str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime")) < uptime+1) {
3289 setverdict(fail, "oml-uptime not incrementing as expected");
3290 }
3291 /* TODO: Disconnect RSL, imply that OML is disconnected and check for uptime zero? */
3292
3293 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
3294
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003295 f_shutdown_helper();
Harald Welte96c94412017-12-09 03:12:45 +01003296}
3297
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003298/* Verify that Upon receival of SET "location", BSC forwards a TRAP
3299 "location-state" over the SCCPlite IPA conn */
3300testcase TC_ctrl_location() runs on test_CT {
3301 var MSC_ConnHdlr vc_conn;
3302 var integer bts_nr := 0;
3303
3304 f_init(1, true);
3305 f_sleep(1.0);
3306
3307 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234567,fix3d,0.340000,0.560000,0.780000");
3308 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3309 "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
3310
3311 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "1");
3312 f_sleep(2.0);
3313
3314 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234888,fix3d,0.350000,0.570000,0.790000");
3315 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3316 "1234888,fix3d,0.350000,0.570000,0.790000,operational,locked,off,001,01");
3317
3318 /* should match the one from config */
3319 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
3320
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003321 f_shutdown_helper();
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003322}
3323
Harald Welte6f521d82017-12-11 19:52:02 +01003324
3325/***********************************************************************
3326 * Paging Testing
3327 ***********************************************************************/
3328
3329type record Cell_Identity {
3330 GsmMcc mcc,
3331 GsmMnc mnc,
3332 GsmLac lac,
3333 GsmCellId ci
3334};
Harald Welte24135bd2018-03-17 19:27:53 +01003335private const Cell_Identity cid := { '001'H, '01'H, 1, 0 };
Stefan Sperling049a86e2018-03-20 15:51:00 +01003336private const Cell_Identity unknown_cid := { '678'H, 'f90'H, 1, 0 };
Harald Welte6f521d82017-12-11 19:52:02 +01003337
Harald Welte5d1a2202017-12-13 19:51:29 +01003338type set of integer BtsIdList;
3339
3340private function f_bts_in_list(integer bts_id, BtsIdList bts_ids) return boolean {
3341 for (var integer j := 0; j < sizeof(bts_ids); j := j + 1) {
3342 if (bts_id == bts_ids[j]) {
3343 return true;
3344 }
3345 }
3346 return false;
3347}
Harald Welte6f521d82017-12-11 19:52:02 +01003348
3349/* core paging test helper function; used by most paging test cases */
3350private function f_pageing_helper(hexstring imsi,
3351 template BSSMAP_FIELD_CellIdentificationList cid_list,
Harald Welte5d1a2202017-12-13 19:51:29 +01003352 BtsIdList bts_ids := { 0 },
Harald Welte6f521d82017-12-11 19:52:02 +01003353 template RSL_ChanNeeded rsl_chneed := omit,
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003354 template (omit) OCT4 tmsi := omit) runs on test_CT
Harald Welte6f521d82017-12-11 19:52:02 +01003355{
3356 var template BSSMAP_IE_ChannelNeeded bssmap_chneed;
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003357 var template MobileIdentityV mi;
Harald Welte6f521d82017-12-11 19:52:02 +01003358 var RSL_Message rx_rsl;
3359 var integer paging_group := hex2int(imsi[lengthof(imsi)-1]);
Harald Welte5d1a2202017-12-13 19:51:29 +01003360 var integer i;
Harald Welte6f521d82017-12-11 19:52:02 +01003361
3362 f_init();
Harald Welte6f521d82017-12-11 19:52:02 +01003363
3364 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Harald Weltec3068592018-03-17 19:55:31 +01003365 for (i := 0; i < NUM_BTS; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003366 IPA_RSL[i][0].clear;
Harald Welte5d1a2202017-12-13 19:51:29 +01003367 }
Harald Welte6f521d82017-12-11 19:52:02 +01003368
3369 if (isvalue(rsl_chneed)) {
3370 /* The values of 08.08 3.2.2.36 and 08.58 9.3.40 are luckily identical */
3371 bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
3372 } else {
3373 bssmap_chneed := omit;
3374 }
3375
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003376 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
3377 ts_BSSMAP_Paging(imsi, cid_list, tmsi, bssmap_chneed)));
Harald Welte6f521d82017-12-11 19:52:02 +01003378
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003379 if (not istemplatekind(tmsi, "omit")) {
3380 mi := t_MI_TMSI(tmsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003381 } else {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003382 mi := tr_MI_IMSI(imsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003383 }
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003384
Harald Welte5d1a2202017-12-13 19:51:29 +01003385 for (i := 0; i < sizeof(bts_ids); i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003386 rx_rsl := f_exp_ipa_rx(tr_RSL_PAGING_CMD(mi), idx := {bts_ids[i], 0});
Harald Welte5d1a2202017-12-13 19:51:29 +01003387 /* check channel type, paging group */
3388 if (rx_rsl.ies[1].body.paging_group != paging_group) {
3389 setverdict(fail, "Paging for wrong paging group");
3390 }
3391 if (ispresent(rsl_chneed) and
3392 rx_rsl.ies[3].body.chan_needed.chan_needed != valueof(rsl_chneed)) {
3393 setverdict(fail, "RSL Channel Needed != BSSMAP Channel Needed");
3394 }
Harald Welte6f521d82017-12-11 19:52:02 +01003395 }
Harald Welte2fccd982018-01-31 15:48:19 +01003396 f_sleep(2.0);
Harald Welte5d1a2202017-12-13 19:51:29 +01003397 /* do a quick check on all not-included BTSs if they received paging */
3398 for (i := 0; i < NUM_BTS; i := i + 1) {
3399 timer T := 0.1;
3400 if (f_bts_in_list(i, bts_ids)) {
3401 continue;
3402 }
3403 T.start;
3404 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003405 [] IPA_RSL[i][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003406 setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
3407 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003408 [] IPA_RSL[i][0].receive { repeat; }
Harald Welte5d1a2202017-12-13 19:51:29 +01003409 [] T.timeout { }
3410 }
Harald Welte6f521d82017-12-11 19:52:02 +01003411 }
3412
3413 setverdict(pass);
3414}
3415
Harald Welte5d1a2202017-12-13 19:51:29 +01003416const BtsIdList c_BtsId_all := { 0, 1, 2 };
Harald Welte751d3eb2018-01-31 15:51:06 +01003417const BtsIdList c_BtsId_none := { };
Harald Welte5d1a2202017-12-13 19:51:29 +01003418const BtsIdList c_BtsId_LAC1 := { 0, 1 };
3419const BtsIdList c_BtsId_LAC2 := { 2 };
3420
Harald Welte6f521d82017-12-11 19:52:02 +01003421/* PAGING by IMSI + TMSI */
3422testcase TC_paging_imsi_nochan() runs on test_CT {
3423 var BSSMAP_FIELD_CellIdentificationList cid_list;
3424 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Philipp Maier8c04b0a2018-02-23 13:48:48 +01003425 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, omit);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003426 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003427}
3428
3429/* PAGING by IMSI + TMSI */
3430testcase TC_paging_tmsi_nochan() runs on test_CT {
3431 var BSSMAP_FIELD_CellIdentificationList cid_list;
3432 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003433 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, 'A1B2C301'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003434 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003435}
3436
3437/* Paging with different "channel needed' values */
3438testcase TC_paging_tmsi_any() 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('001010100000002'H, cid_list, c_BtsId_all, RSL_CHANNEED_ANY, 'A1B2C302'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003442 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003443}
3444testcase TC_paging_tmsi_sdcch() runs on test_CT {
3445 var BSSMAP_FIELD_CellIdentificationList cid_list;
3446 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003447 f_pageing_helper('001010100000003'H, cid_list, c_BtsId_all, RSL_CHANNEED_SDCCH, 'A1B2C303'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003448 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003449}
3450testcase TC_paging_tmsi_tch_f() runs on test_CT {
3451 var BSSMAP_FIELD_CellIdentificationList cid_list;
3452 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003453 f_pageing_helper('001010000000004'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_F, 'A1B2C304'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003454 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003455}
3456testcase TC_paging_tmsi_tch_hf() runs on test_CT {
3457 var BSSMAP_FIELD_CellIdentificationList cid_list;
3458 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003459 f_pageing_helper('001010000000005'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_ForH, 'A1B2C305'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003460 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003461}
3462
3463/* Paging by CGI */
3464testcase TC_paging_imsi_nochan_cgi() runs on test_CT {
3465 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3466 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(cid.mcc, cid.mnc, cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003467 f_pageing_helper('001010000000006'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003468 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003469}
3470
3471/* Paging by LAC+CI */
3472testcase TC_paging_imsi_nochan_lac_ci() runs on test_CT {
3473 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3474 cid_list := { cIl_LAC_CI := { ts_BSSMAP_CI_LAC_CI(cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003475 f_pageing_helper('001010000000007'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003476 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003477}
3478
3479/* Paging by CI */
3480testcase TC_paging_imsi_nochan_ci() runs on test_CT {
3481 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3482 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003483 f_pageing_helper('001010000000008'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003484 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003485}
3486
3487/* Paging by LAI */
3488testcase TC_paging_imsi_nochan_lai() runs on test_CT {
3489 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3490 cid_list := { cIl_LAI := { ts_BSSMAP_CI_LAI(cid.mcc, cid.mnc, cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003491 f_pageing_helper('001010000000009'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003492 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003493}
3494
3495/* Paging by LAC */
3496testcase TC_paging_imsi_nochan_lac() runs on test_CT {
3497 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3498 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003499 f_pageing_helper('001010000000010'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003500 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003501}
3502
3503/* Paging by "all in BSS" */
3504testcase TC_paging_imsi_nochan_all() runs on test_CT {
3505 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3506 cid_list := { cIl_allInBSS := ''O };
Harald Welte5d1a2202017-12-13 19:51:29 +01003507 f_pageing_helper('001010000000011'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003508 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003509}
3510
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003511/* Paging by PLMN+LAC+RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003512testcase TC_paging_imsi_nochan_plmn_lac_rnc() runs on test_CT {
3513 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3514 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 +01003515 f_pageing_helper('001010000000012'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003516 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003517}
Harald Welte6f521d82017-12-11 19:52:02 +01003518
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003519/* Paging by RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003520testcase TC_paging_imsi_nochan_rnc() runs on test_CT {
3521 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3522 cid_list := { cIl_RNC := { int2oct(13, 2) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003523 f_pageing_helper('001010000000013'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003524 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003525}
3526
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003527/* Paging by LAC+RNC; We do not implement; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003528testcase TC_paging_imsi_nochan_lac_rnc() runs on test_CT {
3529 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3530 cid_list := { cIl_LAC_RNC := { ts_BSSMAP_CI_LAC_RNC(cid.lac, 14) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003531 f_pageing_helper('001010000000014'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003532 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003533}
3534
Harald Welte6f521d82017-12-11 19:52:02 +01003535/* Paging on multiple cells (multiple entries in list): Verify all of them page */
Harald Welte751d3eb2018-01-31 15:51:06 +01003536testcase TC_paging_imsi_nochan_lacs() runs on test_CT {
3537 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3538 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(1), ts_BSSMAP_CI_LAC(2) } };
3539 f_pageing_helper('001010000000015'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003540 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003541}
3542
3543/* Paging on empty list: Verify none of them page */
3544testcase TC_paging_imsi_nochan_lacs_empty() runs on test_CT {
3545 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3546 cid_list := { cIl_LAC := { } };
3547 f_pageing_helper('001010000000016'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003548 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003549}
3550
Stefan Sperling049a86e2018-03-20 15:51:00 +01003551/* Paging by CGI with unknown MCC/MNC: Verify nothing is paged. */
3552testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
3553 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3554 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(unknown_cid.mcc, unknown_cid.mnc, unknown_cid.lac, unknown_cid.ci) } };
3555 f_pageing_helper('001010000000006'H, cid_list, c_BtsId_none);
3556 f_shutdown_helper();
3557}
3558
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +01003559/* Send paging response containing invalid (wrongly formatted) MobileIdentity IE. */
3560testcase TC_paging_imsi_nochan_ci_resp_invalid_mi() runs on test_CT {
3561 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3562 var BSSAP_N_CONNECT_ind rx_c_ind;
3563 var DchanTuple dt;
3564 var octetstring rr_pag_resp := '06270003535992617965720000'O;
3565 /* { 06 27 } is { GSM48_PDISC_RR, GSM48_MT_RR_PAG_RESP }
3566 * see 3GPP TS 44.018, table 9.1.25.1
3567 * { 00 } or { 01 } is CKSN + Spare Half Octet, not important
3568 * { 03 53 59 92 } is Mobile Station Classmark
3569 * { 61 79 65 72 00 00 } is the invalid Mobile Identity IE (3GPP TS 24.008, 10.5.1.4),
3570 * Length is 0x61 (97 in decimal).
3571 */
3572
3573 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
3574 f_pageing_helper('001010000000008'H, cid_list, { 0 });
3575
3576 /* Send CHAN RQD and wait for allocation; acknowledge it */
3577 dt.rsl_chan_nr := f_chreq_act_ack();
3578 dt.idx := {0, 0};
3579
3580 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
3581 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), rr_pag_resp));
3582
3583 /* Expevct a CR with a matching Paging response on the A-Interface */
3584 timer T := 5.0;
3585 T.start;
3586 alt {
3587 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
3588 setverdict(pass);
3589 dt.sccp_conn_id := rx_c_ind.connectionId;
3590 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
3591 }
3592 [] BSSAP.receive {
3593 setverdict(fail, "Received unexpected message on A-Interface!");
3594 }
3595 [] T.timeout {
3596 setverdict(fail, "Received nothing on A-Interface!");
3597 }
3598 }
3599
3600 f_perform_clear_test_ct(dt);
3601 f_shutdown_helper();
3602}
3603
Harald Welte6f521d82017-12-11 19:52:02 +01003604/* Verify paging retransmission interval + count */
3605/* Verify paging stops after channel establishment */
Harald Welte6f521d82017-12-11 19:52:02 +01003606/* Test behavior under paging overload */
Harald Welteae026692017-12-09 01:03:01 +01003607
Harald Weltee65d40e2017-12-13 00:09:06 +01003608/* Verify PCH load */
3609testcase TC_paging_imsi_load() runs on test_CT {
3610 var BSSMAP_FIELD_CellIdentificationList cid_list;
3611 timer T := 4.0;
Harald Welte2caa1062018-03-17 18:19:05 +01003612 timer T_retrans := 1.0;
Harald Weltee65d40e2017-12-13 00:09:06 +01003613 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003614 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Weltee65d40e2017-12-13 00:09:06 +01003615
3616 /* tell BSC there is no paging space anymore */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003617 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte3b57ab52018-03-17 18:01:10 +01003618 f_sleep(0.2);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003619 IPA_RSL[0][0].clear;
Harald Weltee65d40e2017-12-13 00:09:06 +01003620
3621 /* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
3622 * there would be 8 retransmissions during 4 seconds */
3623 T.start;
Harald Welte2caa1062018-03-17 18:19:05 +01003624 T_retrans.start;
Harald Weltee65d40e2017-12-13 00:09:06 +01003625 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003626 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Weltee65d40e2017-12-13 00:09:06 +01003627 setverdict(fail, "Received PAGING after LOAD_IND(0)");
Daniel Willmannafce8662018-07-06 23:11:32 +02003628 mtc.stop;
Harald Weltee65d40e2017-12-13 00:09:06 +01003629 }
Harald Welte2caa1062018-03-17 18:19:05 +01003630 [] T_retrans.timeout {
3631 /* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003632 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte2caa1062018-03-17 18:19:05 +01003633 T_retrans.start;
3634 repeat;
3635 }
Harald Weltee65d40e2017-12-13 00:09:06 +01003636 [] T.timeout {
3637 setverdict(pass);
3638 }
3639 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003640
3641 f_shutdown_helper();
Harald Weltee65d40e2017-12-13 00:09:06 +01003642}
3643
Harald Welte235ebf12017-12-15 14:18:16 +01003644/* Verify Paging Counter */
Harald Welte1ff69992017-12-14 12:31:17 +01003645testcase TC_paging_counter() runs on test_CT {
3646 var BSSMAP_FIELD_CellIdentificationList cid_list;
3647 timer T := 4.0;
3648 var integer i;
3649 var integer paging_attempted_bsc;
3650 var integer paging_attempted_bts[NUM_BTS];
Oliver Smith8b343d32021-11-26 13:01:42 +01003651 var integer paging_expired_bsc;
Harald Welte1ff69992017-12-14 12:31:17 +01003652 var integer paging_expired_bts[NUM_BTS];
3653 cid_list := valueof(ts_BSSMAP_CIL_noCell);
3654
3655 f_init();
3656
3657 /* read counters before paging */
3658 paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003659 paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
Harald Welte1ff69992017-12-14 12:31:17 +01003660 for (i := 0; i < NUM_BTS; i := i+1) {
3661 paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
3662 paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
3663 }
3664
3665 f_pageing_helper('001230000000001'H, cid_list, c_BtsId_all);
3666
3667 /* expect the attempted pages on BSC and each BTSs to have incremented by one */
3668 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", paging_attempted_bsc+1);
3669 for (i := 0; i < NUM_BTS; i := i+1) {
3670 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted",
3671 paging_attempted_bts[i]+1);
3672 }
3673
3674 /* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
3675 f_sleep(12.0);
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003676 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
Harald Welte1ff69992017-12-14 12:31:17 +01003677 for (i := 0; i < NUM_BTS; i := i+1) {
3678 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
3679 paging_expired_bts[i]+1);
3680 }
Harald Welte1ff69992017-12-14 12:31:17 +01003681
Philipp Maier282ca4b2018-02-27 17:17:00 +01003682 f_shutdown_helper();
Harald Welte1ff69992017-12-14 12:31:17 +01003683}
3684
3685
Harald Welte10985002017-12-12 09:29:15 +01003686/* Verify paging stops after A-RESET */
3687testcase TC_paging_imsi_a_reset() runs on test_CT {
3688 var BSSMAP_FIELD_CellIdentificationList cid_list;
3689 timer T := 3.0;
3690 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003691 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Welte10985002017-12-12 09:29:15 +01003692
3693 /* Perform a BSSMAP Reset and wait for ACK */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003694 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 +01003695 alt {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003696 [] 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 +01003697 [] BSSAP.receive { repeat; }
3698 }
3699
Daniel Willmanncbef3982018-07-30 09:22:40 +02003700 /* Wait to avoid a possible race condition if a paging message is
3701 * received right before the reset ACK. */
3702 f_sleep(0.2);
3703
Harald Welte10985002017-12-12 09:29:15 +01003704 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Philipp Maier1e6b4422018-02-23 14:02:13 +01003705 for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003706 IPA_RSL[i][0].clear;
Philipp Maier1e6b4422018-02-23 14:02:13 +01003707 }
Harald Welte10985002017-12-12 09:29:15 +01003708
3709 /* Wait for 3 seconds if any more PAGING CMD are received on RSL */
3710 T.start;
3711 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003712 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte10985002017-12-12 09:29:15 +01003713 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003714 mtc.stop;
Harald Welte10985002017-12-12 09:29:15 +01003715 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003716 [] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003717 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003718 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003719 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003720 [] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003721 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003722 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003723 }
Harald Welte10985002017-12-12 09:29:15 +01003724 [] T.timeout {
3725 setverdict(pass);
3726 }
3727 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003728
3729 f_shutdown_helper();
Harald Welte10985002017-12-12 09:29:15 +01003730}
Harald Welteae026692017-12-09 01:03:01 +01003731
Philipp Maierf45824a2019-08-14 14:44:10 +02003732/* Verify how we handle unsolicited Paging Response. In case of an unsolicit
3733 * paging response we can not know which MSC is in charge, so we will blindly
3734 * pick the first configured MSC. This behavior is required in order to make
3735 * MT-CSFB calls working because in those cases the BSC can not know that the
3736 * MSC has already paged the subscriver via SGs. So any MT-CSFB call will look
3737 * like an unsolicited Paging Response to the MSC.
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003738 */
3739testcase TC_paging_resp_unsol() runs on test_CT {
3740
3741 f_init(1);
Philipp Maierf45824a2019-08-14 14:44:10 +02003742 timer T := 5.0;
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003743
3744 var BSSAP_N_CONNECT_ind rx_c_ind;
3745 var DchanTuple dt;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02003746 var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010008880018'H)));
Philipp Maierf45824a2019-08-14 14:44:10 +02003747 var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003748
3749 /* Send CHAN RQD and wait for allocation; acknowledge it */
3750 dt.rsl_chan_nr := f_chreq_act_ack();
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003751 dt.idx := {0, 0};
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003752
3753 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
Pau Espin Pedrole8a51012023-01-03 11:59:59 +01003754 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 +01003755
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003756
Philipp Maierf45824a2019-08-14 14:44:10 +02003757 /* Expevct a CR with a matching Paging response on the A-Interface */
3758 T.start;
3759 alt {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003760 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
Philipp Maierf45824a2019-08-14 14:44:10 +02003761 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003762 dt.sccp_conn_id := rx_c_ind.connectionId;
3763 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
Philipp Maierf45824a2019-08-14 14:44:10 +02003764 }
3765 [] BSSAP.receive {
3766 setverdict(fail, "Received unexpected message on A-Interface!");
3767 }
3768 [] T.timeout {
3769 setverdict(fail, "Received nothing on A-Interface!");
3770 }
3771 }
3772
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003773 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003774 f_shutdown_helper();
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003775}
3776
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003777/* Verify BSC can schedule N paging requests under one minute if BTS buffer is good enough */
3778function f_TC_paging_Nreq(integer num_subscribers, boolean send_pag_load_ind) runs on test_CT {
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003779 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003780 var Hexstrings imsis := {};
3781 var Booleans rx_paging_done := {};
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003782 var integer rx_paging_num := 0;
3783 var integer i;
3784 timer T_rx := 60.0;
3785 timer T_load_ind := 1.0;
3786
3787 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003788 imsis := imsis & {f_gen_imsi(i)};
3789 rx_paging_done := rx_paging_done & { false };
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003790 }
3791
3792 f_init(1, guard_timeout := 100.0);
3793
3794 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003795 IPA_RSL[0][0].clear;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003796 if (send_pag_load_ind) {
3797 /* Tell there's plenty of space at the BTS (UINT16_MAX): */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003798 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(65535));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003799 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003800
3801 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003802 /* Page on LAC-CI of BTS0: */
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003803 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 +02003804 ts_BSSMAP_Paging(imsis[i], valueof(ts_BSSMAP_CIL_LAC_CI({ts_BSSMAP_CI_LAC_CI(1, 0)})),
3805 omit, omit)));
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003806 }
3807
3808 T_rx.start;
3809 T_load_ind.start;
3810 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003811 [] 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 +02003812 var hexstring imsi := rx_rsl_ud.rsl.ies[2].body.ms_identity.mobileIdentityV.oddEvenInd_identity.imsi.digits;
3813 var hexstring imsi_suffix := substr(imsi, lengthof(imsi)-6, 6);
3814 var charstring imsi_str := hex2str(imsi_suffix);
3815 var integer imsi_idx := str2int(imsi_str);
3816 if (rx_paging_done[imsi_idx] == false) {
3817 rx_paging_done[imsi_idx] := true;
3818 rx_paging_num := rx_paging_num + 1;
Pau Espin Pedrolef7ef632022-04-25 13:34:57 +02003819 } else {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003820 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 +02003821 mtc.stop;
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003822 }
3823 if (rx_paging_num < num_subscribers) {
3824 repeat;
3825 }
3826 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003827 [] IPA_RSL[0][0].receive { repeat; }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003828 [] T_load_ind.timeout {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003829 log("[CCH Load Ind timer] received paging requests so far: ", rx_paging_num);
3830 if (send_pag_load_ind) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003831 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(40));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003832 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003833 T_load_ind.start;
3834 repeat;
3835 }
3836 [] T_rx.timeout {
3837 setverdict(fail, "Timeout expecting paging requests, so far ", rx_paging_num);
3838 mtc.stop;
3839 }
3840 }
3841
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003842 /* Drop OML connection to have all paging requests flushed: */
3843 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
3844
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003845 f_shutdown_helper();
3846}
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003847/* Verify BSC can schedule 500 paging requests under one minute if BTS buffer is good enough */
3848testcase TC_paging_500req() runs on test_CT {
3849 f_TC_paging_Nreq(500, true);
3850}
3851/* Same as TC_paging_500req, but without sending CCCH Load Indication, which
3852 * means BTS is always under CCH Load Threshold, aka capable of sending tons of requests.
3853 * Since No CCCH Load Ind, BSC uses a conservative estimation of BTS load, which
3854 * for current config yields ~8req/sec, so 480req/min maximum. */
3855testcase TC_paging_450req_no_paging_load_ind() runs on test_CT {
3856 f_TC_paging_Nreq(450, false);
3857}
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003858
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003859/* Test RSL link drop causes counter increment */
3860testcase TC_rsl_drop_counter() runs on test_CT {
3861 var integer rsl_fail;
3862
Harald Welte89d42e82017-12-17 16:42:41 +01003863 f_init(1);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003864
3865 rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
3866
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003867 f_ipa_rsl_stop(bts[0][0].rsl);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003868
3869 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
3870
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003871 f_shutdown_helper();
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003872}
3873
3874/* TODO: Test OML link drop causes counter increment */
3875
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003876/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
3877function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003878 var IPA_Client client;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003879 timer T := 10.0;
3880
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003881 client.id := "IPA-BTS0-TRX0-RSL";
3882 client.vc_IPA := IPA_Emulation_CT.create(client.id & "-IPA") alive;
3883 client.ccm_pars := c_IPA_default_ccm_pars;
3884 client.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
3885 client.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003886
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01003887 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003888
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003889 f_init_mgcp(0, "VirtMGW");
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003890
3891 /* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003892 map(client.vc_IPA:IPA_PORT, system:IPA);
3893 connect(client.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0][0]);
3894 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 +01003895
3896 /* wait for IPA OML link to connect and then disconnect */
3897 T.start;
3898 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003899 [] IPA_RSL[0][0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003900 T.stop;
3901 return true;
3902 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003903 [] IPA_RSL[0][0].receive { repeat }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003904 [] T.timeout {
Daniel Willmannafce8662018-07-06 23:11:32 +02003905 return false;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003906 }
3907 }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003908 return false;
3909}
3910
3911/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3912testcase TC_rsl_unknown_unit_id() runs on test_CT {
3913 if (f_ipa_unknown_unit_id(mp_bsc_rsl_port)) {
3914 setverdict(pass);
3915 } else {
3916 setverdict(fail, "Timeout RSL waiting for connection to close");
3917 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003918 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003919}
3920
3921
3922/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3923testcase TC_oml_unknown_unit_id() runs on test_CT {
3924 if (f_ipa_unknown_unit_id(mp_bsc_oml_port)) {
3925 setverdict(pass);
3926 } else {
3927 setverdict(fail, "Timeout OML waiting for connection to close");
3928 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003929 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003930}
3931
3932
Harald Weltec1a2fff2017-12-17 11:06:19 +01003933/***********************************************************************
Harald Welte6811d102019-04-14 22:23:14 +02003934 * "New world" test cases using RSL_Emulation + RAN_Emulation
Harald Weltec1a2fff2017-12-17 11:06:19 +01003935 ***********************************************************************/
3936
Harald Welte6811d102019-04-14 22:23:14 +02003937import from RAN_Emulation all;
Harald Welte47cd0e32020-08-21 12:39:11 +02003938import from BSSAP_LE_Emulation all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01003939import from RSL_Emulation all;
3940import from MSC_ConnectionHandler all;
3941
3942type function void_fn(charstring id) runs on MSC_ConnHdlr;
3943
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003944/* helper function to create and connect a MSC_ConnHdlr component
3945 * TODO: allow connecting to TRX1..N, not only TRX0 */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003946private 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 +02003947 connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003948 connect(vc_conn:RSL, bts[0][0].rsl.vc_RSL:CLIENT_PT);
3949 connect(vc_conn:RSL_PROC, bts[0][0].rsl.vc_RSL:RSL_PROC);
3950 if (isvalue(bts[1][0])) {
3951 connect(vc_conn:RSL1, bts[1][0].rsl.vc_RSL:CLIENT_PT);
3952 connect(vc_conn:RSL1_PROC, bts[1][0].rsl.vc_RSL:RSL_PROC);
Philipp Maier956a92f2018-02-16 10:58:07 +01003953 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003954 if (isvalue(bts[2][0])) {
3955 connect(vc_conn:RSL2, bts[2][0].rsl.vc_RSL:CLIENT_PT);
3956 connect(vc_conn:RSL2_PROC, bts[2][0].rsl.vc_RSL:RSL_PROC);
Neels Hofmeyr91401012019-07-11 00:42:35 +02003957 }
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003958 connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02003959 if (mp_enable_lcs_tests) {
3960 connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
3961 connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
3962 }
Daniel Willmannebdecc02020-08-12 15:30:17 +02003963 connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003964 connect(vc_conn:MGCP_PROC, vc_MGCP[mgwpool_idx]:MGCP_PROC);
3965 connect(vc_conn:MGCP, vc_MGCP[mgwpool_idx]:MGCP_CLIENT);
3966 connect(vc_conn:MGCP_MULTI, vc_MGCP[mgwpool_idx]:MGCP_CLIENT_MULTI);
Harald Welte336820c2018-05-31 20:34:52 +02003967}
3968
Neels Hofmeyrda436782021-07-20 22:09:06 +02003969function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
Harald Welte336820c2018-05-31 20:34:52 +02003970runs on test_CT return MSC_ConnHdlr {
3971 var charstring id := testcasename();
3972 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003973 var integer bssap_idx := 0;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003974 var integer mgwpool_idx := 0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003975 if (isvalue(pars)) {
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003976 var TestHdlrParams pars_val := valueof(pars);
3977 bssap_idx := pars_val.mscpool.bssap_idx;
3978 mgwpool_idx := pars_val.mgwpool_idx;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003979 }
Harald Welte336820c2018-05-31 20:34:52 +02003980 vc_conn := MSC_ConnHdlr.create(id);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003981 f_connect_handler(vc_conn, bssap_idx, mgwpool_idx);
Neels Hofmeyrda436782021-07-20 22:09:06 +02003982 return vc_conn;
3983}
3984
3985function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
3986runs on test_CT return MSC_ConnHdlr {
3987 var charstring id := testcasename();
Harald Weltea0630032018-03-20 21:09:55 +01003988 vc_conn.start(f_handler_init(fn, id, pars));
Harald Weltec1a2fff2017-12-17 11:06:19 +01003989 return vc_conn;
3990}
3991
Neels Hofmeyrda436782021-07-20 22:09:06 +02003992function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
3993runs on test_CT return MSC_ConnHdlr {
3994 return f_start_handler_run(f_start_handler_create(pars), fn, pars);
3995}
3996
Harald Weltea0630032018-03-20 21:09:55 +01003997/* first function inside ConnHdlr component; sets g_pars + starts function */
3998private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
3999runs on MSC_ConnHdlr {
4000 if (isvalue(pars)) {
4001 g_pars := valueof(pars);
4002 }
4003 fn.apply(id);
4004}
4005
Oliver Smith26a3db72021-07-09 13:51:29 +02004006private function f_vty_encryption_a5(charstring options) runs on test_CT {
4007 f_vty_transceive(BSCVTY, "configure terminal");
4008 f_vty_transceive(BSCVTY, "network");
4009 f_vty_transceive(BSCVTY, "encryption a5 " & options);
4010 f_vty_transceive(BSCVTY, "exit");
4011 f_vty_transceive(BSCVTY, "exit");
4012}
4013
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004014const charstring VTY_A5_DEFAULT := "0 1 3";
4015
Oliver Smith26a3db72021-07-09 13:51:29 +02004016private function f_vty_encryption_a5_reset() runs on test_CT {
4017 /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004018 f_vty_encryption_a5(VTY_A5_DEFAULT);
Oliver Smith26a3db72021-07-09 13:51:29 +02004019}
4020
Harald Welte3c86ea02018-05-10 22:28:05 +02004021/* Establish signalling channel (non-assignment case) followed by cipher mode */
4022private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004023 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4024 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte3c86ea02018-05-10 22:28:05 +02004025 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Philipp Maier23000732018-05-18 11:25:37 +02004026 ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode := omit;
4027 ass_cmd.pdu.bssmap.assignmentRequest.aoIPTransportLayer := omit;
4028 exp_compl.pdu.bssmap.assignmentComplete.circuitIdentityCode := omit;
4029 exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
Harald Welte3c86ea02018-05-10 22:28:05 +02004030
Philipp Maier23000732018-05-18 11:25:37 +02004031 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004032 f_perform_clear();
Harald Welte3c86ea02018-05-10 22:28:05 +02004033}
4034testcase TC_ciph_mode_a5_0() runs on test_CT {
4035 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004036 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004037 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
4038
4039 f_init(1, true);
4040 f_sleep(1.0);
4041 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4042 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004043 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004044}
4045testcase TC_ciph_mode_a5_1() runs on test_CT {
4046 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004047 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004048 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
4049
4050 f_init(1, true);
4051 f_sleep(1.0);
4052 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4053 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004054 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004055}
Oliver Smith50b98122021-07-09 15:00:28 +02004056/* OS#4975: verify that A5/2 is preferred over A5/0 */
4057testcase TC_ciph_mode_a5_2_0() runs on test_CT {
4058 var MSC_ConnHdlr vc_conn;
4059 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4060
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004061 pars.encr := f_encr_params('05'O, '04'O); /* A5/0 and A5/2 (0x01|0x04)*/
Oliver Smith50b98122021-07-09 15:00:28 +02004062
4063 f_init(1, true);
4064 f_vty_encryption_a5("0 1 2 3");
4065 f_sleep(1.0);
4066 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4067 vc_conn.done;
4068 f_vty_encryption_a5_reset();
4069 f_shutdown_helper();
4070}
Oliver Smith1dff88d2021-07-09 08:45:51 +02004071/* OS#4975: verify that A5/1 is preferred over A5/2 */
4072testcase TC_ciph_mode_a5_2_1() runs on test_CT {
4073 var MSC_ConnHdlr vc_conn;
4074 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4075
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004076 pars.encr := f_encr_params('06'O, '02'O); /* A5/1 and A5/2 (0x02|0x04)*/
Oliver Smith1dff88d2021-07-09 08:45:51 +02004077
4078 f_init(1, true);
4079 f_vty_encryption_a5("1 2");
4080 f_sleep(1.0);
4081 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4082 vc_conn.done;
4083 f_vty_encryption_a5_reset();
4084 f_shutdown_helper();
4085}
Harald Welte3c86ea02018-05-10 22:28:05 +02004086testcase TC_ciph_mode_a5_3() runs on test_CT {
4087 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004088 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004089 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
4090
4091 f_init(1, true);
4092 f_sleep(1.0);
4093 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4094 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004095 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004096}
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004097/* Establish a Signalling channel with A5/4 encryption. */
4098testcase TC_ciph_mode_a5_4() runs on test_CT {
4099 var MSC_ConnHdlr vc_conn;
4100 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4101 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Harald Welte3c86ea02018-05-10 22:28:05 +02004102
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004103 f_init(1, true);
Oliver Smith26a3db72021-07-09 13:51:29 +02004104 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004105 f_sleep(1.0);
4106 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4107 vc_conn.done;
Oliver Smith26a3db72021-07-09 13:51:29 +02004108 f_vty_encryption_a5_reset();
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004109 f_shutdown_helper();
4110}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004111/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
4112private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
4113 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4114 var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
4115 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4116 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4117
4118 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004119 f_perform_clear();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004120}
4121testcase TC_assignment_aoip_tla_v6() runs on test_CT {
4122 var MSC_ConnHdlr vc_conn;
4123 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4124
4125 f_init(1, true);
4126 f_sleep(1.0);
4127 vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
4128 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004129 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004130}
4131
Harald Welte3c86ea02018-05-10 22:28:05 +02004132
4133/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
Harald Welte651fcdc2018-05-10 20:23:16 +02004134private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004135 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4136 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004137
Harald Welte552620d2017-12-16 23:21:36 +01004138 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4139 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte73cd2712017-12-17 00:44:52 +01004140
Harald Weltea0630032018-03-20 21:09:55 +01004141 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004142 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004143}
Harald Welte552620d2017-12-16 23:21:36 +01004144testcase TC_assignment_fr_a5_0() runs on test_CT {
4145 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004146 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004147 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
Harald Welte552620d2017-12-16 23:21:36 +01004148
Harald Welte89d42e82017-12-17 16:42:41 +01004149 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004150 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004151 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004152 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004153 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004154}
Harald Welte552620d2017-12-16 23:21:36 +01004155testcase TC_assignment_fr_a5_1() runs on test_CT {
Harald Weltec1a2fff2017-12-17 11:06:19 +01004156 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004157 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004158 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004159
Harald Welte89d42e82017-12-17 16:42:41 +01004160 f_init(1, true);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004161 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004162 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4163 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004164 f_shutdown_helper();
Harald Welte651fcdc2018-05-10 20:23:16 +02004165}
4166testcase TC_assignment_fr_a5_3() runs on test_CT {
4167 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004168 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004169 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004170
Harald Welte651fcdc2018-05-10 20:23:16 +02004171 f_init(1, true);
4172 f_sleep(1.0);
4173 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004174 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004175 f_shutdown_helper();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004176}
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004177/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
4178testcase TC_assignment_fr_a5_4() runs on test_CT {
4179 var MSC_ConnHdlr vc_conn;
4180 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4181 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
4182
4183 f_init(1, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02004184 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004185 f_sleep(1.0);
4186 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4187 vc_conn.done;
Oliver Smith7eabd312021-07-12 14:18:56 +02004188 f_vty_encryption_a5_reset();
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004189 f_shutdown_helper();
4190}
Harald Weltec1a2fff2017-12-17 11:06:19 +01004191
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +02004192/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
4193testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
4194 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4195 var MSC_ConnHdlr vc_conn;
4196
4197 f_init(1, true);
4198 f_sleep(1.0);
4199
4200 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
4201 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
4202 vc_conn.done;
4203 f_shutdown_helper();
4204}
4205
Harald Welte552620d2017-12-16 23:21:36 +01004206/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
4207private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004208 g_pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004209 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02004210 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004211
4212 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02004213 /* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
4214
Harald Weltea0630032018-03-20 21:09:55 +01004215 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004216 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004217}
Harald Welte552620d2017-12-16 23:21:36 +01004218testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
4219 var MSC_ConnHdlr vc_conn;
4220
Harald Welte89d42e82017-12-17 16:42:41 +01004221 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004222 f_sleep(1.0);
4223
Harald Welte8863fa12018-05-10 20:15:27 +02004224 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
Harald Welte552620d2017-12-16 23:21:36 +01004225 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004226 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004227}
4228
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004229private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
4230 var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
4231 var PDU_BSSAP exp_ass_req := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004232
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004233 exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4234 exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4235
4236 /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
4237
4238 var BSSMAP_FIELD_CodecType codecType;
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004239
4240 codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
4241 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
4242
4243 f_create_chan_and_exp();
4244 /* we should now have a COMPL_L3 at the MSC */
4245
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004246 /* Start ciphering, expect Cipher Mode Reject */
Neels Hofmeyr6c388f22021-06-11 02:36:56 +02004247 f_cipher_mode(g_pars.encr, exp_fail := true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004248 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004249}
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004250testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
4251 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004252 var MSC_ConnHdlr vc_conn;
4253
Harald Welte89d42e82017-12-17 16:42:41 +01004254 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004255 f_sleep(1.0);
4256
Neels Hofmeyr0588cad2021-06-11 01:38:18 +02004257 pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004258 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004259 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004260 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004261}
4262
4263
Harald Welte4532e0a2017-12-23 02:05:44 +01004264private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004265 g_pars := f_gen_test_hdlr_pars();
Harald Welte4532e0a2017-12-23 02:05:44 +01004266 var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
Philipp Maier48604732018-10-09 15:00:37 +02004267 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte4532e0a2017-12-23 02:05:44 +01004268 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004269
4270 f_statsd_reset();
Harald Weltea0630032018-03-20 21:09:55 +01004271 f_establish_fully(ass_cmd, exp_compl);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004272
4273 var StatsDExpects expect := {
Daniel Willmannc5398f72020-09-21 10:41:35 +02004274 { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
4275 { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
Daniel Willmannebdecc02020-08-12 15:30:17 +02004276 { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
4277 { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
4278 };
4279 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004280 f_perform_clear();
Harald Welte4532e0a2017-12-23 02:05:44 +01004281}
4282
4283testcase TC_assignment_sign() runs on test_CT {
4284 var MSC_ConnHdlr vc_conn;
4285
4286 f_init(1, true);
4287 f_sleep(1.0);
4288
Harald Welte8863fa12018-05-10 20:15:27 +02004289 vc_conn := f_start_handler(refers(f_tc_assignment_sign));
Harald Welte4532e0a2017-12-23 02:05:44 +01004290 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004291 f_shutdown_helper();
Harald Welte4532e0a2017-12-23 02:05:44 +01004292}
4293
Harald Welte60aa5762018-03-21 19:33:13 +01004294/***********************************************************************
4295 * Codec (list) testing
4296 ***********************************************************************/
4297
4298/* check if the given rsl_mode is compatible with the a_elem */
4299private function f_match_codec(BSSMAP_FIELD_CodecElement a_elem, RSL_IE_ChannelMode rsl_mode)
4300return boolean {
4301 select (a_elem.codecType) {
4302 case (GSM_FR) {
4303 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1))) {
4304 return true;
4305 }
4306 }
4307 case (GSM_HR) {
4308 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1))) {
4309 return true;
4310 }
4311 }
4312 case (GSM_EFR) {
4313 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2))) {
4314 return true;
4315 }
4316 }
4317 case (FR_AMR) {
4318 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3))) {
4319 return true;
4320 }
4321 }
4322 case (HR_AMR) {
4323 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3))) {
4324 return true;
4325 }
4326 }
4327 case else { }
4328 }
4329 return false;
4330}
4331
4332/* check if the given rsl_mode is compatible with the a_list */
4333private function f_match_codecs(BSSMAP_IE_SpeechCodecList a_list, RSL_IE_ChannelMode rsl_mode)
4334return boolean {
4335 for (var integer i := 0; i < sizeof(a_list); i := i+1) {
4336 if (f_match_codec(a_list.codecElements[i], rsl_mode)) {
4337 return true;
4338 }
4339 }
4340 return false;
4341}
4342
4343/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
Philipp Maier61f6b572018-07-06 14:03:38 +02004344function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
Harald Welte60aa5762018-03-21 19:33:13 +01004345return BSSMAP_IE_ChannelType {
4346 /* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
4347 var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
4348 select (a_elem.codecType) {
4349 case (GSM_FR) {
4350 ret.channelRateAndType := ChRate_TCHF;
4351 ret.speechId_DataIndicator := Spdi_TCHF_FR;
4352 }
4353 case (GSM_HR) {
4354 ret.channelRateAndType := ChRate_TCHH;
4355 ret.speechId_DataIndicator := Spdi_TCHH_HR;
4356 }
4357 case (GSM_EFR) {
4358 ret.channelRateAndType := ChRate_TCHF;
4359 ret.speechId_DataIndicator := Spdi_TCHF_EFR;
4360 }
4361 case (FR_AMR) {
4362 ret.channelRateAndType := ChRate_TCHF;
4363 ret.speechId_DataIndicator := Spdi_TCHF_AMR;
4364 }
4365 case (HR_AMR) {
4366 ret.channelRateAndType := ChRate_TCHH;
4367 ret.speechId_DataIndicator := Spdi_TCHH_AMR;
4368 }
4369 case else {
4370 setverdict(fail, "Unsupported codec ", a_elem);
Daniel Willmannafce8662018-07-06 23:11:32 +02004371 mtc.stop;
Harald Welte60aa5762018-03-21 19:33:13 +01004372 }
4373 }
4374 return ret;
4375}
4376
Harald Weltea63b9102018-03-22 20:36:16 +01004377private function f_rsl_chmod_tmpl_from_codec(BSSMAP_FIELD_CodecElement a_elem)
4378return template RSL_IE_Body {
4379 var template RSL_IE_Body mode_ie := {
4380 chan_mode := {
4381 len := ?,
4382 reserved := ?,
4383 dtx_d := ?,
4384 dtx_u := ?,
4385 spd_ind := RSL_SPDI_SPEECH,
4386 ch_rate_type := -,
Oliver Smith0033b122023-02-28 13:30:53 +01004387 u := { speech := - }
Harald Weltea63b9102018-03-22 20:36:16 +01004388 }
4389 }
4390
4391 select (a_elem.codecType) {
4392 case (GSM_FR) {
4393 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004394 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004395 }
4396 case (GSM_HR) {
4397 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004398 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004399 }
4400 case (GSM_EFR) {
4401 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004402 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM2;
Harald Weltea63b9102018-03-22 20:36:16 +01004403 }
4404 case (FR_AMR) {
4405 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004406 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004407 }
4408 case (HR_AMR) {
4409 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004410 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004411 }
4412 }
4413 return mode_ie;
4414}
4415
Harald Welte60aa5762018-03-21 19:33:13 +01004416type record CodecListTest {
4417 BSSMAP_IE_SpeechCodecList codec_list,
4418 charstring id
4419}
4420type record of CodecListTest CodecListTests
4421
4422private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004423 f_assignment_codec(id);
4424}
4425
4426private function f_assignment_codec(charstring id, boolean do_perform_clear := true) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02004427 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02004428 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welte60aa5762018-03-21 19:33:13 +01004429
4430 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004431 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte79f3f542018-05-25 20:02:37 +02004432 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4433 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
4434 g_pars.ass_codec_list.codecElements[0];
Philipp Maierd0e64b02019-03-13 14:15:23 +01004435 if (isvalue(g_pars.expect_mr_s0_s7)) {
4436 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
4437 g_pars.expect_mr_s0_s7;
4438 }
Harald Welte79f3f542018-05-25 20:02:37 +02004439 }
Harald Welte60aa5762018-03-21 19:33:13 +01004440 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4441 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
Harald Welte60aa5762018-03-21 19:33:13 +01004442 log("expecting ASS COMPL like this: ", exp_compl);
4443
4444 f_establish_fully(ass_cmd, exp_compl);
Harald Weltea63b9102018-03-22 20:36:16 +01004445
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004446 if (not g_pars.expect_channel_mode_modify) {
4447 /* Verify that the RSL-side activation actually matches our expectations */
4448 var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
Harald Weltea63b9102018-03-22 20:36:16 +01004449
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004450 var RSL_IE_Body mode_ie;
4451 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
4452 setverdict(fail, "Couldn't find CHAN_MODE IE");
Daniel Willmannafce8662018-07-06 23:11:32 +02004453 mtc.stop;
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004454 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004455 var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
4456 if (not match(mode_ie, t_mode_ie)) {
4457 log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
4458 setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004459 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004460
4461 var RSL_IE_Body mr_conf;
4462 if (g_pars.expect_mr_conf_ie != omit) {
4463 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
4464 setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
4465 mtc.stop;
4466 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004467 log("found RSL MR CONFIG IE: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004468
4469 if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
Vadim Yanitskiy8b189372022-09-14 17:31:17 +07004470 setverdict(fail, "RSL MR CONFIG IE does not match expectation. ",
4471 "Expected: ", g_pars.expect_mr_conf_ie, ", got: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004472 }
4473 } else {
4474 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
4475 log("found RSL MR CONFIG IE: ", mr_conf);
4476 setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
4477 mtc.stop;
4478 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004479 }
4480 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004481
4482 if (do_perform_clear) {
4483 f_perform_clear();
4484 }
Harald Welte60aa5762018-03-21 19:33:13 +01004485}
4486
Philipp Maierd0e64b02019-03-13 14:15:23 +01004487private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
4488
4489 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4490 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4491
4492 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004493 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maierd0e64b02019-03-13 14:15:23 +01004494 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4495 }
4496 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4497 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
4498 log("expecting ASS FAIL like this: ", exp_fail);
4499
4500 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004501 f_perform_clear();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004502}
4503
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004504const CounterNameVals counternames_bsc_bts_assignment := {
4505 { "assignment:attempted", 0 },
4506 { "assignment:completed", 0 },
4507 { "assignment:stopped", 0 },
4508 { "assignment:no_channel", 0 },
4509 { "assignment:timeout", 0 },
4510 { "assignment:failed", 0 },
4511 { "assignment:error", 0 }
4512};
4513
4514const CounterNameVals counternames_bts_assignment := {
4515 { "assignment:attempted_sign", 0 },
4516 { "assignment:attempted_speech", 0 },
4517 { "assignment:completed_sign", 0 },
4518 { "assignment:completed_speech", 0 },
4519 { "assignment:stopped_sign", 0 },
4520 { "assignment:stopped_speech", 0 },
4521 { "assignment:no_channel_sign", 0 },
4522 { "assignment:no_channel_speech", 0 },
4523 { "assignment:timeout_sign", 0 },
4524 { "assignment:timeout_speech", 0 },
4525 { "assignment:failed_sign", 0 },
4526 { "assignment:failed_speech", 0 },
4527 { "assignment:error_sign", 0 },
4528 { "assignment:error_speech", 0 }
4529};
4530
4531function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
4532 var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
4533 f_ctrs_bts_init(bts_count, bts_names);
4534 f_ctrs_bsc_init(counternames_bsc_bts_assignment);
4535}
4536
Harald Welte60aa5762018-03-21 19:33:13 +01004537testcase TC_assignment_codec_fr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004538 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004539 var MSC_ConnHdlr vc_conn;
4540
4541 f_init(1, true);
4542 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004543 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004544
4545 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004546 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004547 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004548
4549 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4550 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4551 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4552 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4553 f_ctrs_bts_verify();
4554
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004555 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004556}
4557
4558testcase TC_assignment_codec_hr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004559 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004560 var MSC_ConnHdlr vc_conn;
4561
4562 f_init(1, true);
4563 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004564 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004565
4566 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004567 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004568 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004569
4570 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4571 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4572 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4573 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4574 f_ctrs_bts_verify();
4575
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004576 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004577}
4578
4579testcase TC_assignment_codec_efr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004580 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004581 var MSC_ConnHdlr vc_conn;
4582
4583 f_init(1, true);
4584 f_sleep(1.0);
4585
4586 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004587 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004588 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004589 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004590}
4591
Philipp Maierd0e64b02019-03-13 14:15:23 +01004592/* Allow 5,90k only (current default config) */
4593private function f_allow_amr_rate_5_90k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004594 f_vty_cfg_msc(BSCVTY, 0, {
4595 "amr-config 12_2k forbidden",
4596 "amr-config 10_2k forbidden",
4597 "amr-config 7_95k forbidden",
4598 "amr-config 7_40k forbidden",
4599 "amr-config 6_70k forbidden",
4600 "amr-config 5_90k allowed",
4601 "amr-config 5_15k forbidden",
4602 "amr-config 4_75k forbidden"
4603 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004604}
4605
4606/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
4607 * ("Config-NB-Code = 1") */
4608private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004609 f_vty_cfg_msc(BSCVTY, 0, {
4610 "amr-config 12_2k allowed",
4611 "amr-config 10_2k forbidden",
4612 "amr-config 7_95k forbidden",
4613 "amr-config 7_40k allowed",
4614 "amr-config 6_70k forbidden",
4615 "amr-config 5_90k allowed",
4616 "amr-config 5_15k forbidden",
4617 "amr-config 4_75k allowed"
4618 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004619}
4620
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004621private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
4622 var charstring tch;
4623 if (fr) {
4624 tch := "tch-f";
4625 } else {
4626 tch := "tch-h";
4627 }
4628 f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
4629}
4630
4631/* Set the AMR start-mode for this TCH back to the default configuration. */
4632private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
4633 f_vty_amr_start_mode_set(fr, "auto");
4634}
4635
Harald Welte60aa5762018-03-21 19:33:13 +01004636testcase TC_assignment_codec_amr_f() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004637 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004638 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004639
4640 /* Note: This setups the codec configuration. The parameter payload in
4641 * mr_conf must be consistant with the parameter codecElements in pars
4642 * and also must match the amr-config in osmo-bsc.cfg! */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004643 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004644 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004645 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004646 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004647
Harald Welte60aa5762018-03-21 19:33:13 +01004648 f_init(1, true);
4649 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004650 f_vty_amr_start_mode_set(true, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004651 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004652
Harald Welte8863fa12018-05-10 20:15:27 +02004653 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004654 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004655
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004656 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4657 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4658 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4659 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4660 f_ctrs_bts_verify();
4661
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004662 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004663 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004664}
4665
4666testcase TC_assignment_codec_amr_h() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004667 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004668 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004669
4670 /* See note above */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004671 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004672 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004673 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004674 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004675
Harald Welte60aa5762018-03-21 19:33:13 +01004676 f_init(1, true);
4677 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004678 f_vty_amr_start_mode_set(false, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004679 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004680
Harald Welte8863fa12018-05-10 20:15:27 +02004681 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004682 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004683
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004684 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4685 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4686 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4687 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4688 f_ctrs_bts_verify();
4689
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004690 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004691 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004692}
4693
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004694/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
4695testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
4696 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4697 var MSC_ConnHdlr vc_conn;
4698
4699 f_init(1, true);
4700 f_sleep(1.0);
4701
4702 /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
4703 * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
4704 * expecting a Channel Mode Modify if the channel type is compatible. */
4705 f_disable_all_sdcch();
4706 f_disable_all_tch_h();
4707
4708 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4709 pars.expect_channel_mode_modify := true;
4710 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4711 vc_conn.done;
4712
4713 f_enable_all_sdcch();
4714 f_enable_all_tch();
4715 f_shutdown_helper();
4716}
4717
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004718/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
4719testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
4720 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4721 var MSC_ConnHdlr vc_conn;
4722
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004723 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4724 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
4725 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy36fe9582022-09-14 15:25:04 +07004726 pars.expect_mr_conf_ie := c_mr_conf_5_90;
4727 pars.expect_mr_conf_ie.multirate_cfg.icmi := false; /* expect ICMI=0, smod=00: */
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004728
4729 f_init(1, true);
4730 f_sleep(1.0);
4731
4732 /* First set nonzero start mode bits */
4733 f_vty_amr_start_mode_set(true, "4");
4734 /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
4735 * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
4736 * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
4737 f_vty_amr_start_mode_set(true, "auto");
4738
4739 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4740 vc_conn.done;
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004741
4742 /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
4743 f_vty_amr_start_mode_set(true, "1");
4744 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004745 f_shutdown_helper();
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004746}
4747
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004748function f_TC_assignment_codec_amr(boolean fr, RSL_IE_MultirateCfg mr_cfg,
4749 bitstring s8_s0, bitstring exp_s8_s0,
4750 charstring start_mode := "1")
Philipp Maierd0e64b02019-03-13 14:15:23 +01004751runs on test_CT {
4752
4753 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4754 var MSC_ConnHdlr vc_conn;
4755
Philipp Maierd0e64b02019-03-13 14:15:23 +01004756 if (fr) {
4757 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4758 } else {
4759 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4760 }
4761 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4762 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004763 pars.expect_mr_conf_ie := { multirate_cfg := mr_cfg };
Philipp Maierd0e64b02019-03-13 14:15:23 +01004764 pars.expect_mr_s0_s7 := exp_s8_s0;
4765
4766 f_init(1, true);
4767 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004768 f_vty_amr_start_mode_set(fr, start_mode);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004769 f_sleep(1.0);
4770
4771 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4772 vc_conn.done;
4773 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004774 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004775}
4776
4777function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
4778runs on test_CT {
4779
4780 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4781 var MSC_ConnHdlr vc_conn;
4782
4783 if (fr) {
4784 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4785 } else {
4786 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4787 }
4788 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4789 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4790
4791 f_init(1, true);
4792 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004793 f_vty_amr_start_mode_set(fr, "1");
Philipp Maierd0e64b02019-03-13 14:15:23 +01004794 f_sleep(1.0);
4795
4796 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
4797 vc_conn.done;
4798 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004799 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004800}
4801
Philipp Maierd0e64b02019-03-13 14:15:23 +01004802/* Set S1, we expect an AMR multirate configuration IE with all four rates
4803 * set. */
4804testcase TC_assignment_codec_amr_f_S1() 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, '00000011'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, we expect an AMR multirate configuration IE with the lower three
4812 * rates set. */
4813testcase TC_assignment_codec_amr_h_S1() 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, '00000010'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/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4821 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4822testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004823 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4824 params := '20882208'O));
4825 f_TC_assignment_codec_amr(true, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004826 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004827}
4828
4829/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4830 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4831testcase TC_assignment_codec_amr_h_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004832 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4833 params := '208820'O));
4834 f_TC_assignment_codec_amr(false, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004835 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004836}
4837
4838/* The following block of tests selects more and more rates until all four
4839 * possible rates are in the active set (full rate) */
4840testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004841 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4842 f_TC_assignment_codec_amr(true, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004843 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004844}
4845
4846testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004847 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4848 params := '2080'O));
4849 f_TC_assignment_codec_amr(true, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004850 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004851}
4852
4853testcase TC_assignment_codec_amr_f_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004854 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4855 params := '208820'O));
4856 f_TC_assignment_codec_amr(true, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004857 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004858}
4859
4860testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004861 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4862 params := '20882208'O));
4863 f_TC_assignment_codec_amr(true, mr_cfg, '10010101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004864 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004865}
4866
4867/* The following block of tests selects more and more rates until all three
4868 * possible rates are in the active set (half rate) */
4869testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004870 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4871 f_TC_assignment_codec_amr(false, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004872 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004873}
4874
4875testcase TC_assignment_codec_amr_h_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004876 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4877 params := '2080'O));
4878 f_TC_assignment_codec_amr(false, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004879 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004880}
4881
4882testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004883 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4884 params := '208820'O));
4885 f_TC_assignment_codec_amr(false, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004886 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004887}
4888
4889/* The following block tests what happens when the MSC does offer rate
4890 * configurations that are not supported by the BSC. Normally such situations
4891 * should not happen because the MSC gets informed by the BSC in advance via
4892 * the L3 COMPLETE message which rates are applicable. The MSC should not try
4893 * to offer rates that are not applicable anyway. */
4894
4895testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004896 /* Try to include 12,2k in into the active set even though the channel
4897 * is half rate only. The BSC is expected to remove the 12,0k */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004898 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4899 params := '208820'O));
4900 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004901 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004902}
4903
4904testcase TC_assignment_codec_amr_f_S01234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004905 /* See what happens when all rates are selected at once. Since then
4906 * Also S1 is selected, this setting will be prefered and we should
4907 * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004908 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4909 params := '20882208'O));
4910 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004911 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004912}
4913
4914testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004915 /* Same as above, but with S1 missing, the MSC is then expected to
4916 * select the currently supported rates, which are also 12.2k, 7,40k,
4917 * 5,90k, and 4,75k, into the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004918 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4919 params := '20882208'O));
4920 f_TC_assignment_codec_amr(true, mr_cfg, '11111101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004921 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004922}
4923
4924testcase TC_assignment_codec_amr_f_zero() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004925 /* Try to select no rates at all */
4926 f_TC_assignment_codec_amr_fail(true, '00000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004927 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004928}
4929
4930testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004931 /* Try to select only unsupported rates */
4932 f_TC_assignment_codec_amr_fail(true, '01101000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004933 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004934}
4935
4936testcase TC_assignment_codec_amr_h_S7() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004937 /* Try to select 12,2k for half rate */
4938 f_TC_assignment_codec_amr_fail(false, '10000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004939 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004940}
4941
Neels Hofmeyr21863562020-11-26 00:34:33 +00004942testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004943 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4944 codec_modes := '10010101'B,
4945 params := '20882208'O));
4946 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004947 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004948}
4949
4950testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004951 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4952 codec_modes := '00010101'B,
4953 params := '208820'O));
4954 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B,
Neels Hofmeyr21863562020-11-26 00:34:33 +00004955 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004956 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004957}
4958
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004959testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004960 /* "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 +07004961 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 3,
4962 codec_modes := '10010101'B,
4963 params := '20882208'O));
4964 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004965 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004966}
4967
4968testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004969 /* "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 +07004970 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 2,
4971 codec_modes := '00010101'B,
4972 params := '208820'O));
4973 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004974 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004975}
4976
Philipp Maierac09bfc2019-01-08 13:41:39 +01004977private function f_disable_all_tch_f() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004978 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 borken");
4979 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 borken");
4980 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 borken");
4981 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004982}
4983
4984private function f_disable_all_tch_h() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004985 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 borken");
4986 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004987}
4988
4989private function f_enable_all_tch() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004990 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 unused");
4991 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 unused");
4992 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 unused");
4993 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 unused");
4994 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 unused");
4995 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004996}
4997
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004998private function f_disable_all_sdcch() runs on test_CT {
4999 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
5000 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
5001 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
5002 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
5003}
5004
5005private function f_enable_all_sdcch() runs on test_CT {
5006 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
5007 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
5008 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
5009 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
5010}
5011
Philipp Maierac09bfc2019-01-08 13:41:39 +01005012/* Allow HR only */
5013private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs on MSC_ConnHdlr {
5014 g_pars := f_gen_test_hdlr_pars();
5015 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5016 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5017 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5018 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5019 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5020 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5021 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005022 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005023}
5024
5025/* Allow FR only */
5026private function f_TC_assignment_codec_xr_exhausted_req_fr(charstring id) runs on MSC_ConnHdlr {
5027 g_pars := f_gen_test_hdlr_pars();
5028 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5029 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5030 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5031 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5032 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5033 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5034 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005035 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005036}
5037
5038/* Allow HR only (expect assignment failure) */
5039private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) runs on MSC_ConnHdlr {
5040 g_pars := f_gen_test_hdlr_pars();
5041 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5042 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5043 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5044 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5045 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5046 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5047 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005048 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005049}
5050
5051/* Allow FR only (expect assignment failure) */
5052private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) runs on MSC_ConnHdlr {
5053 g_pars := f_gen_test_hdlr_pars();
5054 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5055 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5056 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5057 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5058 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5059 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5060 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005061 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005062}
5063
5064/* Allow FR and HR, but prefer FR */
5065private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5066 g_pars := f_gen_test_hdlr_pars();
5067 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5068 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5069 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5070 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5071 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5072 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5073 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5074 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005075 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005076}
5077
5078/* Allow FR and HR, but prefer HR */
5079private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5080 g_pars := f_gen_test_hdlr_pars();
5081 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5082 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5083 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5084 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5085 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5086 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5087 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5088 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005089 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005090}
5091
5092/* Allow FR and HR, but prefer FR */
5093private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5094 g_pars := f_gen_test_hdlr_pars();
5095 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5096 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5097 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5098 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5099 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5100 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5101 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5102 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005103 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005104}
5105
5106/* Allow FR and HR, but prefer HR */
5107private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5108 g_pars := f_gen_test_hdlr_pars();
5109 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5110 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5111 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5112 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5113 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5114 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5115 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5116 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005117 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005118}
5119
5120/* Request a HR channel while all FR channels are exhausted, this is expected
5121 * to work without conflicts */
5122testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
5123 var MSC_ConnHdlr vc_conn;
5124 f_init(1, true);
5125 f_sleep(1.0);
5126 f_enable_all_tch();
5127 f_disable_all_tch_f();
5128 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
5129 vc_conn.done;
5130 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005131 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005132}
5133
5134/* Request a FR channel while all FR channels are exhausted, this is expected
5135 * to fail. */
5136testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
5137 var MSC_ConnHdlr vc_conn;
5138 f_init(1, true);
5139 f_sleep(1.0);
5140 f_enable_all_tch();
5141 f_disable_all_tch_f();
5142 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
5143 vc_conn.done;
5144 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005145 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005146}
5147
5148/* Request a FR (prefered) or alternatively a HR channel while all FR channels
5149 * are exhausted, this is expected to be resolved by selecting a HR channel. */
5150testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
5151 var MSC_ConnHdlr vc_conn;
5152 f_init(1, true);
5153 f_sleep(1.0);
5154 f_enable_all_tch();
5155 f_disable_all_tch_f();
5156 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
5157 vc_conn.done;
5158 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005159 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005160}
5161
5162/* Request a HR (prefered) or alternatively a FR channel while all FR channels
5163 * are exhausted, this is expected to work without conflicts. */
5164testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
5165 var MSC_ConnHdlr vc_conn;
5166 f_init(1, true);
5167 f_sleep(1.0);
5168 f_enable_all_tch();
5169 f_disable_all_tch_f();
5170 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
5171 vc_conn.done;
5172 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005173 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005174}
5175
5176/* Request a FR channel while all HR channels are exhausted, this is expected
5177 * to work without conflicts */
5178testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
5179 var MSC_ConnHdlr vc_conn;
5180 f_init(1, true);
5181 f_sleep(1.0);
5182 f_enable_all_tch();
5183 f_disable_all_tch_h();
5184 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
5185 vc_conn.done;
5186 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005187 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005188}
5189
5190/* Request a HR channel while all HR channels are exhausted, this is expected
5191 * to fail. */
5192testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
5193 var MSC_ConnHdlr vc_conn;
5194 f_init(1, true);
5195 f_sleep(1.0);
5196 f_enable_all_tch();
5197 f_disable_all_tch_h();
5198 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
5199 vc_conn.done;
5200 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005201 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005202}
5203
5204/* Request a HR (prefered) or alternatively a FR channel while all HR channels
5205 * are exhausted, this is expected to be resolved by selecting a FR channel. */
5206testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
5207 var MSC_ConnHdlr vc_conn;
5208 f_init(1, true);
5209 f_sleep(1.0);
5210 f_enable_all_tch();
5211 f_disable_all_tch_h();
5212 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
5213 vc_conn.done;
5214 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005215 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005216}
5217
5218/* Request a FR (prefered) or alternatively a HR channel while all HR channels
5219 * are exhausted, this is expected to work without conflicts. */
5220testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
5221 var MSC_ConnHdlr vc_conn;
5222 f_init(1, true);
5223 f_sleep(1.0);
5224 f_enable_all_tch();
5225 f_disable_all_tch_h();
5226 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
5227 vc_conn.done;
5228 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005229 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005230}
5231
5232/* Allow FR and HR, but prefer HR */
5233private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5234 g_pars := f_gen_test_hdlr_pars();
5235 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5236 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5237 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5238 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5239 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5240 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5241 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5242 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005243 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005244}
5245
5246/* Allow FR and HR, but prefer FR */
5247private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5248 g_pars := f_gen_test_hdlr_pars();
5249 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5250 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5251 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5252 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5253 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5254 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5255 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5256 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005257 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005258}
5259
5260/* Request a HR (prefered) or alternatively a FR channel, it is expected that
5261 * HR, which is the prefered type, is selected. */
5262testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
5263 var MSC_ConnHdlr vc_conn;
5264 f_init(1, true);
5265 f_sleep(1.0);
5266 f_enable_all_tch();
5267 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
5268 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005269 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005270}
5271
5272/* Request a FR (prefered) or alternatively a HR channel, it is expected that
5273 * FR, which is the prefered type, is selected. */
5274testcase TC_assignment_codec_req_fr_hr() runs on test_CT {
5275 var MSC_ConnHdlr vc_conn;
5276 f_init(1, true);
5277 f_sleep(1.0);
5278 f_enable_all_tch();
5279 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_fr_hr));
5280 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005281 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005282}
5283
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005284/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
5285private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
5286 g_pars := f_gen_test_hdlr_pars();
5287 g_pars.ra := '02'O; /* RA containing reason=LU */
5288
5289 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5290 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5291 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5292 var template uint3_t tsc := ?;
5293
5294 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5295 f_create_bssmap_exp(l3_enc);
5296 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5297 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5298
5299 /* we should now have a COMPL_L3 at the MSC */
5300 timer T := 10.0;
5301 T.start;
5302 alt {
5303 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5304 [] T.timeout {
5305 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5306 }
5307 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005308
5309 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005310}
5311testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
5312 var MSC_ConnHdlr vc_conn;
5313 f_init(1, true);
5314 f_sleep(1.0);
5315 f_disable_all_sdcch();
5316 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
5317 vc_conn.done;
5318 f_enable_all_sdcch();
5319 f_shutdown_helper();
5320}
5321
5322/* Request a signalling channel with all SDCCH exhausted, it is
5323 expected that no TCH will be selected for signalling and assigment will fail
5324 because it's dictated by VTY config */
5325testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
5326 var RSL_Message rsl_unused, rsl_msg;
5327 var GsmRrMessage rr;
5328 f_init(1, false);
5329 f_sleep(1.0);
5330 f_vty_allow_tch_for_signalling(false, 0);
5331 f_disable_all_sdcch();
5332
5333 /* RA containing reason=LU */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005334 f_ipa_tx(ts_RSL_CHAN_RQD('02'O, 2342));
5335 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005336 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
5337 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
5338 setverdict(fail, "Expected reject");
5339 }
5340
5341 f_vty_allow_tch_for_signalling(true, 0);
5342 f_enable_all_sdcch();
5343 f_shutdown_helper();
5344}
5345
5346/* Request a voice channel with all SDCCH exhausted, it is
5347 * expected that TCH channel will be allocated since the VTY option is only
5348 * aimed at signalling requests */
5349private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
5350 g_pars := f_gen_test_hdlr_pars();
5351 g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
5352
5353 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5354 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5355 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5356 var template uint3_t tsc := ?;
5357
5358 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5359 f_create_bssmap_exp(l3_enc);
5360 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5361 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5362
5363 /* we should now have a COMPL_L3 at the MSC */
5364 timer T := 10.0;
5365 T.start;
5366 alt {
5367 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5368 [] T.timeout {
5369 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5370 }
5371 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005372 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005373}
5374testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
5375 var MSC_ConnHdlr vc_conn;
5376 f_init(1, true);
5377 f_sleep(1.0);
5378 f_vty_allow_tch_for_signalling(false, 0);
5379 f_disable_all_sdcch();
5380
5381 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
5382 vc_conn.done;
5383
5384 f_vty_allow_tch_for_signalling(true, 0);
5385 f_enable_all_sdcch();
5386 f_shutdown_helper();
5387}
5388
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005389/* Test Osmux setup BSC<->MSC */
5390testcase TC_assignment_osmux_cn() runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005391 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5392 var MSC_ConnHdlr vc_conn;
5393
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005394 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5395 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5396 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiyb9bf00f2022-09-14 15:35:37 +07005397 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02005398 pars.use_osmux_cn := true;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005399
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02005400 g_osmux_enabled_cn := true;
5401 f_init(1, true);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005402 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005403 f_vty_amr_start_mode_set(false, "1");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005404
5405 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5406 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005407
5408 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01005409 f_shutdown_helper();
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005410}
5411
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005412/* Test Osmux setup BTS<->BSC */
5413testcase TC_assignment_osmux_bts() runs on test_CT {
5414 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5415 var MSC_ConnHdlr vc_conn;
5416
5417 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5418 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5419 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005420 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005421 pars.use_osmux_bts := true;
5422
5423 g_osmux_enabled_bts := true;
5424 f_init(1, true);
5425 f_sleep(1.0);
5426 f_vty_amr_start_mode_set(false, "1");
5427
5428 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5429 vc_conn.done;
5430
5431 f_vty_amr_start_mode_restore(false);
5432 f_shutdown_helper();
5433}
5434
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +02005435/* Test non-AMR codecs still work fine as RTP when Osmux is enabled BTS<->BSC<->MSC */
5436testcase TC_assignment_codec_hr_osmux_on() runs on test_CT {
5437 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5438 var MSC_ConnHdlr vc_conn;
5439
5440 g_osmux_enabled_cn := true;
5441 g_osmux_enabled_bts := true;
5442 f_init(1, true);
5443 f_sleep(1.0);
5444 f_ctrs_bsc_and_bts_assignment_init(1);
5445
5446 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5447 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5448 vc_conn.done;
5449
5450 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
5451 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
5452 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
5453 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
5454 f_ctrs_bts_verify();
5455
5456 f_shutdown_helper();
5457}
5458
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005459/* Test Osmux setup BTS<->BSC<->MSC */
5460testcase TC_assignment_osmux() runs on test_CT {
5461 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5462 var MSC_ConnHdlr vc_conn;
5463
5464 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5465 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5466 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005467 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005468 pars.use_osmux_cn := true;
5469 pars.use_osmux_bts := true;
5470
5471 g_osmux_enabled_cn := true;
5472 g_osmux_enabled_bts := true;
5473 f_init(1, true);
5474 f_sleep(1.0);
5475 f_vty_amr_start_mode_set(false, "1");
5476
5477 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5478 vc_conn.done;
5479
5480 f_vty_amr_start_mode_restore(false);
5481 f_shutdown_helper();
5482}
5483
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005484/* test the procedure of the MSC requesting a Classmark Update:
5485 * a) BSSMAP Classmark Request should result in RR CLASSMARK ENQUIRY,
5486 * b) L3 RR CLASSMARK CHANGE should result in BSSMAP CLASSMARK UPDATE */
Harald Welte898113b2018-01-31 18:32:21 +01005487private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005488 g_pars := f_gen_test_hdlr_pars();
5489
Harald Weltea0630032018-03-20 21:09:55 +01005490 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005491 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005492
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005493 BSSAP.send(ts_BSSMAP_ClassmarkRequest);
5494 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
5495
Harald Welte898113b2018-01-31 18:32:21 +01005496 f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
5497 BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
5498 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005499
5500 f_perform_clear();
Harald Welte898113b2018-01-31 18:32:21 +01005501}
5502testcase TC_classmark() runs on test_CT {
5503 var MSC_ConnHdlr vc_conn;
5504 f_init(1, true);
5505 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005506 vc_conn := f_start_handler(refers(f_tc_classmark));
Harald Welte898113b2018-01-31 18:32:21 +01005507 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005508 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005509}
5510
Harald Welteeddf0e92020-06-21 19:42:15 +02005511/* Send a CommonID from the simulated MSC and verify that the information is used to
5512 * fill BSC-internal data structures (specifically, bsc_subscr associated with subscr_conn) */
5513private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
5514 g_pars := f_gen_test_hdlr_pars();
5515 f_MscConnHdlr_init_vty();
5516
5517 f_create_chan_and_exp();
5518 /* we should now have a COMPL_L3 at the MSC */
Harald Welteeddf0e92020-06-21 19:42:15 +02005519
5520 /* Send CommonID */
5521 BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
5522
5523 /* Use VTY to verify that the IMSI of the subscr_conn is set */
5524 var charstring regex := "*(IMSI: " & hex2str(g_pars.imsi) & ")*";
5525 f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
5526
5527 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005528
5529 f_perform_clear();
Harald Welteeddf0e92020-06-21 19:42:15 +02005530}
5531testcase TC_common_id() runs on test_CT {
5532 var MSC_ConnHdlr vc_conn;
5533 f_init(1, true);
5534 f_sleep(1.0);
5535 vc_conn := f_start_handler(refers(f_tc_common_id));
5536 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005537 f_shutdown_helper();
Harald Welteeddf0e92020-06-21 19:42:15 +02005538}
5539
Harald Weltee3bd6582018-01-31 22:51:25 +01005540private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005541 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005542 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005543 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005544
Harald Weltee3bd6582018-01-31 22:51:25 +01005545 /* send the single message we want to send */
5546 f_rsl_send_l3(l3);
5547}
5548
5549private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr {
5550 timer T := sec;
5551 var PDU_BSSAP bssap;
Harald Welte898113b2018-01-31 18:32:21 +01005552 T.start;
5553 alt {
Harald Weltee3bd6582018-01-31 22:51:25 +01005554 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap {
5555 setverdict(fail, "Unexpected BSSMAP ", bssap);
Daniel Willmannafce8662018-07-06 23:11:32 +02005556 mtc.stop;
Harald Welte898113b2018-01-31 18:32:21 +01005557 }
5558 [] T.timeout {
5559 setverdict(pass);
5560 }
5561 }
5562}
5563
Harald Weltee3bd6582018-01-31 22:51:25 +01005564/* unsolicited ASSIGNMENT FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5565private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
5566 f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
5567 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005568 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005569}
Harald Welte898113b2018-01-31 18:32:21 +01005570testcase TC_unsol_ass_fail() runs on test_CT {
5571 var MSC_ConnHdlr vc_conn;
5572 f_init(1, true);
5573 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005574 vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
Harald Welte898113b2018-01-31 18:32:21 +01005575 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005576 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005577}
Harald Welte552620d2017-12-16 23:21:36 +01005578
Harald Welteea99a002018-01-31 20:46:43 +01005579
5580/* unsolicited ASSIGNMENT COMPLETE (without ASSIGN) from MS shouldn't bring BSC down */
5581private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005582 f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
5583 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005584 f_perform_clear();
Harald Welteea99a002018-01-31 20:46:43 +01005585}
5586testcase TC_unsol_ass_compl() runs on test_CT {
5587 var MSC_ConnHdlr vc_conn;
5588 f_init(1, true);
5589 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005590 vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
Harald Welteea99a002018-01-31 20:46:43 +01005591 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005592 f_shutdown_helper();
Harald Welteea99a002018-01-31 20:46:43 +01005593}
5594
5595
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005596/* unsolicited HANDOVER FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5597private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005598 f_est_single_l3(ts_RRM_HandoverFailure('00'O));
5599 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005600 f_perform_clear();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005601}
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005602testcase TC_unsol_ho_fail() runs on test_CT {
5603 var MSC_ConnHdlr vc_conn;
5604 f_init(1, true);
5605 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005606 vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005607 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005608 f_shutdown_helper();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005609}
5610
5611
Harald Weltee3bd6582018-01-31 22:51:25 +01005612/* short message from MS should be ignored */
5613private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005614 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005615 f_create_chan_and_exp();
Harald Weltee3bd6582018-01-31 22:51:25 +01005616 /* we should now have a COMPL_L3 at the MSC */
Harald Weltee3bd6582018-01-31 22:51:25 +01005617
5618 /* send short message */
5619 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
5620 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005621 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005622}
5623testcase TC_err_82_short_msg() runs on test_CT {
5624 var MSC_ConnHdlr vc_conn;
5625 f_init(1, true);
5626 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005627 vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
Harald Weltee3bd6582018-01-31 22:51:25 +01005628 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005629 f_shutdown_helper();
Harald Weltee3bd6582018-01-31 22:51:25 +01005630}
5631
5632
Harald Weltee9e02e42018-01-31 23:36:25 +01005633/* 24.008 8.4 Unknown message must trigger RR STATUS */
5634private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
5635 f_est_single_l3(ts_RRM_UL_REL('00'O));
5636 timer T := 3.0
5637 alt {
5638 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
5639 setverdict(pass);
5640 }
5641 [] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
Harald Welte458fd372018-03-21 11:26:23 +01005642 [] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
Harald Weltee9e02e42018-01-31 23:36:25 +01005643 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005644 f_perform_clear();
Harald Weltee9e02e42018-01-31 23:36:25 +01005645}
5646testcase TC_err_84_unknown_msg() runs on test_CT {
5647 var MSC_ConnHdlr vc_conn;
5648 f_init(1, true);
5649 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005650 vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
Harald Weltee9e02e42018-01-31 23:36:25 +01005651 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005652 f_shutdown_helper();
Harald Weltee9e02e42018-01-31 23:36:25 +01005653}
5654
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005655/***********************************************************************
5656 * Handover
5657 ***********************************************************************/
5658
Harald Welte94e0c342018-04-07 11:33:23 +02005659/* execute a "bts <0-255> trx <0-255> timeslot <0-7> " command on given Dchan */
5660private function f_vty_ts_action(charstring suffix, integer bts_nr, integer trx_nr, integer ts_nr)
5661runs on test_CT {
5662 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5663 " timeslot "&int2str(ts_nr)&" ";
5664 f_vty_transceive(BSCVTY, cmd & suffix);
5665}
5666
Harald Welte261af4b2018-02-12 21:20:39 +01005667/* 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 +07005668private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
5669 uint8_t bts_nr, uint8_t trx_nr,
5670 in RslChannelNr chan_nr)
5671{
Harald Welte261af4b2018-02-12 21:20:39 +01005672 /* FIXME: resolve those from component-global state */
5673 var integer ts_nr := chan_nr.tn;
5674 var integer ss_nr;
5675 if (ischosen(chan_nr.u.ch0)) {
5676 ss_nr := 0;
5677 } else if (ischosen(chan_nr.u.lm)) {
5678 ss_nr := chan_nr.u.lm.sub_chan;
5679 } else if (ischosen(chan_nr.u.sdcch4)) {
5680 ss_nr := chan_nr.u.sdcch4.sub_chan;
5681 } else if (ischosen(chan_nr.u.sdcch8)) {
5682 ss_nr := chan_nr.u.sdcch8.sub_chan;
5683 } else {
5684 setverdict(fail, "Invalid ChanNr ", chan_nr);
Daniel Willmannafce8662018-07-06 23:11:32 +02005685 mtc.stop;
Harald Welte261af4b2018-02-12 21:20:39 +01005686 }
5687
5688 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5689 " timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005690 f_vty_transceive(pt, cmd & suffix);
Harald Welte261af4b2018-02-12 21:20:39 +01005691}
5692
Neels Hofmeyr91401012019-07-11 00:42:35 +02005693/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
5694 * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor
5695 * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
5696 * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
5697 * pair, not really to a specific BTS number. */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005698private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
5699 in RslChannelNr chan_nr, uint8_t new_bts_nr)
5700{
5701 f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
Harald Welte261af4b2018-02-12 21:20:39 +01005702}
5703
5704/* intra-BSC hand-over between BTS0 and BTS1 */
5705private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02005706 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5707 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte261af4b2018-02-12 21:20:39 +01005708
5709 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5710 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5711
Harald Weltea0630032018-03-20 21:09:55 +01005712 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005713 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Harald Welte261af4b2018-02-12 21:20:39 +01005714
5715 var HandoverState hs := {
5716 rr_ho_cmpl_seen := false,
5717 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005718 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005719 expect_target_tsc := c_BtsParams[1].tsc
Harald Welte261af4b2018-02-12 21:20:39 +01005720 };
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005721 /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005722 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
Harald Welte261af4b2018-02-12 21:20:39 +01005723 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5724 f_rslem_suspend(RSL1_PROC);
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005725
5726 /* From the MGW perspective, a handover is is characterized by
5727 * performing one MDCX operation with the MGW. So we expect to see
5728 * one more MDCX during handover. */
5729 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5730
Harald Welte261af4b2018-02-12 21:20:39 +01005731 alt {
5732 [] as_handover(hs);
Harald Welte261af4b2018-02-12 21:20:39 +01005733 }
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005734
Philipp Maier4dae0652018-11-12 12:03:26 +01005735 /* Since this is an internal handover we expect the BSC to inform the
5736 * MSC about the event */
5737 BSSAP.receive(tr_BSSMAP_HandoverPerformed);
5738
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005739 /* Check the amount of MGCP transactions is still consistant with the
5740 * test expectation */
5741 f_check_mgcp_expectations()
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005742
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005743 var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
5744
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005745 /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
5746 * 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 +02005747 f_verify_encr_info(chan_act);
5748
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005749 f_chan_act_verify_tsc(chan_act, c_BtsParams[1].tsc);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005750
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005751 f_perform_clear(RSL1, RSL1_PROC);
5752
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005753 f_sleep(0.5);
Harald Welte261af4b2018-02-12 21:20:39 +01005754}
5755
5756testcase TC_ho_int() runs on test_CT {
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005757 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte261af4b2018-02-12 21:20:39 +01005758 var MSC_ConnHdlr vc_conn;
5759 f_init(2, true);
5760 f_sleep(1.0);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005761
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005762 pars.expect_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005763
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005764 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005765
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005766 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
Harald Welte261af4b2018-02-12 21:20:39 +01005767 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005768
5769 /* from f_establish_fully() */
5770 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5771 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5772 /* from handover */
5773 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5774 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5775 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5776 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005777 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5778 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005779 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005780 f_shutdown_helper(ho := true);
Harald Welte261af4b2018-02-12 21:20:39 +01005781}
Harald Weltee9e02e42018-01-31 23:36:25 +01005782
Oliver Smith7eabd312021-07-12 14:18:56 +02005783function 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 +02005784 var MSC_ConnHdlr vc_conn;
5785 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5786 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
5787
5788 f_init(2, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02005789 f_vty_encryption_a5(enc_a5);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005790 f_sleep(1.0);
5791
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005792 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005793
5794 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
5795 vc_conn.done;
5796
5797 /* from f_establish_fully() */
5798 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5799 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5800 /* from handover */
5801 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5802 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5803 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5804 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005805 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5806 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005807 f_ctrs_bsc_and_bts_verify();
Oliver Smith7eabd312021-07-12 14:18:56 +02005808 f_vty_encryption_a5_reset();
Oliver Smith39f53072022-10-27 14:44:04 +02005809 f_shutdown_helper(ho := true);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005810}
5811
5812testcase TC_ho_int_a5_0() runs on test_CT {
5813 f_tc_ho_int_a5('01'O);
5814}
5815
5816testcase TC_ho_int_a5_1() runs on test_CT {
5817 f_tc_ho_int_a5('02'O);
5818}
5819
5820testcase TC_ho_int_a5_3() runs on test_CT {
5821 f_tc_ho_int_a5('08'O);
5822}
5823
5824testcase TC_ho_int_a5_4() runs on test_CT {
Oliver Smith7eabd312021-07-12 14:18:56 +02005825 f_tc_ho_int_a5('10'O, "0 1 3 4");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005826}
5827
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005828/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
5829private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
5830 g_pars := f_gen_test_hdlr_pars();
5831 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5832 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005833
5834 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5835 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5836
5837 f_establish_fully(ass_cmd, exp_compl);
5838 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
5839
5840 var HandoverState hs := {
5841 rr_ho_cmpl_seen := false,
5842 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005843 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005844 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005845 };
5846 /* issue hand-over command on VTY */
5847 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
5848 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5849 f_rslem_suspend(RSL1_PROC);
5850
5851 /* From the MGW perspective, a handover is is characterized by
5852 * performing one MDCX operation with the MGW. So we expect to see
5853 * one more MDCX during handover. */
5854 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5855
5856 var RSL_Message rsl;
5857 var PDU_ML3_NW_MS l3;
5858 var RslChannelNr new_chan_nr;
5859 var GsmArfcn arfcn;
5860 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
5861 l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
5862 if (not ischosen(l3.msgs.rrm.handoverCommand)) {
5863 setverdict(fail, "Expected handoverCommand");
5864 mtc.stop;
5865 }
5866 }
5867 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
5868 new_chan_nr, arfcn);
5869
5870 f_rslem_register(0, new_chan_nr, RSL1_PROC);
5871
5872 /* resume processing of RSL DChan messages, which was temporarily suspended
5873 * before performing a hand-over */
5874 f_rslem_resume(RSL1_PROC);
5875 RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
5876
5877 f_sleep(1.0);
5878
5879 /* Handover fails because no HANDO DET appears on the new lchan,
5880 * and the old lchan reports a Radio Link Failure. */
5881 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
5882
5883 var PDU_BSSAP rx_clear_request;
5884 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5885 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5886 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5887
5888 var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
5889
5890 var MgcpCommand mgcp;
5891 interleave {
5892 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
5893 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005894 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005895 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005896 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005897 }
5898 [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005899 [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005900 RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005901 f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005902 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005903 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5904 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5905 }
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005906 }
5907
5908 f_sleep(0.5);
5909 setverdict(pass);
5910}
5911testcase TC_ho_int_radio_link_failure() runs on test_CT {
5912 var MSC_ConnHdlr vc_conn;
5913 f_init(2, true);
5914 f_sleep(1.0);
5915
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005916 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005917
5918 vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
5919 vc_conn.done;
5920
5921 /* from f_establish_fully() */
5922 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5923 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5924 /* from handover */
5925 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5926 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
5927 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5928 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005929 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5930 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005931 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005932 f_shutdown_helper(ho := true);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005933}
5934
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005935/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005936private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005937 var MgcpCommand mgcp;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005938 var template MgcpResponse mgcp_resp;
5939 var MGCP_RecvFrom mrf;
5940 var template MgcpMessage msg_resp;
5941 var template MgcpMessage msg_dlcx := {
5942 command := tr_DLCX()
5943 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005944
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005945 if (g_pars.aoip) {
5946 MGCP.receive(tr_DLCX()) -> value mgcp {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005947 log("Got first DLCX: ", mgcp);
5948 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005949 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005950
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005951 MGCP.receive(tr_DLCX()) -> value mgcp {
5952 log("Got second DLCX: ", mgcp);
5953 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
5954 };
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005955 } else {
5956 /* For SCCPLite, BSC doesn't handle the MSC-side */
5957 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
5958 log("Got first DLCX: ", mrf.msg.command);
5959 msg_resp := {
5960 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
5961 }
5962 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
5963 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005964 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005965}
5966
Oliver Smithc9a5f532022-10-21 11:32:23 +02005967private function f_ho_out_of_this_bsc(template (omit) BSSMAP_oldToNewBSSIEs exp_oldToNewBSSIEs := omit,
5968 boolean skip_meas_rep := false) runs on MSC_ConnHdlr {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005969
Oliver Smithc9a5f532022-10-21 11:32:23 +02005970 if (not skip_meas_rep) {
5971 var NcellReports neighbor_rep := {
5972 { rxlev := 20, bcch_freq := 0, bsic := 11 }
5973 };
5974 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
5975 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
5976 l3_mr, 0));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005977
Oliver Smithc9a5f532022-10-21 11:32:23 +02005978 BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
5979 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005980
5981 f_sleep(0.5);
5982 /* The MSC negotiates Handover Request and Handover Request Ack with
5983 * the other BSS and comes back with a BSSMAP Handover Command
5984 * containing an RR Handover Command coming from the target BSS... */
5985
5986 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5987 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
5988 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5989 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
5990 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
5991
5992 /* expect the Handover Command to go out on RR */
5993 var RSL_Message rsl_ho_cmd
5994 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
5995 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
5996 var RSL_IE_Body rsl_ho_cmd_l3;
5997 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
5998 log("RSL message contains no L3 Info IE, expected RR Handover Command");
5999 setverdict(fail);
6000 } else {
6001 log("Found L3 Info: ", rsl_ho_cmd_l3);
6002 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6003 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6004 setverdict(fail);
6005 } else {
6006 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6007 setverdict(pass);
6008 }
6009 }
6010
6011 /* When the other BSS has reported a completed handover, this side is
6012 * torn down. */
6013
6014 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_HANDOVER_SUCCESSFUL;
6015 var BssmapCause cause := enum2int(cause_val);
6016 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6017
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006018 f_expect_dlcx_conns();
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006019
6020 interleave {
6021 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
6022 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
6023 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006024 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
6025 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
6026 }
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006027 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006028 setverdict(pass);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006029}
6030
6031private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
6032 g_pars := f_gen_test_hdlr_pars();
6033 var PDU_BSSAP ass_req := f_gen_ass_req();
6034 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6035 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6036 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6037 f_establish_fully(ass_req, exp_compl);
6038
6039 f_ho_out_of_this_bsc();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006040}
6041testcase TC_ho_out_of_this_bsc() runs on test_CT {
6042 var MSC_ConnHdlr vc_conn;
6043
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006044 f_init_vty();
6045 f_bts_0_cfg(BSCVTY,
6046 {"neighbor-list mode automatic",
6047 "handover 1",
6048 "handover algorithm 2",
6049 "handover2 window rxlev averaging 1",
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006050 "no neighbors",
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006051 "neighbor lac 99 arfcn 123 bsic any"});
6052 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6053
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006054 f_init(1, true);
6055 f_sleep(1.0);
6056
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006057 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006058
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006059 vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
6060 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006061
6062 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6063 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6064 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6065 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6066 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6067 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
6068 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006069 f_shutdown_helper(ho := true);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006070}
6071
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006072private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6073 template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
Vadim Yanitskiy2ef6a2f2020-10-08 23:17:32 +07006074 template (present) OCT1 dlci := ?,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006075 octetstring l3 := '0123456789'O)
6076runs on MSC_ConnHdlr {
Neels Hofmeyr43654812020-09-25 01:35:35 +02006077 /* The old lchan and conn should still be active. See that arbitrary L3
6078 * is still going through. */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006079 rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
Neels Hofmeyr43654812020-09-25 01:35:35 +02006080 var template PDU_BSSAP exp_data := {
6081 discriminator := '1'B,
6082 spare := '0000000'B,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006083 dlci := dlci,
6084 lengthIndicator := lengthof(l3),
Neels Hofmeyr43654812020-09-25 01:35:35 +02006085 pdu := {
6086 dtap := l3
6087 }
6088 };
6089 BSSAP.receive(exp_data);
6090 setverdict(pass);
6091}
6092
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006093private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6094 template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006095 template (value) OCT1 dlci := '00'O,
6096 octetstring l3 := '0123456789'O)
6097runs on MSC_ConnHdlr {
6098 BSSAP.send(PDU_BSSAP:{
6099 discriminator := '1'B,
6100 spare := '0000000'B,
6101 dlci := dlci,
6102 lengthIndicator := lengthof(l3),
6103 pdu := {
6104 dtap := l3
6105 }
6106 });
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006107 rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006108 setverdict(pass);
6109}
6110
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006111/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
6112 * simply never sends a BSSMAP Handover Command. */
6113private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006114 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006115
6116 var PDU_BSSAP ass_req := f_gen_ass_req();
6117 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6118 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6119 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6120 f_establish_fully(ass_req, exp_compl);
6121
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006122 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006123 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6124
6125 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6126
6127 /* osmo-bsc should time out 10 seconds after the handover started.
6128 * Let's give it a bit extra. */
6129 f_sleep(15.0);
6130
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006131 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006132 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006133 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006134}
6135testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
6136 var MSC_ConnHdlr vc_conn;
6137
6138 f_init(1, true);
6139 f_sleep(1.0);
6140
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006141 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006142
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006143 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
6144 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006145
6146 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6147 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6148 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6149 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6150 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6151 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6152 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006153 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006154}
6155
6156/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
6157 * RR Handover Failure. */
6158private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006159 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006160
6161 var PDU_BSSAP ass_req := f_gen_ass_req();
6162 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6163 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6164 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6165 f_establish_fully(ass_req, exp_compl);
6166
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006167 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006168 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6169
6170 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6171
6172 f_sleep(0.5);
6173 /* The MSC negotiates Handover Request and Handover Request Ack with
6174 * the other BSS and comes back with a BSSMAP Handover Command
6175 * containing an RR Handover Command coming from the target BSS... */
6176
6177 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6178 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6179 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6180 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6181 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6182
6183 /* expect the Handover Command to go out on RR */
6184 var RSL_Message rsl_ho_cmd
6185 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6186 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6187 var RSL_IE_Body rsl_ho_cmd_l3;
6188 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6189 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6190 setverdict(fail);
6191 } else {
6192 log("Found L3 Info: ", rsl_ho_cmd_l3);
6193 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6194 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6195 setverdict(fail);
6196 } else {
6197 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6198 setverdict(pass);
6199 }
6200 }
6201
6202 f_sleep(0.2);
6203 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
6204
6205 /* Should tell the MSC about the failure */
6206 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6207
6208 f_sleep(1.0);
6209
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006210 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006211 f_sleep(1.0);
6212
6213 setverdict(pass);
6214 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006215 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006216}
6217testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
6218 var MSC_ConnHdlr vc_conn;
6219
6220 f_init(1, true);
6221 f_sleep(1.0);
6222
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006223 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006224
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006225 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
6226 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006227
6228 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6229 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6230 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6231 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6232 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6233 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
6234 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006235 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006236}
6237
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006238/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
6239 * (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 +02006240 * and the lchan is released. */
6241private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006242 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006243
6244 var PDU_BSSAP ass_req := f_gen_ass_req();
6245 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6246 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6247 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6248 f_establish_fully(ass_req, exp_compl);
6249
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006250 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006251 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6252
6253 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6254
6255 f_sleep(0.5);
6256 /* The MSC negotiates Handover Request and Handover Request Ack with
6257 * the other BSS and comes back with a BSSMAP Handover Command
6258 * containing an RR Handover Command coming from the target BSS... */
6259
6260 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6261 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6262 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6263 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6264 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6265
6266 /* expect the Handover Command to go out on RR */
6267 var RSL_Message rsl_ho_cmd
6268 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6269 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6270 var RSL_IE_Body rsl_ho_cmd_l3;
6271 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6272 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6273 setverdict(fail);
6274 } else {
6275 log("Found L3 Info: ", rsl_ho_cmd_l3);
6276 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6277 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6278 setverdict(fail);
6279 } else {
6280 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6281 setverdict(pass);
6282 }
6283 }
6284
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006285 /* We get neither success nor failure report from the remote BSS. Eventually T8 times out and we run into 3GPP
6286 * TS 48.008 3.1.5.3.3 "Abnormal Conditions": Clear Request should go to the MSC, and RR should be released
6287 * after Clear Command */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006288
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006289 var PDU_BSSAP rx_clear_request;
Neels Hofmeyre1797aa2019-07-09 19:34:04 +02006290 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
6291 log("Got BSSMAP Clear Request");
6292 /* Instruct BSC to clear channel */
6293 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6294 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6295
6296 var MgcpCommand mgcp;
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006297 interleave {
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01006298 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
6299 log("Got Deact SACCH");
6300 }
Harald Welte924b6ea2019-02-04 01:05:34 +01006301 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
Neels Hofmeyr211169d2018-11-07 00:37:29 +01006302 log("Got RR Release");
6303 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02006304 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006305 log("Got RF Chan Rel");
6306 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02006307 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006308 }
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006309 }
6310
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006311 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006312 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006313 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006314
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006315 setverdict(pass);
6316 f_sleep(1.0);
6317}
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006318testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006319 var MSC_ConnHdlr vc_conn;
6320
6321 f_init(1, true);
6322 f_sleep(1.0);
6323
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006324 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006325
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006326 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006327 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006328
6329 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6330 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6331 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6332 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6333 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6334 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6335 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006336 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006337}
6338
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006339private 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 +01006340 var PDU_BSSAP rx_bssap;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006341 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6342 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6343 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6344 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6345 * before we get started. */
6346 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6347 f_rslem_register(0, new_chan_nr);
6348 g_chan_nr := new_chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06006349 var uint3_t expect_target_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006350 f_sleep(1.0);
6351
6352 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6353 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006354 var default as_media := activate(as_Media());
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006355
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01006356 var PDU_BSSAP ho_req := f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
6357 cell_id_source := g_pars.cell_id_source,
6358 oldToNewBSSIEs := oldToNewBSSIEs,
6359 enc := g_pars.encr);
6360 if (g_pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr) {
6361 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, ho_req));
6362 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6363 } else {
6364 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, omit));
6365 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6366 BSSAP.send(ho_req);
6367 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006368
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006369 alt {
6370 [] BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap {
6371 if (g_pars.expect_ho_fail) {
6372 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6373 "Expected Handover Request to fail, but got Handover Request Ack")
6374 }
6375 }
6376 [] BSSAP.receive(tr_BSSMAP_HandoverFailure) -> value rx_bssap {
6377 if (not g_pars.expect_ho_fail) {
6378 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6379 "Expected Handover Request to succeed, but got Handover Failure")
6380 }
6381 // TODO: evaluate correct cause value. But osmo-bsc doesn't seem to send meaningful causes yet!
6382 // For now just accept any cause.
6383 BSSAP.receive(tr_BSSMAP_ClearRequest);
6384 setverdict(pass);
6385 return;
6386 }
6387 }
6388
Oliver Smith7a8594a2023-02-13 14:30:49 +01006389 if (g_pars.expect_ho_fail_lchan_est) {
6390 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6391 setverdict(pass);
Oliver Smitha1cbec52023-02-21 12:44:12 +01006392
6393 /* When we let MGCP MDCX run into a timeout, it's still in the
6394 * queue and additionally after BSSAP HandoverFailure, two DLCX
Oliver Smith30eb8822023-03-06 12:31:53 +01006395 * get sent (for AoIP, for SCCPlite one DLCX). */
Oliver Smitha1cbec52023-02-21 12:44:12 +01006396 if (g_pars.ignore_mgw_mdcx) {
Oliver Smith30eb8822023-03-06 12:31:53 +01006397 if (g_pars.aoip) {
6398 MGCP.receive(tr_MDCX);
6399 MGCP.receive(tr_DLCX);
6400 MGCP.receive(tr_DLCX);
6401 } else {
6402 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_MDCX}));
6403 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_DLCX}));
6404 }
Oliver Smitha1cbec52023-02-21 12:44:12 +01006405 }
Oliver Smith7a8594a2023-02-13 14:30:49 +01006406 return;
6407 }
6408
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006409 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6410
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006411 /* we're sure that the channel activation is done now, verify the parameters in it */
6412 var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
6413 f_verify_encr_info(chan_act);
6414 f_chan_act_verify_tsc(chan_act, expect_target_tsc);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006415
Neels Hofmeyr46e16e52022-02-23 17:04:00 +01006416 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.codecList)) {
6417 if (not g_pars.aoip) {
6418 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6419 "handoverRequestAck: Expected no Speech Codec List (BSS Supported), because this is not AoIP");
6420 }
6421 /* TODO: check actual codecs? */
6422 } else {
6423 if (g_pars.aoip) {
6424 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6425 "handoverRequestAck: Expected Speech Codec List (BSS Supported), but none found");
6426 }
6427 }
6428
6429 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.speechCodec)) {
6430 if (not g_pars.aoip) {
6431 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6432 "handoverRequestAck: Expected no Speech Codec (Chosen), because this is not AoIP");
6433 }
6434 /* TODO: check actual codec? */
6435 } else {
6436 if (g_pars.aoip) {
6437 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6438 "handoverRequestAck: Expected Speech Codec (Chosen), but none found");
6439 }
6440 }
6441
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006442 var octetstring ho_command_str;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006443 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6444 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6445 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6446 log("L3 Info in HO Request Ack is ", ho_command);
6447
6448 var GsmArfcn arfcn;
6449 var RslChannelNr actual_new_chan_nr;
6450 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6451 actual_new_chan_nr, arfcn);
6452
6453 if (actual_new_chan_nr != new_chan_nr) {
6454 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6455 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6456 setverdict(fail);
6457 return;
6458 }
6459 log("Handover Command chan_nr is", actual_new_chan_nr);
6460
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006461 var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
6462 if (not match(got_tsc, expect_target_tsc)) {
6463 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6464 expect_target_tsc, " got ", got_tsc);
6465 mtc.stop;
6466 } else {
6467 log("handoverCommand: verified TSC = ", got_tsc);
6468 }
6469
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006470 /* Check the Cipher Mode Setting IE (shall be present during inter-RAT handover) */
6471 if (ispresent(ho_command.msgs.rrm.handoverCommand.cipherModeSetting)) {
6472 var CipherModeSetting_TV cms := ho_command.msgs.rrm.handoverCommand.cipherModeSetting;
6473 var template (present) CipherModeSetting_TV tr_cms := {
6474 sC := '0'B, /* no ciphering by default */
6475 algorithmIdentifier := '000'B,
6476 elementIdentifier := ?
6477 };
6478 if (ispresent(g_pars.encr) and g_pars.encr.enc_alg_expect != '01'O) { /* A5/N */
6479 tr_cms.algorithmIdentifier := f_cipher_mode_bssmap_to_rr(g_pars.encr.enc_alg_expect);
6480 tr_cms.sC := '1'B;
6481 }
6482 if (not match(cms, tr_cms)) {
6483 setverdict(fail, "RR Handover Command: unexpected Cipher Mode Setting IE: ",
6484 cms, ", expected: ", tr_cms);
6485 }
6486 } else {
6487 setverdict(fail, "RR Handover Command: Cipher Mode Setting IE is not present");
6488 }
6489
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006490 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6491 * tells the MS to handover to the new lchan. Here comes the new MS on
6492 * the new lchan with a Handover RACH: */
6493
6494 /* send handover detect */
6495
6496 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6497
6498 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6499
6500 /* send handover complete over the new channel */
6501
6502 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_HandoverComplete('00'O));
6503 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
6504 enc_PDU_ML3_MS_NW(l3_tx)));
6505
6506 BSSAP.receive(tr_BSSMAP_HandoverComplete);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006507 deactivate(as_media);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006508 setverdict(pass);
6509}
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006510
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006511private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006512 var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006513 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
6514 if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
6515 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006516 }
6517 if (g_pars.exp_fast_return) {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006518 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006519 } else {
6520 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006521 }
6522 f_ho_into_this_bsc(id, oldToNewBSSIEs);
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006523 if (g_pars.expect_ho_fail) {
6524 f_perform_clear_no_lchan();
Oliver Smith7a8594a2023-02-13 14:30:49 +01006525 } else if (g_pars.expect_ho_fail_lchan_est) {
6526 BSSAP.receive(tr_BSSMAP_ClearRequest);
6527 f_perform_clear_no_lchan();
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006528 } else {
6529 f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
6530 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006531 setverdict(pass);
6532}
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006533function 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 +01006534 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006535
6536 f_init(1, true);
6537 f_sleep(1.0);
6538
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006539 f_vty_encryption_a5(vty_a5_cfg);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006540 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006541
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006542 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6543 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006544
6545 vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
6546 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006547
6548 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006549 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006550 if (pars.expect_ho_fail) {
6551 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6552 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:failed");
Oliver Smith7a8594a2023-02-13 14:30:49 +01006553 } else if (pars.expect_ho_fail_lchan_est) {
6554 f_ctrs_bsc_and_bts_add(0, "handover:error");
6555 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006556 } else {
6557 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6558 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
6559 }
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006560 f_ctrs_bsc_and_bts_verify();
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006561
6562 f_vty_encryption_a5_reset();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006563}
6564
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006565testcase TC_ho_into_this_bsc() runs on test_CT {
6566 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6567 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006568 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006569}
6570
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006571function f_tc_ho_into_this_bsc_a5(TestHdlrEncrParams encr, charstring vty_a5_cfg := VTY_A5_DEFAULT,
6572 boolean expect_fail := false) runs on test_CT {
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006573 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006574 pars.encr := encr;
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006575 pars.expect_ho_fail := expect_fail;
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006576 f_tc_ho_into_this_bsc_main(pars, vty_a5_cfg);
Oliver Smith39f53072022-10-27 14:44:04 +02006577 f_shutdown_helper(ho := true);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006578}
6579
6580testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006581 f_tc_ho_into_this_bsc_a5(f_encr_params('01'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006582}
6583
6584testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006585 f_tc_ho_into_this_bsc_a5(f_encr_params('02'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006586}
6587
6588testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006589 f_tc_ho_into_this_bsc_a5(f_encr_params('08'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006590}
6591
6592testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006593 f_tc_ho_into_this_bsc_a5(f_encr_params('10'O, kc128 := true), "3 4");
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006594}
6595
Neels Hofmeyr1951be22022-02-16 16:21:07 +01006596/* Report: in inter-BSC incoming handover, when the MSC omits the Chosen Encryption Algorithm IE in the Handover Request
6597 * message, then osmo-bsc starts an unencrypted lchan even if A5/0 is not permitted.
6598 *
6599 * This test verifies that the Encryption Information is present in the Channel Activation when the Chosen Enc Alg is
6600 * omitted.
6601 *
6602 * Related: SYS#5839
6603 */
6604testcase TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() runs on test_CT {
6605 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O, alg_chosen := omit));
6606}
6607
6608testcase TC_ho_into_this_bsc_a5_1_3() runs on test_CT {
6609 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O));
6610}
6611
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006612/* Send a permitted algo mask that does not intersect with osmo-bsc.cfg */
6613testcase TC_ho_into_this_bsc_a5_mismatch() runs on test_CT {
6614 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '18'O, alg_expect := '10'O), "0 1",
6615 expect_fail := true); // 0x18 = A5/3 and A5/4
6616}
6617
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006618testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
6619 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6620 pars.host_aoip_tla := "::6";
6621 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006622 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006623}
6624
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006625/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006626 to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006627 channel is later released (RR CHannel Release), should trigger inclusion of
6628 IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
6629 neighbors. */
6630testcase TC_srvcc_eutran_to_geran() runs on test_CT {
6631 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6632 pars.last_used_eutran_plmn := '323454'O;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006633 pars.exp_fast_return := true;
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006634 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006635
6636 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6637 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6638 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006639 f_shutdown_helper(ho := true);
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006640}
6641
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006642/* Same as TC_srvcc_eutran_to_geran, but enables ciphering on the target channel. */
6643testcase TC_srvcc_eutran_to_geran_a5_3() runs on test_CT {
6644 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6645 pars.encr := f_encr_params('08'O); /* only A5/3 */
6646 pars.last_used_eutran_plmn := '323454'O;
6647 pars.exp_fast_return := true;
6648 f_tc_ho_into_this_bsc_main(pars);
6649
6650 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6651 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6652 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006653 f_shutdown_helper(ho := true);
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006654}
6655
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006656/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
6657 on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
6658 list when the channel is released. */
6659testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
6660 f_init_vty();
6661 f_vty_allow_srvcc_fast_return(true, 0)
6662
6663 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6664 pars.last_used_eutran_plmn := '323454'O;
6665 pars.exp_fast_return := false;
6666 f_tc_ho_into_this_bsc_main(pars);
6667 f_vty_allow_srvcc_fast_return(false, 0);
6668 f_shutdown_helper();
6669}
6670
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01006671/* Same as TC_srvcc_eutran_to_geran, but using SAI as serving Cell Identifier. SYS#5838 */
6672testcase TC_srvcc_eutran_to_geran_src_sai() runs on test_CT {
6673 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6674 pars.last_used_eutran_plmn := '323454'O;
6675 pars.cell_id_source := valueof(ts_CellID_SAI('123456'O, 300, 444));
6676 f_tc_ho_into_this_bsc_main(pars);
6677
6678 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6679 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6680 f_ctrs_bsc_and_bts_verify();
6681 f_shutdown_helper();
6682}
6683
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006684private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
6685 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
6686 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
6687 f_ho_into_this_bsc(id, oldToNewBSSIEs);
6688 f_ho_out_of_this_bsc(oldToNewBSSIEs);
6689 setverdict(pass);
6690}
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006691
6692private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
6693 runs on test_CT {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006694 var MSC_ConnHdlr vc_conn;
6695 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6696
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006697 f_init_vty();
6698 f_bts_0_cfg(BSCVTY,
6699 {"neighbor-list mode automatic",
6700 "handover 1",
6701 "handover algorithm 2",
6702 "handover2 window rxlev averaging 1",
6703 "no neighbors",
6704 "neighbor lac 99 arfcn 123 bsic any"});
6705 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6706
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006707 f_init(1, true);
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006708 if (disable_fast_return) {
6709 f_vty_allow_srvcc_fast_return(true, 0);
6710 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006711 f_sleep(1.0);
6712
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006713 f_ctrs_bsc_and_bts_handover_init();
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006714
6715 pars.last_used_eutran_plmn := '323454'O;
6716 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6717 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
6718
6719 vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
6720 vc_conn.done;
6721
6722 f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
6723 f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
6724 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
6725 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
6726 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
6727 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006728
6729 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
6730 f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006731 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006732
6733 if (disable_fast_return) {
6734 f_vty_allow_srvcc_fast_return(false, 0);
6735 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006736 f_shutdown_helper();
6737}
6738
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006739/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
6740 BSS Information" IE with "Last Used E-UTRAN PLMN Id".
6741 Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
6742 IE with "Last Used E-UTRAN PLMN Id" from first step. */
6743testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
6744 f_tc_srvcc_eutran_to_geran_ho_out_main(false);
6745}
6746/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
6747 * independently of fast-reture allowed/forbidden in local BTS */
6748testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
6749 f_tc_srvcc_eutran_to_geran_ho_out_main(true);
6750}
6751
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006752private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
6753 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6754 f_rslem_register(0, new_chan_nr);
6755 g_chan_nr := new_chan_nr;
6756 f_sleep(1.0);
6757
6758 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6759 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6760 activate(as_Media());
6761
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006762 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006763 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006764 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006765
6766 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6767
6768 var PDU_BSSAP rx_bssap;
6769 var octetstring ho_command_str;
6770
6771 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6772
6773 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6774 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6775 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6776 log("L3 Info in HO Request Ack is ", ho_command);
6777
6778 var GsmArfcn arfcn;
6779 var RslChannelNr actual_new_chan_nr;
6780 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6781 actual_new_chan_nr, arfcn);
6782
6783 if (actual_new_chan_nr != new_chan_nr) {
6784 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6785 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6786 setverdict(fail);
6787 return;
6788 }
6789 log("Handover Command chan_nr is", actual_new_chan_nr);
6790
Neels Hofmeyr61ca08d2019-05-06 23:52:22 +02006791 /* For deterministic test results, give some time for the MGW endpoint to be configured */
6792 f_sleep(1.0);
6793
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006794 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6795 * tells the MS to handover to the new lchan. In this case, the MS
6796 * reports a Handover Failure to the old BSS, which forwards a BSSMAP
6797 * Handover Failure to the MSC. The procedure according to 3GPP TS
6798 * 48.008 3.1.5.3.2 "Handover Failure" is then that the MSC sends a
6799 * BSSMAP Clear Command: */
6800
6801 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6802 var BssmapCause cause := enum2int(cause_val);
6803 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6804
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006805 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006806 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006807 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006808
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006809 setverdict(pass);
6810 f_sleep(1.0);
6811
6812 setverdict(pass);
6813}
6814testcase TC_ho_in_fail_msc_clears() runs on test_CT {
6815 var MSC_ConnHdlr vc_conn;
6816 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6817
6818 f_init(1, true);
6819 f_sleep(1.0);
6820
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006821 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006822
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006823 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6824 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006825
6826 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
6827 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006828
6829 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6830 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6831 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6832 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6833 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006834 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006835}
6836
6837private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
6838 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6839 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6840 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6841 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6842 * before we get started. */
6843 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6844 f_rslem_register(0, new_chan_nr);
6845 g_chan_nr := new_chan_nr;
6846 f_sleep(1.0);
6847
6848 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6849 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6850 activate(as_Media());
6851
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006852 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006853 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006854 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006855
6856 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6857
6858 var PDU_BSSAP rx_bssap;
6859 var octetstring ho_command_str;
6860
6861 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6862
6863 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6864 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6865 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6866 log("L3 Info in HO Request Ack is ", ho_command);
6867
6868 var GsmArfcn arfcn;
6869 var RslChannelNr actual_new_chan_nr;
6870 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6871 actual_new_chan_nr, arfcn);
6872
6873 if (actual_new_chan_nr != new_chan_nr) {
6874 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6875 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6876 setverdict(fail);
6877 return;
6878 }
6879 log("Handover Command chan_nr is", actual_new_chan_nr);
6880
6881 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6882 * tells the MS to handover to the new lchan. Here comes the new MS on
6883 * the new lchan with a Handover RACH: */
6884
6885 /* send handover detect */
6886
6887 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6888
6889 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6890
6891 /* The MSC chooses to clear the connection now, maybe we got the
6892 * Handover RACH on the new cell but the MS still signaled Handover
6893 * Failure to the old BSS? */
6894
6895 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6896 var BssmapCause cause := enum2int(cause_val);
6897 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6898
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006899 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006900 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006901 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006902
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006903 f_sleep(1.0);
6904}
6905testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
6906 var MSC_ConnHdlr vc_conn;
6907 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6908
6909 f_init(1, true);
6910 f_sleep(1.0);
6911
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006912 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006913
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006914 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6915 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006916
6917 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
6918 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006919
6920 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6921 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6922 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6923 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6924 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006925 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006926}
6927
6928/* The new BSS's lchan times out before the MSC decides that handover failed. */
6929private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
6930 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6931 f_rslem_register(0, new_chan_nr);
6932 g_chan_nr := new_chan_nr;
6933 f_sleep(1.0);
6934
6935 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6936 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01006937 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006938
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006939 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006940 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006941 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006942
6943 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6944
6945 var PDU_BSSAP rx_bssap;
6946 var octetstring ho_command_str;
6947
6948 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6949
6950 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6951 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6952 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6953 log("L3 Info in HO Request Ack is ", ho_command);
6954
6955 var GsmArfcn arfcn;
6956 var RslChannelNr actual_new_chan_nr;
6957 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6958 actual_new_chan_nr, arfcn);
6959
6960 if (actual_new_chan_nr != new_chan_nr) {
6961 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6962 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6963 setverdict(fail);
6964 return;
6965 }
6966 log("Handover Command chan_nr is", actual_new_chan_nr);
6967
6968 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6969 * tells the MS to handover to the new lchan. But the MS never shows up
6970 * on the new lchan. */
6971
6972 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6973
6974 /* Did osmo-bsc also send a Clear Request? */
6975 timer T := 0.5;
6976 T.start;
6977 alt {
6978 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
6979 [] T.timeout { }
6980 }
6981
6982 /* MSC plays along with a Clear Command (no matter whether osmo-bsc
6983 * asked for it, this is a Handover Failure after all). */
6984
6985 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6986 var BssmapCause cause := enum2int(cause_val);
6987 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6988
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006989 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006990 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006991 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006992
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006993 f_sleep(1.0);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006994}
6995testcase TC_ho_in_fail_no_detect() runs on test_CT {
6996 var MSC_ConnHdlr vc_conn;
6997 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6998
Oliver Smithd49f46d2023-03-08 12:23:13 +01006999 pars.fail_on_dlcx := false;
7000
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007001 f_init(1, true);
7002 f_sleep(1.0);
7003
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007004 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007005
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007006 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7007 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007008
7009 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect), pars);
7010 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007011
7012 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7013 f_ctrs_bsc_and_bts_add(0, "handover:error");
7014 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7015 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7016 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007017 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007018}
7019
7020/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
7021private function f_tc_ho_in_fail_no_detect2(charstring id) runs on MSC_ConnHdlr {
7022 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
7023 f_rslem_register(0, new_chan_nr);
7024 g_chan_nr := new_chan_nr;
7025 f_sleep(1.0);
7026
7027 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
7028 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01007029 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007030
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007031 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007032 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02007033 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007034
7035 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
7036
7037 var PDU_BSSAP rx_bssap;
7038 var octetstring ho_command_str;
7039
7040 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
7041
7042 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
7043 log("Received L3 Info in HO Request Ack: ", ho_command_str);
7044 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
7045 log("L3 Info in HO Request Ack is ", ho_command);
7046
7047 var GsmArfcn arfcn;
7048 var RslChannelNr actual_new_chan_nr;
7049 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
7050 actual_new_chan_nr, arfcn);
7051
7052 if (actual_new_chan_nr != new_chan_nr) {
7053 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
7054 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
7055 setverdict(fail);
7056 return;
7057 }
7058 log("Handover Command chan_nr is", actual_new_chan_nr);
7059
7060 /* Now the MSC forwards the RR Handover Command to the other BSC, which
7061 * tells the MS to handover to the new lchan. But the MS never shows up
7062 * on the new lchan. */
7063
7064 BSSAP.receive(tr_BSSMAP_HandoverFailure);
7065
7066 /* MSC plays dumb and sends no Clear Command */
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007067 var PDU_BSSAP rx_clear_request;
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02007068
7069 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request {
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007070 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
7071 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7072 };
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007073 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007074 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007075 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007076
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007077 f_sleep(1.0);
7078}
7079testcase TC_ho_in_fail_no_detect2() runs on test_CT {
7080 var MSC_ConnHdlr vc_conn;
7081 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7082
Oliver Smith735b47c2023-02-15 16:03:54 +01007083 pars.fail_on_dlcx := false;
7084
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007085 f_init(1, true);
7086 f_sleep(1.0);
7087
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007088 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007089
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007090 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7091 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007092
7093 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
7094 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007095
7096 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7097 f_ctrs_bsc_and_bts_add(0, "handover:error");
7098 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7099 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7100 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007101 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007102}
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01007103
Oliver Smith7a8594a2023-02-13 14:30:49 +01007104testcase TC_ho_in_fail_mgw_mdcx_timeout() runs on test_CT {
7105 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7106
7107 pars.ignore_mgw_mdcx := true;
7108 pars.expect_ho_fail_lchan_est := true;
7109
7110 f_tc_ho_into_this_bsc_main(pars);
7111 f_shutdown_helper(ho := true);
7112}
7113
Oliver Smith4eed06f2023-02-15 15:43:19 +01007114testcase TC_ho_in_fail_ipa_crcx_timeout() runs on test_CT {
7115 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7116
7117 pars.ignore_ipa_media := true;
7118 pars.expect_ho_fail_lchan_est := true;
7119 pars.fail_on_dlcx := false;
7120
7121 f_tc_ho_into_this_bsc_main(pars);
7122 f_shutdown_helper(ho := true);
7123}
7124
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007125/* An incoming inter-BSC HO can either issue the Handover Request message attached to the initial SCCP N-Connect (as in
7126 * the other tests we have so far), or the first CR can be "empty" with the BSSAP request following later. Test the
7127 * empty N-Connect case. */
7128testcase TC_ho_into_this_bsc_sccp_cr_without_bssap() runs on test_CT {
7129 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7130 pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr := false;
7131 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02007132 f_shutdown_helper(ho := true);
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007133}
7134
Neels Hofmeyr91401012019-07-11 00:42:35 +02007135type record of charstring Commands;
7136
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007137private function f_bts_0_cfg(TELNETasp_PT pt, Commands cmds := {})
Neels Hofmeyr91401012019-07-11 00:42:35 +02007138{
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007139 f_vty_enter_cfg_bts(pt, 0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007140 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007141 f_vty_transceive(pt, cmds[i]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007142 }
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007143 f_vty_transceive(pt, "end");
Neels Hofmeyr91401012019-07-11 00:42:35 +02007144}
7145
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01007146private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
7147{
7148 f_vty_enter_cfg_cs7_inst(pt, 0);
7149 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
7150 f_vty_transceive(pt, cmds[i]);
7151 }
7152 f_vty_transceive(pt, "end");
7153}
7154
Neels Hofmeyr91401012019-07-11 00:42:35 +02007155private function f_probe_for_handover(charstring log_label,
7156 charstring log_descr,
7157 charstring handover_vty_cmd,
7158 boolean expect_handover,
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007159 boolean is_inter_bsc_handover := false,
7160 template uint3_t expect_target_tsc := ?)
Neels Hofmeyr91401012019-07-11 00:42:35 +02007161runs on MSC_ConnHdlr
7162{
Neels Hofmeyrb3fc8982020-05-11 00:16:42 +02007163 /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
7164 * lchans to be established on bts 1 or bts 2. */
7165 f_rslem_suspend(RSL1_PROC);
7166 f_rslem_suspend(RSL2_PROC);
7167
Neels Hofmeyr91401012019-07-11 00:42:35 +02007168 var RSL_Message rsl;
7169
7170 var charstring log_msg := " (expecting handover)"
7171 if (not expect_handover) {
7172 log_msg := " (expecting NO handover)";
7173 }
7174 log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg);
7175 f_vty_transceive(BSCVTY, handover_vty_cmd);
7176
Neels Hofmeyr91401012019-07-11 00:42:35 +02007177 timer T := 2.0;
7178 T.start;
7179
7180 alt {
7181 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
7182 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
7183 log("Rx L3 from net: ", l3);
7184 if (ischosen(l3.msgs.rrm.handoverCommand)) {
7185 var RslChannelNr new_chan_nr;
7186 var GsmArfcn arfcn;
7187 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
7188 new_chan_nr, arfcn);
7189 log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
7190 log(l3.msgs.rrm.handoverCommand);
7191
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007192 /* Verify correct TSC in handoverCommand */
7193 var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
7194 if (not match(got_tsc, expect_target_tsc)) {
7195 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
7196 expect_target_tsc, " got ", got_tsc);
7197 mtc.stop;
7198 } else {
7199 log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
7200 expect_target_tsc, ")");
7201 }
7202
Neels Hofmeyr91401012019-07-11 00:42:35 +02007203 /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
7204 * matter on which BTS it really is, we're not going to follow through an entire handover
7205 * anyway. */
7206 f_rslem_register(0, new_chan_nr, RSL1_PROC);
7207 f_rslem_resume(RSL1_PROC);
7208 f_rslem_register(0, new_chan_nr, RSL2_PROC);
7209 f_rslem_resume(RSL2_PROC);
7210
7211 if (expect_handover and not is_inter_bsc_handover) {
7212 setverdict(pass);
7213 log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected.");
7214 } else {
7215 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. "
7216 & log_label & ": " & log_descr);
7217 }
7218
7219 log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
7220 /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with
7221 * Handover Failure. */
7222 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
7223
7224 /* target BTS is told to release lchan again; don't care which BTS nor what messages. */
7225 f_sleep(0.5);
7226 RSL1.clear;
7227 RSL2.clear;
7228 log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)");
7229 break;
7230 } else {
7231 repeat;
7232 }
7233 }
7234 [] BSSAP.receive(tr_BSSMAP_HandoverRequired) {
7235 if (expect_handover and is_inter_bsc_handover) {
7236 setverdict(pass);
7237 log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected.");
7238 } else {
7239 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. "
7240 & log_label & ": " & log_descr);
7241 }
7242
7243 log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)");
7244
7245 /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to
7246 * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required,
7247 * setting a short timeout and waiting is the only way. */
7248 log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out...");
7249 f_sleep(1.5);
7250 log("f_probe_for_handover(" & log_label & "): ...done");
7251
7252 break;
7253 }
7254 [] T.timeout {
7255 if (expect_handover) {
7256 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. "
7257 & log_label & ": " & log_descr);
7258 } else {
7259 setverdict(pass);
7260 log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected.");
7261 }
7262 log("f_probe_for_handover(" & log_label & "): done (got no Handover)");
7263 break;
7264 }
7265 }
7266
7267 f_rslem_resume(RSL1_PROC);
7268 f_rslem_resume(RSL2_PROC);
7269 f_sleep(3.0);
7270 RSL.clear;
7271
7272 log("f_probe_for_handover(" & log_label & "): done clearing");
7273}
7274
7275/* Test the effect of various neighbor configuration scenarios:
7276 *
7277 * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0.
7278 * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO.
7279 */
7280private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
7281 g_pars := f_gen_test_hdlr_pars();
7282 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
7283 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007284
7285 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
7286 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
7287
7288 /* Establish lchan at bts 0 */
7289 f_establish_fully(ass_cmd, exp_compl);
7290
7291 /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */
7292 f_vty_enter_cfg_network(BSCVTY);
7293 f_vty_transceive(BSCVTY, "timer T7 1");
7294 f_vty_transceive(BSCVTY, "end");
7295}
7296
7297private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
7298 f_tc_ho_neighbor_config_start();
7299
7300 /*
7301 * bts 0 ARFCN 871 BSIC 10
7302 * bts 1 ARFCN 871 BSIC 11
7303 * bts 2 ARFCN 871 BSIC 12
7304 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7305 */
7306
7307 log("f_tc_ho_neighbor_config: 1. No 'neighbor' config");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007308 f_bts_0_cfg(BSCVTY, {"no neighbors"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007309 f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
7310 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007311 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007312
7313 f_probe_for_handover("1.b", "HO to unknown cell does not start",
7314 "handover any to arfcn 13 bsic 39",
7315 false);
7316
7317 f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error",
7318 "handover any to arfcn 871 bsic 12",
7319 false);
7320
7321 f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
7322 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007323 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007324
7325 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007326}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007327testcase TC_ho_neighbor_config_1() runs on test_CT {
7328 var MSC_ConnHdlr vc_conn;
7329 f_init(3, true, guard_timeout := 60.0);
7330 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007331 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007332 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
7333 vc_conn.done;
7334
7335 /* f_tc_ho_neighbor_config_start() */
7336 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7337 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7338
7339 /* 1.a */
7340 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7341 * handover quickly by sending a Handover Failure message. */
7342 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7343 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7344 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7345 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007346 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7347 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007348
7349 /* 1.b */
7350 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7351 f_ctrs_bsc_and_bts_add(0, "handover:error");
7352
7353 /* 1.c */
7354 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7355 f_ctrs_bsc_and_bts_add(0, "handover:error");
7356
7357 /* 1.d */
7358 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7359 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7360 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7361 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007362 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7363 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007364
7365 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007366 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007367}
7368
Neels Hofmeyr91401012019-07-11 00:42:35 +02007369private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
7370 f_tc_ho_neighbor_config_start();
7371
7372 /*
7373 * bts 0 ARFCN 871 BSIC 10
7374 * bts 1 ARFCN 871 BSIC 11
7375 * bts 2 ARFCN 871 BSIC 12
7376 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7377 */
7378
7379 log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007380 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007381 f_sleep(0.5);
7382
7383 f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
7384 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007385 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007386
7387 f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
7388 "handover any to arfcn 871 bsic 12",
7389 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007390 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007391}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007392testcase TC_ho_neighbor_config_2() runs on test_CT {
7393 var MSC_ConnHdlr vc_conn;
7394 f_init(3, true, guard_timeout := 50.0);
7395 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007396 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007397 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
7398 vc_conn.done;
7399
7400 /* f_tc_ho_neighbor_config_start() */
7401 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7402 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7403
7404 /* 2.a */
7405 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7406 * handover quickly by sending a Handover Failure message. */
7407 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7408 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7409 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7410 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007411 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7412 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007413
7414 /* 2.b */
7415 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7416 f_ctrs_bsc_and_bts_add(0, "handover:error");
7417
7418 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007419 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007420}
7421
Neels Hofmeyr91401012019-07-11 00:42:35 +02007422private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
7423 f_tc_ho_neighbor_config_start();
7424
7425 /*
7426 * bts 0 ARFCN 871 BSIC 10
7427 * bts 1 ARFCN 871 BSIC 11
7428 * bts 2 ARFCN 871 BSIC 12
7429 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7430 */
7431
7432 log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007433 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007434 f_sleep(0.5);
7435
7436 f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor",
7437 "handover any to arfcn 871 bsic 11",
7438 false);
7439 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",
7440 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007441 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007442 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007443}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007444testcase TC_ho_neighbor_config_3() runs on test_CT {
7445 var MSC_ConnHdlr vc_conn;
7446 f_init(3, true, guard_timeout := 50.0);
7447 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007448 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007449 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
7450 vc_conn.done;
7451
7452 /* f_tc_ho_neighbor_config_start() */
7453 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7454 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7455
7456 /* 3.a */
7457 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7458 f_ctrs_bsc_and_bts_add(0, "handover:error");
7459
7460 /* 3.b */
7461 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7462 * handover quickly by sending a Handover Failure message. */
7463 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7464 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7465 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7466 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007467 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7468 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007469
7470 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007471 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007472}
7473
Neels Hofmeyr91401012019-07-11 00:42:35 +02007474private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
7475 f_tc_ho_neighbor_config_start();
7476
7477 /*
7478 * bts 0 ARFCN 871 BSIC 10
7479 * bts 1 ARFCN 871 BSIC 11
7480 * bts 2 ARFCN 871 BSIC 12
7481 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7482 */
7483
7484 log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007485 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007486 f_sleep(0.5);
7487
7488 f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor",
7489 "handover any to arfcn 871 bsic 11",
7490 false);
7491 f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor",
7492 "handover any to arfcn 871 bsic 12",
7493 false);
7494 f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
7495 "handover any to arfcn 123 bsic 45",
7496 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007497 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007498}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007499testcase TC_ho_neighbor_config_4() runs on test_CT {
7500 var MSC_ConnHdlr vc_conn;
7501 f_init(3, true, guard_timeout := 50.0);
7502 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007503 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007504 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
7505 vc_conn.done;
7506
7507 /* f_tc_ho_neighbor_config_start() */
7508 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7509 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7510
7511 /* 4.a */
7512 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7513 f_ctrs_bsc_and_bts_add(0, "handover:error");
7514
7515 /* 4.b */
7516 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7517 f_ctrs_bsc_and_bts_add(0, "handover:error");
7518
7519 /* 4.c */
7520 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7521 * handover quickly by timing out after the Handover Required message */
7522 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7523 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7524 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7525 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7526
7527 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007528 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007529}
7530
Neels Hofmeyr91401012019-07-11 00:42:35 +02007531private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
7532 f_tc_ho_neighbor_config_start();
7533
7534 /*
7535 * bts 0 ARFCN 871 BSIC 10
7536 * bts 1 ARFCN 871 BSIC 11
7537 * bts 2 ARFCN 871 BSIC 12
7538 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7539 */
7540
7541 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 +02007542 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007543 f_sleep(0.5);
7544
7545 f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
7546 "handover any to arfcn 871 bsic 12",
7547 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007548 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007549}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007550testcase TC_ho_neighbor_config_5() runs on test_CT {
7551 var MSC_ConnHdlr vc_conn;
7552 f_init(3, true);
7553 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007554 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007555 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
7556 vc_conn.done;
7557
7558 /* f_tc_ho_neighbor_config_start() */
7559 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7560 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7561
7562 /* 5 */
7563 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7564 * handover quickly by timing out after the Handover Required message */
7565 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7566 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7567 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7568 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7569
7570 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007571 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007572}
7573
Neels Hofmeyr91401012019-07-11 00:42:35 +02007574private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
7575 f_tc_ho_neighbor_config_start();
7576
7577 /*
7578 * bts 0 ARFCN 871 BSIC 10
7579 * bts 1 ARFCN 871 BSIC 11
7580 * bts 2 ARFCN 871 BSIC 12
7581 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7582 */
7583
7584 log("f_tc_ho_neighbor_config: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:"
7585 & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007586 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007587 f_sleep(0.5);
7588
7589 f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
7590 "handover any to arfcn 871 bsic 12",
7591 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007592 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007593}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007594testcase TC_ho_neighbor_config_6() runs on test_CT {
7595 var MSC_ConnHdlr vc_conn;
7596 f_init(3, true);
7597 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007598 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007599 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
7600 vc_conn.done;
7601
7602 /* f_tc_ho_neighbor_config_start() */
7603 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7604 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7605
7606 /* 6.a */
7607 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7608 * handover quickly by timing out after the Handover Required message */
7609 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7610 f_ctrs_bsc_and_bts_add(0, "handover:error");
7611
7612 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007613 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007614}
7615
Neels Hofmeyr91401012019-07-11 00:42:35 +02007616private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
7617 f_tc_ho_neighbor_config_start();
7618
7619 /*
7620 * bts 0 ARFCN 871 BSIC 10
7621 * bts 1 ARFCN 871 BSIC 11
7622 * bts 2 ARFCN 871 BSIC 12
7623 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7624 */
7625
7626 log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:"
7627 & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007628 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007629 f_sleep(0.5);
7630
7631 f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
7632 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007633 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007634 f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
7635 "handover any to arfcn 123 bsic 45",
7636 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007637 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007638}
Neels Hofmeyr91401012019-07-11 00:42:35 +02007639testcase TC_ho_neighbor_config_7() runs on test_CT {
7640 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf2b88032020-06-16 00:35:04 +02007641 f_init(3, true, guard_timeout := 50.0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007642 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007643 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007644 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
7645 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007646
7647 /* f_tc_ho_neighbor_config_start() */
7648 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7649 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7650
7651 /* 7.a */
7652 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7653 * handover quickly by sending a Handover Failure message. */
7654 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7655 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7656 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7657 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007658 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7659 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007660
7661 /* 7.b */
7662 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7663 * handover quickly by timing out after the Handover Required message */
7664 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7665 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7666 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7667 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7668
7669 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007670 f_shutdown_helper(ho := true);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007671}
7672
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007673/* OS#3041: Open and close N connections in a normal fashion, and expect no
7674 * BSSMAP Reset just because of that. */
7675testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
7676 var default d;
7677 var integer i;
7678 var DchanTuple dt;
7679
7680 f_init();
7681
7682 /* Wait for initial BSSMAP Reset to pass */
7683 f_sleep(4.0);
7684
7685 d := activate(no_bssmap_reset());
7686
7687 /* Setup up a number of connections and RLSD them again from the MSC
7688 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7689 * Let's do it some more times for good measure. */
Harald Weltec3260d92018-06-11 17:48:16 +02007690 for (i := 0; i < 4; i := i+1) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007691 /* Since we're doing a lot of runs, give each one a fresh
7692 * T_guard from the top. */
7693 T_guard.start;
7694
7695 /* Setup a BSSAP connection and clear it right away. This is
7696 * the MSC telling the BSC about a planned release, it's not an
7697 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007698 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007699
7700 /* MSC disconnects (RLSD). */
7701 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
7702 }
7703
7704 /* In the buggy behavior, a timeout of 2 seconds happens between above
7705 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7706 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7707 f_sleep(4.0);
7708
7709 deactivate(d);
7710 f_shutdown_helper();
7711}
Harald Welte552620d2017-12-16 23:21:36 +01007712
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007713/* OS#3041: Open and close N connections in a normal fashion, and expect no
7714 * BSSMAP Reset just because of that. Invoke the release by a BSSMAP Clear from
7715 * the MSC. */
7716testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
7717 var default d;
7718 var integer i;
7719 var DchanTuple dt;
7720 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007721 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
7722 var BssmapCause cause := enum2int(cause_val);
7723
7724 f_init();
7725
7726 /* Wait for initial BSSMAP Reset to pass */
7727 f_sleep(4.0);
7728
7729 d := activate(no_bssmap_reset());
7730
7731 /* Setup up a number of connections and RLSD them again from the MSC
7732 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7733 * Let's do it some more times for good measure. */
7734 for (i := 0; i < 8; i := i+1) {
7735 /* Since we're doing a lot of runs, give each one a fresh
7736 * T_guard from the top. */
7737 T_guard.start;
7738
7739 /* Setup a BSSAP connection and clear it right away. This is
7740 * the MSC telling the BSC about a planned release, it's not an
7741 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007742 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007743
7744 /* Instruct BSC to clear channel */
7745 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7746
7747 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007748 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007749 }
7750
7751 /* In the buggy behavior, a timeout of 2 seconds happens between above
7752 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7753 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7754 f_sleep(4.0);
7755
7756 deactivate(d);
7757 f_shutdown_helper();
7758}
7759
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007760/* OS#3041: Open and close N connections in a normal fashion, and expect no
7761 * BSSMAP Reset just because of that. Close connections from the MS side with a
7762 * Release Ind on RSL. */
7763testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
7764 var default d;
7765 var integer i;
7766 var DchanTuple dt;
7767 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007768 var integer j;
7769
7770 f_init();
7771
7772 /* Wait for initial BSSMAP Reset to pass */
7773 f_sleep(4.0);
7774
7775 d := activate(no_bssmap_reset());
7776
7777 /* Setup up a number of connections and RLSD them again from the MSC
7778 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7779 * Let's do it some more times for good measure. */
7780 for (i := 0; i < 8; i := i+1) {
7781 /* Since we're doing a lot of runs, give each one a fresh
7782 * T_guard from the top. */
7783 T_guard.start;
7784
7785 /* Setup a BSSAP connection and clear it right away. This is
7786 * the MSC telling the BSC about a planned release, it's not an
7787 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007788 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007789
7790 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007791 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007792
7793 /* expect Clear Request on MSC side */
7794 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
7795
7796 /* Instruct BSC to clear channel */
7797 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
7798 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7799
7800 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007801 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007802 }
7803
7804 /* In the buggy behavior, a timeout of 2 seconds happens between above
7805 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7806 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7807 f_sleep(4.0);
7808
7809 deactivate(d);
7810 f_shutdown_helper();
7811}
7812
Harald Welte94e0c342018-04-07 11:33:23 +02007813/***********************************************************************
7814 * IPA style dynamic PDCH
7815 ***********************************************************************/
7816
7817private function f_dyn_ipa_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7818 template (omit) RSL_Cause nack := omit)
7819runs on test_CT {
7820 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7821 var RSL_Message rsl_unused;
7822 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7823 f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
7824 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007825 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007826 if (istemplatekind(nack, "omit")) {
7827 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007828 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007829 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007830 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007831 }
7832}
7833
7834private function f_dyn_ipa_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7835 template (omit) RSL_Cause nack := omit)
7836runs on test_CT {
7837 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7838 var RSL_Message rsl_unused;
7839 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7840 f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
7841 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007842 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_DEACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007843 if (istemplatekind(nack, "omit")) {
7844 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007845 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007846 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007847 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007848 }
7849}
7850
7851private function f_ts_dyn_mode_get(integer bts_nr, integer trx_nr, integer ts_nr)
7852runs on test_CT return charstring {
7853 var charstring cmd, resp;
7854 cmd := "show timeslot "&int2str(bts_nr)&" "&int2str(trx_nr)&" "&int2str(ts_nr);
Stefan Sperlingcff13562018-11-13 15:24:06 +01007855 return f_vty_transceive_match_regexp_retry(BSCVTY, cmd, "*\((*)\)*", 0, 4, 1.0);
Harald Welte94e0c342018-04-07 11:33:23 +02007856}
7857
7858private function f_ts_dyn_mode_assert(integer bts_nr, integer trx_nr, integer ts_nr,
7859 template charstring exp)
7860runs on test_CT {
7861 var charstring mode := f_ts_dyn_mode_get(bts_nr, trx_nr, ts_nr);
7862 if (not match(mode, exp)) {
7863 setverdict(fail, "Unexpected TS Mode: ", mode);
Daniel Willmannafce8662018-07-06 23:11:32 +02007864 mtc.stop;
Harald Welte94e0c342018-04-07 11:33:23 +02007865 }
7866}
7867
7868private function f_ts_set_chcomb(integer bts_nr, integer trx_nr, integer ts_nr, charstring chcomb)
7869runs on test_CT {
7870 f_vty_enter_cfg_ts(BSCVTY, bts_nr, trx_nr, ts_nr);
7871 f_vty_transceive(BSCVTY, "phys_chan_config " & chcomb);
7872 f_vty_transceive(BSCVTY, "end");
7873}
7874
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007875
7876private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
7877 var integer i;
7878 for (i := 0; i < 8; i := i + 1) {
7879 f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
7880 }
7881}
7882
Harald Welte94e0c342018-04-07 11:33:23 +02007883private const charstring TCHF_MODE := "TCH/F mode";
7884private const charstring TCHH_MODE := "TCH/H mode";
7885private const charstring PDCH_MODE := "PDCH mode";
7886private const charstring NONE_MODE := "NONE mode";
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007887private const charstring SDCCH8_MODE := "SDCCH8 mode";
Harald Welte94e0c342018-04-07 11:33:23 +02007888
7889/* Test IPA PDCH activation / deactivation triggered by VTY */
7890testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
7891 var RSL_Message rsl_unused;
7892
7893 /* change Timeslot 6 before f_init() starts RSL */
7894 f_init_vty();
7895 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7896 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7897
7898 f_init(1, false);
7899 f_sleep(1.0);
7900
7901 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7902
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007903 log("TCH/F_PDCH pchan starts out in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007904 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7905 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007906 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7907 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007908 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007909 log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007910 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7911
7912 /* De-activate it via VTY */
7913 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7914 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007915 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007916 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7917
7918 /* re-activate it via VTY */
7919 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn);
7920 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007921 log("TCH/F_PDCH pchan, PDCH ACT via VTY, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007922 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7923
7924 /* and finally de-activate it again */
7925 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7926 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007927 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007928 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7929
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007930 /* clean up config */
7931 f_ts_set_chcomb(0, 0, 6, "PDCH");
7932
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007933 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007934}
7935
7936/* Test IPA PDCH activation NACK */
7937testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
7938 var RSL_Message rsl_unused;
7939
7940 /* change Timeslot 6 before f_init() starts RSL */
7941 f_init_vty();
7942 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7943 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7944
7945 f_init(1, false);
7946 f_sleep(1.0);
7947
7948 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7949
7950 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7951 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007952 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7953 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007954 f_sleep(1.0);
7955 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7956
7957 /* De-activate it via VTY */
7958 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7959 f_sleep(1.0);
7960 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7961
7962 /* re-activate it via VTY, but fail that; check BSC still assumes TCH/F mode */
7963 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn, RSL_ERR_EQUIPMENT_FAIL);
7964 f_sleep(1.0);
7965 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7966
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007967 /* clean up config */
7968 f_ts_set_chcomb(0, 0, 6, "PDCH");
7969
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007970 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007971}
7972
7973
7974/***********************************************************************
7975 * Osmocom style dynamic PDCH
7976 ***********************************************************************/
7977
7978private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7979 template (omit) RSL_Cause nack := omit)
7980runs on test_CT {
7981 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7982 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007983 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007984 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7985 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007986 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT(chan_nr, ?));
Harald Welte94e0c342018-04-07 11:33:23 +02007987 if (istemplatekind(nack, "omit")) {
7988 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007989 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02007990 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007991 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007992 }
7993}
7994
7995private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7996 template (omit) RSL_Cause nack := omit)
7997runs on test_CT {
7998 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7999 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02008000 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02008001 /* FIXME: no VTY command to activate Osmocom PDCH !! */
8002 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008003 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008004 if (istemplatekind(nack, "omit")) {
8005 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008006 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008007 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008008 //f_ipa_tx(ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02008009 }
8010}
8011
8012/* Test Osmocom dyn PDCH activation / deactivation triggered by VTY */
8013testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
8014 var RSL_Message rsl_unused;
8015
8016 /* change Timeslot 6 before f_init() starts RSL */
8017 f_init_vty();
8018 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8019 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8020
8021 f_init(1, false);
8022 f_sleep(1.0);
8023
8024 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8025
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008026 log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02008027 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8028 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008029 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008030
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008031 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02008032 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008033 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 +02008034 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
8035
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008036 /* clean up config */
8037 f_ts_set_chcomb(0, 0, 6, "PDCH");
8038
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008039 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008040}
8041
8042/* Test Osmocom dyn PDCH activation NACK behavior */
8043testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
8044 var RSL_Message rsl_unused;
8045
8046 /* change Timeslot 6 before f_init() starts RSL */
8047 f_init_vty();
8048 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8049 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8050
8051 f_init(1, false);
8052 f_sleep(1.0);
8053
8054 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8055
8056 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8057 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008058 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008059
8060 /* NACK this activation and expect the "show timeslot" mode still to be NONE */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008061 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte94e0c342018-04-07 11:33:23 +02008062 f_sleep(1.0);
8063 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8064
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008065 /* clean up config */
8066 f_ts_set_chcomb(0, 0, 6, "PDCH");
8067
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008068 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008069}
8070
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008071/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
8072testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
8073 var RSL_Message rsl_unused, rsl_msg;
8074 var DchanTuple dt;
8075 var BSSAP_N_CONNECT_ind rx_c_ind;
8076
8077 /* change Timeslot 6 before f_init() starts RSL */
8078 f_init_vty();
8079 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8080 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8081
8082 f_init(1, false);
8083 f_sleep(1.0);
8084
8085 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8086
8087 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8088 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8089 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008090 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008091
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008092 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008093 f_sleep(1.0);
8094 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8095 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8096
8097 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8098 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008099 var DchanTuples sdcch_cleanup := {};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008100 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008101 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008102 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008103 sdcch_cleanup := sdcch_cleanup & { dt };
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008104 }
8105
8106 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008107 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8108 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8109 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008110
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008111 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008112 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008113 dt.idx := {0, 0};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008114
8115 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008116 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8117 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008118 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
8119
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008120 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 +02008121 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8122 dt.sccp_conn_id := rx_c_ind.connectionId;
8123 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8124
8125 /* Instruct BSC to clear channel */
8126 var BssmapCause cause := 0;
8127 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008128 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008129
8130 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008131 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8132 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008133 f_sleep(1.0);
8134 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8135
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008136 /* Clean up SDCCH lchans */
8137 for (i := 0; i < lengthof(sdcch_cleanup); i := i + 1) {
8138 f_perform_clear_test_ct(sdcch_cleanup[i]);
8139 }
8140
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008141 /* clean up config */
8142 f_ts_set_chcomb(0, 0, 6, "PDCH");
8143
8144 f_shutdown_helper();
8145}
8146
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008147/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
8148testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
8149 var ASP_RSL_Unitdata rsl_ud;
8150 var integer i;
8151 var integer chreq_total, chreq_nochan;
8152
8153 f_init_vty();
8154 for (i := 1; i < 8; i := i + 1) {
8155 if (i == 2) {
8156 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8157 } else {
8158 f_ts_set_chcomb(0, 0, i, "PDCH");
8159 }
8160 }
8161 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8162
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008163 f_init(1, guard_timeout := 60.0);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008164
8165 /* The dyn TS want to activate PDCH mode, ACK that. */
8166 var RslChannelNr chan_nr;
8167 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008168 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
8169 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008170
8171 f_sleep(1.0);
8172
8173 /* Exhaust all dedicated SDCCH lchans.
8174 /* GSM 44.018 Table 9.1.8.2:
8175 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
8176 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008177 var DchanTuples chan_cleanup := {};
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008178 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008179 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 +02008180 }
8181
8182 /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008183 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 +02008184 /* Also occupy the seven other SDCCH of the dyn TS */
8185 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008186 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 +01008187 }
8188
8189 /* Clean up SDCCH lchans */
8190 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8191 f_perform_clear_test_ct(chan_cleanup[i]);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008192 }
8193
8194 /* clean up config */
8195 f_ts_reset_chcomb(0);
8196
8197 f_shutdown_helper();
8198}
8199
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008200/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
8201 SDCCH8 would end up in having no free TCH, then BSC should decide to activate
8202 it as TCH directly instead. SYS#5309. */
8203testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
8204 var RSL_Message rsl_unused, rsl_msg;
8205 var DchanTuple dt;
8206 var BSSAP_N_CONNECT_ind rx_c_ind;
8207 var integer i;
8208
8209 /* change Timeslot 6 before f_init() starts RSL */
8210 f_init_vty();
8211 for (i := 1; i < 8; i := i + 1) {
8212 if (i == 6) {
8213 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8214 } else {
8215 f_ts_set_chcomb(0, 0, i, "PDCH");
8216 }
8217 }
8218 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8219
8220 f_init(1, false);
8221 f_sleep(1.0);
8222
8223 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8224
8225 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8226 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8227 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008228 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008229
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008230 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008231 f_sleep(1.0);
8232 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8233 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8234
8235 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8236 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008237 var DchanTuples chan_cleanup := {};
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02008238 var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008239 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008240 dt := f_est_dchan(ra, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008241 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008242 }
8243
8244 /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008245 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
8246 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8247 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008248
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008249 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008250 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008251 dt.idx := {0, 0};
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008252
8253 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008254 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8255 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008256 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
8257
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008258 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 +02008259 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8260 dt.sccp_conn_id := rx_c_ind.connectionId;
8261 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8262
8263 /* Instruct BSC to clear channel */
8264 var BssmapCause cause := 0;
8265 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008266 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008267
8268 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008269 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8270 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008271 f_sleep(1.0);
8272 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8273
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008274 /* Clean up SDCCH lchans */
8275 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8276 f_perform_clear_test_ct(chan_cleanup[i]);
8277 }
8278
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008279 /* clean up config */
8280 f_ts_reset_chcomb(0);
8281 /* TODO: clean up other channels? */
8282
8283 f_shutdown_helper();
8284}
8285
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008286/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
8287testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
8288 var RSL_Message rsl_unused, rsl_msg;
8289 var DchanTuple dt;
8290 var BSSAP_N_CONNECT_ind rx_c_ind;
8291 var GsmRrMessage rr;
8292
8293 /* change Timeslot 6 before f_init() starts RSL */
8294 f_init_vty();
8295 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8296 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8297
8298 f_init(1, false);
8299 f_sleep(1.0);
8300
8301 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8302
8303 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8304 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8305 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008306 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008307
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008308 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008309 f_sleep(1.0);
8310 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8311 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8312
8313 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8314 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008315 var DchanTuples chan_cleanup := {};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008316 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008317 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008318 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008319 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008320 }
8321
8322 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008323 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8324 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8325 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008326
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008327 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008328 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008329 dt.idx := {0, 0};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008330
8331 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008332 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
8333 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008334 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
8335 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
8336 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
8337 }
8338
8339 /* FIXME? Currently the TS stays in state BORKEN: */
8340
8341 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008342 /* rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8343 * f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008344 * f_sleep(1.0);
8345 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
8346 */
8347
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008348 /* Clean up SDCCH lchans */
8349 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8350 f_perform_clear_test_ct(chan_cleanup[i]);
8351 }
8352
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008353 /* clean up config */
8354 f_ts_set_chcomb(0, 0, 6, "PDCH");
8355
8356 f_shutdown_helper();
8357}
8358
Stefan Sperling0796a822018-10-05 13:01:39 +02008359testcase TC_chopped_ipa_ping() runs on test_CT {
Stefan Sperling554123f2018-10-09 14:12:30 +02008360 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port, mp_bsc_ctrl_port};
Stefan Sperling0796a822018-10-05 13:01:39 +02008361 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8362 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8363 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008364 f_shutdown_helper();
Stefan Sperling0796a822018-10-05 13:01:39 +02008365}
8366
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008367testcase TC_chopped_ipa_payload() runs on test_CT {
8368 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port
8369 /* TODO: mp_bsc_ctrl_port does not work yet */};
8370 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8371 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8372 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008373 f_shutdown_helper();
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008374}
8375
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008376/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
8377 the BTS does autonomous MS power control loop */
8378testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
8379 var MSC_ConnHdlr vc_conn;
8380 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8381 //pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
8382 pars.exp_ms_power_params := true;
8383
8384 f_init(1, true);
8385 f_sleep(1.0);
8386 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
8387 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008388 f_shutdown_helper();
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008389}
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008390
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008391/* Verify activation and deactivation of the BCCH carrier power reduction mode */
8392testcase TC_c0_power_red_mode() runs on test_CT {
8393 f_init(1);
8394
8395 for (var integer red := 6; red >= 0; red := red - 2) {
8396 /* Configure BCCH carrier power reduction mode via the VTY */
8397 f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
8398
8399 /* Expect Osmocom specific BS Power Control message on the RSL */
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03008400 var template (present) RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008401 chan_nr := t_RslChanNr_BCCH(0),
8402 bs_power := tr_RSL_IE_BS_Power(red / 2));
8403 tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008404 var RSL_Message unused := f_exp_ipa_rx(tr_rsl_pdu);
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008405
8406 /* Additionally verify the applied value over the CTRL interface */
8407 var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
8408 if (cred != int2str(red)) {
8409 setverdict(fail, "Unexpected BCCH carrier power reduction value ",
8410 cred, " (expected ", red, ")");
8411 }
8412 }
8413
8414 f_shutdown_helper();
8415}
8416
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008417/***********************************************************************
8418 * MSC Pooling
8419 ***********************************************************************/
8420
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008421template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
Harald Weltebf397612021-01-14 20:39:46 +01008422 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 +02008423
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008424private 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 +02008425runs on MSC_ConnHdlr {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008426 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008427 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008428 f_logp(BSCVTY, "Got RSL RR Release");
8429 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008430 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008431 f_logp(BSCVTY, "Got RSL Deact SACCH");
8432 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008433 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008434 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008435 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8436 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008437 break;
8438 }
8439 }
8440}
8441
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008442private altstep as_mgcp_ack_all_dlcx() runs on MSC_ConnHdlr {
8443 var MgcpCommand mgcp_cmd;
8444 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
8445 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
8446 repeat;
8447 }
8448}
8449
8450private altstep as_rsl_ack_all_rel_req() runs on MSC_ConnHdlr {
8451 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
8452 [] RSL.receive(tr_RSL_REL_REQ(g_chan_nr, ?)) {
8453 RSL.send(ts_RSL_REL_CONF(g_chan_nr, main_dcch));
8454 repeat;
8455 }
8456}
8457
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008458friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
8459 template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02008460runs on MSC_ConnHdlr {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008461 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8462 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008463 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008464 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8465 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008466 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008467 f_logp(BSCVTY, "Got RSL RR Release");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008468 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008469 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008470 f_logp(BSCVTY, "Got RSL Deact SACCH");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008471 }
8472 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008473 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008474 /* Also drop the SCCP connection */
8475 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8476 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008477 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008478 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008479 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8480 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008481 }
8482 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008483 deactivate(ack_dlcx);
8484 deactivate(ack_rel_req);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008485}
8486
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01008487friend function f_perform_clear_no_rr_rel(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC)
8488runs on MSC_ConnHdlr {
8489 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8490 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
8491 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8492 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8493 interleave {
8494 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
8495 f_logp(BSCVTY, "Got RSL Deact SACCH");
8496 }
8497 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
8498 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8499 /* Also drop the SCCP connection */
8500 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8501 }
8502 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
8503 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
8504 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8505 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
8506 }
8507 }
8508 deactivate(ack_dlcx);
8509 deactivate(ack_rel_req);
8510}
8511
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01008512friend function f_perform_clear_no_lchan()
8513runs on MSC_ConnHdlr {
8514 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8515 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8516 BSSAP.receive(tr_BSSMAP_ClearComplete);
8517 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8518 /* Also drop the SCCP connection */
8519 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8520}
8521
Vadim Yanitskiy65d879d2022-06-23 18:15:39 +07008522friend function f_perform_clear_test_ct(DchanTuple dt)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008523 runs on test_CT
8524{
8525 /* Instruct BSC to clear channel */
8526 var BssmapCause cause := 0;
8527 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008528 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008529}
8530
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008531private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
8532 template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008533runs on MSC_ConnHdlr {
8534 timer T := 10.0;
8535 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
8536
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008537 f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008538 f_create_bssmap_exp(l3_enc);
8539
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008540 /* RSL_Emulation.f_chan_est() on rsl_pt:
8541 * This is basically code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008542 * RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
8543 */
8544 var RSL_Message rx_rsl;
8545 var GsmRrMessage rr;
8546
8547 /* request a channel to be established */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008548 rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008549 /* expect immediate assignment.
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008550 * Code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008551 * rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
8552 */
8553 timer Tt := 10.0;
8554
8555 /* request a channel to be established */
8556 Tt.start;
8557 alt {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008558 [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008559 Tt.stop;
8560 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008561 [] rsl_pt.receive {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008562 setverdict(fail, "Unexpected RSL message on DCHAN");
8563 mtc.stop;
8564 }
8565 [] Tt.timeout {
8566 setverdict(fail, "Timeout waiting for RSL on DCHAN");
8567 mtc.stop;
8568 }
8569 }
8570 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
8571 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008572 rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008573
8574
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008575 if (expect_bssmap_l3) {
8576 f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
8577 var template PDU_BSSAP exp_l3_compl;
8578 exp_l3_compl := tr_BSSMAP_ComplL3()
8579 if (g_pars.aoip == false) {
8580 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
8581 } else {
8582 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
8583 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008584
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008585 var PDU_BSSAP bssap;
8586 T.start;
8587 alt {
8588 [] BSSAP.receive(exp_l3_compl) -> value bssap {
8589 f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
8590 log("rx exp_l3_compl = ", bssap);
8591 }
8592 [] BSSAP.receive(tr_BSSMAP_ComplL3) {
8593 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
8594 }
8595 [] T.timeout {
8596 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
8597 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008598 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008599
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008600 /* start ciphering, if requested */
8601 if (ispresent(g_pars.encr)) {
8602 f_logp(BSCVTY, "start ciphering");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008603 f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008604 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008605 }
8606
8607 if (do_clear) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008608 f_perform_clear(rsl_pt, rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008609 }
8610 setverdict(pass);
8611 f_sleep(1.0);
8612}
8613
8614private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
8615 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8616 if (g_pars.mscpool.rsl_idx == 0) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008617 f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008618 } else if (g_pars.mscpool.rsl_idx == 1) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008619 f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008620 } else if (g_pars.mscpool.rsl_idx == 2) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008621 f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008622 }
8623}
8624
8625/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
8626private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
8627 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008628 f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
8629 f_perform_compl_l3(RSL, RSL_PROC, ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_IMSI_LV('001010000000002'H))) );
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008630 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)) );
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008631 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 +02008632}
8633testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
8634
8635 f_init(1, true);
8636 f_sleep(1.0);
8637 var MSC_ConnHdlr vc_conn;
8638 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008639
8640 f_ctrs_msc_init();
8641
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008642 vc_conn := f_start_handler(refers(f_tc_mscpool_L3Compl_on_1_msc), pars);
8643 vc_conn.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008644
8645 f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008646 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008647}
8648
8649/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
8650/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8651 * just as well using only RSL. */
8652testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
8653
8654 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8655 f_sleep(1.0);
8656
8657 /* Control which MSC gets chosen next by the round-robin, otherwise
8658 * would be randomly affected by which other tests ran before this. */
8659 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8660
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008661 f_ctrs_msc_init();
8662
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008663 var MSC_ConnHdlr vc_conn1;
8664 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8665 pars1.mscpool.rsl_idx := 0;
8666 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8667 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8668 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008669 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008670
8671 var MSC_ConnHdlr vc_conn2;
8672 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8673 pars2.mscpool.rsl_idx := 1;
8674 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8675 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8676 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008677 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008678
8679 /* Test round-robin wrap to the first MSC */
8680 var MSC_ConnHdlr vc_conn3;
8681 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8682 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008683 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008684 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8685 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008686 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008687 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008688}
8689
8690/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 0
8691 * (configured in osmo-bsc.cfg). */
8692/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8693 * just as well using only RSL. */
8694testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
8695
8696 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8697 f_sleep(1.0);
8698
8699 /* Control which MSC gets chosen next by the round-robin, otherwise
8700 * would be randomly affected by which other tests ran before this. */
8701 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8702
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008703 f_ctrs_msc_init();
8704
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008705 var MSC_ConnHdlr vc_conn1;
8706 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8707 pars1.mscpool.rsl_idx := 0;
8708 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8709 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8710 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008711 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008712
8713 var MSC_ConnHdlr vc_conn2;
8714 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8715 pars2.mscpool.rsl_idx := 1;
8716 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8717 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8718 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008719 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008720
8721 /* Test round-robin wrap to the first MSC */
8722 var MSC_ConnHdlr vc_conn3;
8723 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8724 pars3.mscpool.rsl_idx := 2;
8725 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8726 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8727 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008728 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008729 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008730}
8731
8732/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
8733 * (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
8734 * NULL-NRI setting is stronger than that. */
8735/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8736 * just as well using only RSL. */
8737testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
8738
8739 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8740 f_sleep(1.0);
8741
8742 /* Control which MSC gets chosen next by the round-robin, otherwise
8743 * would be randomly affected by which other tests ran before this. */
8744 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8745
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008746 f_ctrs_msc_init();
8747
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008748 var MSC_ConnHdlr vc_conn1;
8749 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8750 pars1.mscpool.rsl_idx := 0;
8751 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8752 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8753 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008754 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008755
8756 var MSC_ConnHdlr vc_conn2;
8757 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8758 pars2.mscpool.rsl_idx := 1;
8759 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8760 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8761 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008762 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008763
8764 /* Test round-robin wrap to the first MSC */
8765 var MSC_ConnHdlr vc_conn3;
8766 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8767 pars3.mscpool.rsl_idx := 2;
8768 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8769 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8770 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008771 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008772 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008773}
8774
8775/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
8776 * assigned to any MSC (configured in osmo-bsc.cfg). */
8777/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8778 * just as well using only RSL. */
8779testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test_CT {
8780
8781 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8782 f_sleep(1.0);
8783
8784 /* Control which MSC gets chosen next by the round-robin, otherwise
8785 * would be randomly affected by which other tests ran before this. */
8786 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8787
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008788 f_ctrs_msc_init();
8789
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008790 var MSC_ConnHdlr vc_conn1;
8791 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8792 pars1.mscpool.rsl_idx := 0;
8793 /* An NRI that is not assigned to any MSC */
8794 pars1.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(1023))));
8795 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8796 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008797 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008798
8799 var MSC_ConnHdlr vc_conn2;
8800 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8801 pars2.mscpool.rsl_idx := 1;
8802 /* An NRI that is not assigned to any MSC */
8803 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(768)), '00F110'O));
8804 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8805 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008806 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008807
8808 /* Test round-robin wrap to the first MSC */
8809 var MSC_ConnHdlr vc_conn3;
8810 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8811 pars3.mscpool.rsl_idx := 2;
8812 /* An NRI that is not assigned to any MSC */
8813 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, valueof(ts_MI_TMSI_NRI_LV(819))));
8814 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8815 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008816 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008817 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008818}
8819
8820/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
8821 * assigned to an MSC that is currently not connected (configured in osmo-bsc.cfg). */
8822/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8823 * just as well using only RSL. */
8824testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
8825
8826 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8827 f_sleep(1.0);
8828
8829 /* Control which MSC gets chosen next by the round-robin, otherwise
8830 * would be randomly affected by which other tests ran before this. */
8831 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8832
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008833 f_ctrs_msc_init();
8834
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008835 var MSC_ConnHdlr vc_conn1;
8836 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8837 pars1.mscpool.rsl_idx := 0;
8838 /* An NRI that is assigned to an unconnected MSC */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008839 pars1.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(512)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008840 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8841 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008842 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8843 f_ctrs_msc_add(0, "mscpool:subscr:new");
8844 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008845
8846 var MSC_ConnHdlr vc_conn2;
8847 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8848 pars2.mscpool.rsl_idx := 1;
8849 /* An NRI that is assigned to an unconnected MSC */
8850 pars2.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(767))));
8851 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8852 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008853 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8854 f_ctrs_msc_add(1, "mscpool:subscr:new");
8855 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008856
8857 /* Test round-robin wrap to the first MSC */
8858 var MSC_ConnHdlr vc_conn3;
8859 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8860 pars3.mscpool.rsl_idx := 2;
8861 /* An NRI that is assigned to an unconnected MSC */
8862 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(750)), '00F110'O));
8863 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8864 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008865 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8866 f_ctrs_msc_add(0, "mscpool:subscr:new");
8867 f_ctrs_msc_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008868 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008869}
8870
8871/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
8872 * osmo-bsc.cfg). */
8873/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8874 * just as well using only RSL. */
8875testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
8876
8877 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8878 f_sleep(1.0);
8879
8880 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
8881 * this is not using round-robin. */
8882 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8883
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008884 f_ctrs_msc_init();
8885
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008886 var MSC_ConnHdlr vc_conn1;
8887 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8888 pars1.mscpool.rsl_idx := 0;
8889 /* An NRI of the second MSC's range (256-511) */
8890 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(256))));
8891 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8892 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008893 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008894
8895 var MSC_ConnHdlr vc_conn2;
8896 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8897 pars2.mscpool.rsl_idx := 1;
8898 /* An NRI of the second MSC's range (256-511) */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008899 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(260)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008900 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8901 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008902 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008903
8904 var MSC_ConnHdlr vc_conn3;
8905 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8906 pars3.mscpool.rsl_idx := 2;
8907 /* An NRI of the second MSC's range (256-511) */
8908 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(511)), '00F110'O));
8909 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8910 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008911 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008912 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008913}
8914
8915/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
8916 * while a round-robin remains unaffected by that. */
8917/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8918 * just as well using only RSL. */
8919testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
8920
8921 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8922 f_sleep(1.0);
8923
8924 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
8925 * this is not using round-robin. */
8926 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8927
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008928 f_ctrs_msc_init();
8929
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008930 var MSC_ConnHdlr vc_conn1;
8931 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 2);
8932 pars1.mscpool.rsl_idx := 0;
8933 /* An NRI of the third MSC's range (512-767) */
8934 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(512))));
8935 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8936 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008937 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008938
8939 var MSC_ConnHdlr vc_conn2;
8940 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8941 pars2.mscpool.rsl_idx := 1;
8942 /* An NRI of the third MSC's range (512-767) */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008943 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(678)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008944 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8945 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008946 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008947
8948 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
8949 var MSC_ConnHdlr vc_conn3;
8950 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8951 pars3.mscpool.rsl_idx := 2;
8952 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000013'H)), '00F110'O));
8953 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8954 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008955 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008956 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008957}
8958
8959/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
8960/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8961 * just as well using only RSL. */
8962testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
8963
8964 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8965 f_sleep(1.0);
8966
8967 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
8968 * instead, and hits msc 0. */
8969 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8970
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008971 f_ctrs_msc_init();
8972
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008973 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-bsc.cfg */
8974 var MSC_ConnHdlr vc_conn1;
8975 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8976 pars1.mscpool.rsl_idx := 0;
8977 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(260)), '99F999'O));
8978 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8979 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008980 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008981
8982 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
8983 var MSC_ConnHdlr vc_conn2;
8984 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8985 pars2.mscpool.rsl_idx := 1;
8986 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(555)), '00F110'O));
8987 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8988 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008989 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008990 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008991}
8992
8993/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
8994 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
8995private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
8996 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
8997 //cid_list := { cIl_allInBSS := ''O };
8998 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
8999 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9000 var BSSAP_N_UNITDATA_req paging;
9001 var hexstring imsi := '001010000000123'H;
9002
9003 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9004
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009005 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009006 valueof(ts_BSSMAP_Paging(imsi, cid_list, omit, bssmap_chneed))));
9007 BSSAP.send(paging);
9008
9009 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9010 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9011 * channel number is picked here. */
9012 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9013 f_rslem_register(0, new_chan_nr);
9014 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(imsi)));
9015 f_rslem_unregister(0, new_chan_nr);
9016
9017 /* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
9018 * causes this Paging Response to go to the first MSC (bssap_idx := 0). */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009019 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV(imsi)) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009020 f_sleep(1.0);
9021}
9022testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
9023 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9024 f_sleep(1.0);
9025
9026 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9027 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9028 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
9029
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009030 f_ctrs_msc_init();
9031
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009032 var MSC_ConnHdlr vc_conn1;
9033 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9034 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009035 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9036 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009037 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
9038 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009039 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009040 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009041}
9042
9043/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
9044 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9045private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
9046 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9047 //cid_list := { cIl_allInBSS := ''O };
9048 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9049 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9050 var integer nri_v := 300; /* <-- second MSC's NRI */
Harald Weltebf397612021-01-14 20:39:46 +01009051 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009052 var BSSAP_N_UNITDATA_req paging;
9053
9054 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9055
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009056 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009057 valueof(ts_BSSMAP_Paging('001010000000011'H, cid_list, tmsi, bssmap_chneed))));
9058 BSSAP.send(paging);
9059
9060 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9061 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9062 * channel number is picked here. */
9063 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9064 f_rslem_register(0, new_chan_nr);
9065 RSL.receive(tr_RSL_PAGING_CMD(t_MI_TMSI(tmsi)));
9066 f_rslem_unregister(0, new_chan_nr);
9067
9068 /* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
9069 * third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
9070 * the first MSC (bssap_idx := 0). */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009071 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_TMSI_NRI_LV(nri_v)) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009072 f_sleep(1.0);
9073}
9074testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
9075 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9076 f_sleep(1.0);
9077
9078 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9079 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9080 f_vty_transceive(BSCVTY, "mscpool roundrobin next 2");
9081
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009082 f_ctrs_msc_init();
9083
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009084 var MSC_ConnHdlr vc_conn1;
9085 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9086 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009087 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9088 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009089 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
9090 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009091 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009092 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009093}
9094
9095/* For round-robin, skip an MSC that has 'no allow-attach' set. */
9096/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
9097 * just as well using only RSL. */
9098testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
9099
9100 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9101 f_sleep(1.0);
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009102 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9103 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009104
9105 /* Control which MSC gets chosen next by the round-robin, otherwise
9106 * would be randomly affected by which other tests ran before this. */
9107 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9108
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009109 f_ctrs_msc_init();
9110
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009111 var MSC_ConnHdlr vc_conn1;
9112 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9113 pars1.mscpool.rsl_idx := 0;
9114 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9115 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9116 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009117 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009118
9119 var MSC_ConnHdlr vc_conn2;
9120 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9121 pars2.mscpool.rsl_idx := 1;
9122 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9123 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9124 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009125 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009126
9127 var MSC_ConnHdlr vc_conn3;
9128 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
9129 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009130 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009131 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9132 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009133 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009134 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009135}
9136
9137/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
9138 * TMSI NRI. */
9139testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
9140
9141 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9142 f_sleep(1.0);
9143
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009144 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9145 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
9146
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009147 /* Control which MSC gets chosen next by the round-robin, otherwise
9148 * would be randomly affected by which other tests ran before this. */
9149 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9150
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009151 f_ctrs_msc_init();
9152
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009153 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
9154 var MSC_ConnHdlr vc_conn1;
9155 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
9156 pars1.mscpool.rsl_idx := 0;
9157 /* An NRI of the second MSC's range (256-511) */
9158 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_TMSI_NRI_LV(260))));
9159 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9160 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009161 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009162
9163 var MSC_ConnHdlr vc_conn2;
9164 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9165 pars2.mscpool.rsl_idx := 1;
9166 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9167 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9168 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009169 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009170
9171 var MSC_ConnHdlr vc_conn3;
9172 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 2);
9173 pars3.mscpool.rsl_idx := 2;
9174 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000003'H))));
9175 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9176 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009177 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009178 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009179}
9180
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009181/* When an MSC point-code gets an SCCP N-PCSTATE saying it is unreachable, immediately mark the MSC as unusable. */
9182testcase TC_mscpool_sccp_n_pcstate_detaches_msc() runs on test_CT {
9183
9184 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
9185 f_sleep(1.0);
9186
9187 /* Control which MSC gets chosen next by the round-robin, otherwise
9188 * would be randomly affected by which other tests ran before this. */
9189 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9190
9191 f_ctrs_msc_init();
9192
9193 var MSC_ConnHdlr vc_conn1;
9194 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9195 pars1.mscpool.rsl_idx := 0;
9196 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9197 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9198 vc_conn1.done;
9199 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9200
9201 var MSC_ConnHdlr vc_conn2;
9202 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
9203 pars2.mscpool.rsl_idx := 1;
9204 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9205 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9206 vc_conn2.done;
9207 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9208
9209 f_logp(BSCVTY, "disconnecting msc0");
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009210 f_bssap_idx_disconnect(0);
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009211
9212 /* Now round-robin would wrap to the first MSC, but since the first MSC is disconnected, it wraps around to msc
9213 * 2 again. */
9214 var MSC_ConnHdlr vc_conn3;
9215 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
9216 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009217 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009218 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9219 vc_conn3.done;
9220 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9221 f_shutdown_helper();
9222}
9223
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009224/* When an MSC point-code gets an SCCP N-PCSTATE saying it is now reachable, immediately trigger RESET and bring up the
9225 * MSC. */
9226testcase TC_mscpool_sccp_n_pcstate_attaches_msc() runs on test_CT {
9227
9228 f_init(nr_bts := 3, handler_mode := true, nr_msc := 1);
9229 f_sleep(1.0);
9230
9231 /* Control which MSC gets chosen next by the round-robin, otherwise
9232 * would be randomly affected by which other tests ran before this. */
9233 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9234
9235 f_ctrs_msc_init();
9236
9237 /* There is only one MSC, round robin stays on msc0 */
9238 var MSC_ConnHdlr vc_conn1;
9239 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9240 pars1.mscpool.rsl_idx := 0;
9241 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('0010100230000001'H)), '00F110'O));
9242 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9243 vc_conn1.done;
9244 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9245
9246 var MSC_ConnHdlr vc_conn2;
9247 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9248 pars2.mscpool.rsl_idx := 1;
9249 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010023000002'H))));
9250 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9251 vc_conn2.done;
9252 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9253
9254 f_logp(BSCVTY, "connecting msc1");
9255 f_vty_msc_allow_attach(BSCVTY, { true, true });
9256 f_bssap_idx_init(1);
9257 f_sleep(1.0);
9258
9259 /* This time round-robin wraps to the second MSC, because it is now online. */
9260 var MSC_ConnHdlr vc_conn4;
9261 var TestHdlrParams pars4 := f_gen_test_hdlr_pars(bssap_idx := 1);
9262 pars4.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009263 pars4.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010023000003'H)));
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009264 vc_conn4 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars4);
9265 vc_conn4.done;
9266 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9267
9268 f_shutdown_helper();
9269}
9270
Philipp Maier783681c2020-07-16 16:47:06 +02009271/* Allow/Deny emergency calls globally via VTY */
9272private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
9273 f_vty_enter_cfg_msc(BSCVTY, 0);
9274 if (allow) {
9275 f_vty_transceive(BSCVTY, "allow-emergency allow");
9276 } else {
9277 f_vty_transceive(BSCVTY, "allow-emergency deny");
9278 }
9279 f_vty_transceive(BSCVTY, "exit");
9280 f_vty_transceive(BSCVTY, "exit");
9281}
9282
9283/* Allow/Deny emergency calls per BTS via VTY */
9284private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
9285 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9286 if (allow) {
9287 f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
9288 } else {
9289 f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
9290 }
9291 f_vty_transceive(BSCVTY, "exit");
9292 f_vty_transceive(BSCVTY, "exit");
Neels Hofmeyrb6ed80c2020-10-12 22:52:39 +00009293 f_vty_transceive(BSCVTY, "exit");
Philipp Maier783681c2020-07-16 16:47:06 +02009294}
9295
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02009296/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
9297private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
9298 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9299 if (allow) {
9300 f_vty_transceive(BSCVTY, "srvcc fast-return allow");
9301 } else {
9302 f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
9303 }
9304 f_vty_transceive(BSCVTY, "exit");
9305 f_vty_transceive(BSCVTY, "exit");
9306 f_vty_transceive(BSCVTY, "exit");
9307}
9308
Pau Espin Pedrol14475352021-07-22 15:48:16 +02009309/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
9310private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
9311 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9312 if (allow) {
9313 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
9314 } else {
9315 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
9316 }
9317 f_vty_transceive(BSCVTY, "exit");
9318 f_vty_transceive(BSCVTY, "exit");
9319 f_vty_transceive(BSCVTY, "exit");
9320}
9321
Pau Espin Pedrol35609792023-01-03 16:56:59 +01009322/* Begin assignment procedure and send an EMERGENCY SETUP (RR) */
Philipp Maier783681c2020-07-16 16:47:06 +02009323private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
9324 var PDU_ML3_MS_NW emerg_setup;
9325 var octetstring emerg_setup_enc;
9326 var RSL_Message emerg_setup_data_ind;
9327
9328 f_establish_fully(omit, omit);
9329
9330 emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
9331 emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
9332 emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
9333
9334 RSL.send(emerg_setup_data_ind);
9335}
9336
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009337/* expect EmergencySetup on BSSAP after calling f_assignment_emerg_setup() */
9338private function f_assignment_emerg_setup_exp_bssap()
9339runs on MSC_ConnHdlr {
Philipp Maier783681c2020-07-16 16:47:06 +02009340 var PDU_BSSAP emerg_setup_data_ind_bssap;
9341 var PDU_ML3_MS_NW emerg_setup;
9342 timer T := 3.0;
9343
Philipp Maier783681c2020-07-16 16:47:06 +02009344 T.start;
9345 alt {
9346 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
9347 emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
9348 if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
9349 setverdict(fail, "no emergency setup");
9350 }
9351 }
9352 [] BSSAP.receive {
9353 setverdict(fail, "unexpected BSSAP message!");
9354 }
9355 [] T.timeout {
9356 setverdict(fail, "timout waiting for EMERGENCY SETUP!");
9357 }
9358 }
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009359}
9360
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009361private function f_assignment_emerg_setup_voice()
9362runs on MSC_ConnHdlr {
9363 /* Go on with voice call assignment */
9364 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
9365 var PDU_BSSAP ass_cmd := f_gen_ass_req();
9366
9367 /* Below speechOrDataIndicator and codecList are copied from an emergency call captured during tests.
9368 * They seem a bit weird (AMR-WB, and the order differ between speechId_DataIndicator and the codecList), but
9369 * seems a good idea to see how osmo-bsc reacts to this. */
9370 ass_cmd.pdu.bssmap.assignmentRequest.channelType := {
9371 elementIdentifier := '0B'O, /* overwritten */
9372 lengthIndicator := 0, /* overwritten */
9373 speechOrDataIndicator := '0001'B, /* speech */
9374 spare1_4 := '0000'B,
9375 channelRateAndType := ChRate_TCHForH_Fpref,
9376 speechId_DataIndicator := 'c2918105'O
9377 };
9378 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({
9379 ts_CodecHR, ts_CodecAMR_WB, ts_CodecEFR, ts_CodecFR}));
9380
9381 f_rslem_dchan_queue_enable();
9382
9383 var ExpectCriteria mgcpcrit := {
9384 connid := omit,
9385 endpoint := omit,
9386 transid := omit
9387 };
9388 f_create_mgcp_expect(mgcpcrit);
9389
9390 BSSAP.send(ass_cmd);
9391
9392 var AssignmentState st := valueof(ts_AssignmentStateInit);
9393 st.voice_call := true;
9394 st.is_assignment := false;
9395 alt {
9396 [] as_modify(st);
9397 [] as_Media();
9398 [st.modify_done] BSSAP.receive(exp_compl) {
9399 setverdict(pass);
9400 }
9401 }
9402
9403 /* Voice call carries on ... */
9404 f_sleep(2.0);
9405}
9406
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009407/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
9408 * CALLS are permitted by the BSC config. */
9409private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
9410
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009411 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
9412 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
9413 * another lchan. */
9414 g_pars.ra := f_rnd_ra_emerg();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009415 f_assignment_emerg_setup();
9416 f_assignment_emerg_setup_exp_bssap();
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009417 f_assignment_emerg_setup_voice();
Philipp Maier783681c2020-07-16 16:47:06 +02009418
9419 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009420 f_perform_clear();
Philipp Maier783681c2020-07-16 16:47:06 +02009421}
9422
9423/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
9424 * forbidden by the BSC config. */
9425private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
9426 var PDU_BSSAP emerg_setup_data_ind_bssap;
9427 timer T := 3.0;
9428
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009429 f_assignment_emerg_setup();
Philipp Maier783681c2020-07-16 16:47:06 +02009430
9431 T.start;
9432 alt {
9433 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
9434 setverdict(pass);
9435 }
9436 [] RSL.receive {
9437 setverdict(fail, "unexpected RSL message!");
9438 }
9439 [] T.timeout {
9440 setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
9441 }
9442 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009443 BSSAP.receive(tr_BSSMAP_ClearRequest);
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01009444 f_perform_clear_no_rr_rel();
Philipp Maier783681c2020-07-16 16:47:06 +02009445}
9446
9447/* EMERGENCY CALL situation #1, allowed globally and by BTS */
9448testcase TC_assignment_emerg_setup_allow() runs on test_CT {
9449 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9450 var MSC_ConnHdlr vc_conn;
9451
9452 f_init(1, true);
9453 f_sleep(1.0);
9454
9455 f_vty_allow_emerg_msc(true);
9456 f_vty_allow_emerg_bts(true, 0);
9457 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9458 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009459 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009460}
9461
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +01009462/* Test MO emergency call using MobileIdentity=IMEI (possible for emergency
9463 * calls from phones without SIM card).
9464 * 3GPP TS 24.008 section 10.5.1.4, OS#5849 */
9465testcase TC_assignment_emerg_setup_allow_imei() runs on test_CT {
9466 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9467 var MSC_ConnHdlr vc_conn;
9468
9469 /* Remove IMSI set by f_gen_test_hdlr_pars(), then IMEI will be used to place the call */
9470 pars.imsi := omit;
9471
9472 f_init(1, true);
9473 f_sleep(1.0);
9474
9475 f_vty_allow_emerg_msc(true);
9476 f_vty_allow_emerg_bts(true, 0);
9477 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9478 vc_conn.done;
9479 f_shutdown_helper();
9480}
9481
Philipp Maier783681c2020-07-16 16:47:06 +02009482/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
9483testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
9484 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9485 var MSC_ConnHdlr vc_conn;
9486
9487 f_init(1, true);
9488 f_sleep(1.0);
9489
9490 f_vty_allow_emerg_msc(false);
9491 f_vty_allow_emerg_bts(true, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009492 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx): */
9493 pars.ra := f_rnd_ra_emerg();
Philipp Maier783681c2020-07-16 16:47:06 +02009494 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9495 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009496 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009497}
9498
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009499/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS.
9500 * The RACH req (and hence CHAN RQD) indicate other than emergency call.
9501 * Hence BSC only learns about it being an emergency call later during call setup.
9502 * If interested in the ra="emergency call" + deny bts policy case,
9503 * see TC_chan_rqd_emerg_deny.
9504 */
Philipp Maier783681c2020-07-16 16:47:06 +02009505testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
9506 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9507 var MSC_ConnHdlr vc_conn;
9508
9509 /* Note: This simulates a spec violation by the MS, correct MS
9510 * implementations would not try to establish an emergency call because
9511 * the system information tells in advance that emergency calls are
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009512 * not allowed */
Philipp Maier783681c2020-07-16 16:47:06 +02009513
9514 f_init(1, true);
9515 f_sleep(1.0);
9516
9517 f_vty_allow_emerg_msc(true);
9518 f_vty_allow_emerg_bts(false, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009519 /* Note: Here we implicitly leave default g_pars.ra which is different than "emergency call" */
Philipp Maier783681c2020-07-16 16:47:06 +02009520 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9521 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009522 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009523}
9524
Philipp Maier82812002020-08-13 18:48:27 +02009525/* Test what happens when an emergency call arrives while all TCH channels are
9526 * busy, the BSC is expected to terminate one call in favor of the incoming
9527 * emergency call */
9528testcase TC_emerg_premption() runs on test_CT {
9529 var ASP_RSL_Unitdata rsl_ud;
9530 var integer i;
9531 var integer chreq_total, chreq_nochan;
9532 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009533 var octetstring l3_payload := gen_l3_valid_payload();
Philipp Maier82812002020-08-13 18:48:27 +02009534
9535 f_init(1);
9536 f_sleep(1.0);
9537
9538 f_vty_allow_emerg_msc(true);
9539 f_vty_allow_emerg_bts(true, 0);
9540
9541 /* Fill up all channels on the BTS */
9542 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
9543 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
9544 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 +02009545 f_chreq_act_ack('33'O, i);
Philipp Maier82812002020-08-13 18:48:27 +02009546 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009547 IPA_RSL[0][0].clear;
Philipp Maier82812002020-08-13 18:48:27 +02009548 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
9549 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
9550
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009551 /* Send EST IND for the first TCH, so we get to test the RR release cause */
9552 var RslChannelNr first_tch := valueof(t_RslChanNr_Bm(1));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009553 f_ipa_tx(ts_RSL_EST_IND(first_tch, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009554
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009555 /* Accept BSSAP conn, so we get to test the Clear Request cause */
9556 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009557 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009558 var integer sccp_conn_id := rx_c_ind.connectionId;
9559 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
9560
Philipp Maier82812002020-08-13 18:48:27 +02009561 /* Send Channel request for emegergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009562 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier82812002020-08-13 18:48:27 +02009563
9564 /* Expect the BSC to release one (the first) TCH/F on the BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009565 f_expect_chan_rel(first_tch, expect_rr_chan_rel := true, expect_rll_rel_req := false,
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009566 expect_rr_cause := GSM48_RR_CAUSE_PREMPTIVE_REL);
Philipp Maier82812002020-08-13 18:48:27 +02009567
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009568 /* Also expect a BSSMAP Clear Request with PREEMPTION */
9569 var BSSAP_N_DATA_ind rx_clear_req;
9570 const myBSSMAP_Cause preemption := GSM0808_CAUSE_PREEMPTION;
9571 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_clear_req;
9572 log("XXX ", rx_clear_req);
9573 if (rx_clear_req.userData.pdu.bssmap.clearRequest.cause.causeValue != int2bit(enum2int(preemption), 7)) {
9574 setverdict(fail, "BSSMAP Clear Request: expected cause PREEMPTION");
9575 }
9576
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009577 /* Expect the BSC to send activate/assign the channel for the emergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009578 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009579 if (first_tch != rx_rsl.ies[0].body.chan_nr) {
9580 setverdict(fail, "different TCH lchan activated than expected");
9581 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009582 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(first_tch, 33));
9583 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Philipp Maier104f4c02020-09-11 18:12:18 +02009584
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009585 /* complete the BSSMAP Clear to satisfy the conn leak check */
9586 BSSAP.send(ts_BSSAP_DATA_req(sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(preemption))));
9587 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearComplete)) {
9588 BSSAP.send(ts_BSSAP_DISC_req(sccp_conn_id, 0));
9589 }
9590
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009591 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009592}
9593
9594/* Hopping parameters per a timeslot */
Vadim Yanitskiybc6654a2020-09-13 01:27:40 +07009595private type record length(0..64) of GsmArfcn ArfcnList;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009596private type record FHParamsTs {
9597 boolean enabled,
9598 uint6_t hsn,
9599 uint6_t maio,
9600 ArfcnList ma
9601};
9602
9603/* Hopping parameters per a transceiver */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009604private type record FHParamsTrx {
Philipp Maier798d8952021-10-19 14:43:19 +02009605 GsmBandArfcn arfcn,
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009606 FHParamsTs ts[8]
9607};
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009608
9609/* Randomly generate the hopping parameters for the given timeslot numbers */
9610private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
9611runs on test_CT return FHParamsTrx {
9612 var FHParamsTrx fhp;
9613
Philipp Maier798d8952021-10-19 14:43:19 +02009614 /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
9615 * fall in the GSM900 band. */
9616 fhp.arfcn.arfcn := f_rnd_int(3);
9617 fhp.arfcn.pcs := false;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009618
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009619 for (var integer tn := 0; tn < 8; tn := tn + 1) {
9620 if (not match(tn, tr_tn)) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009621 fhp.ts[tn].enabled := false;
9622 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009623 continue;
9624 }
9625
9626 /* Random HSN / MAIO values: 0..63 */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009627 fhp.ts[tn].hsn := f_rnd_int(64);
9628 fhp.ts[tn].maio := f_rnd_int(64);
9629 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009630
9631 /* Random Mobile Allocation (hopping channels) */
9632 var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
9633 var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
9634 for (var integer i := 1; i <= ma_len; i := i + 1) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009635 fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009636 }
9637
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009638 fhp.ts[tn].enabled := true;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009639 }
9640
9641 log("f_TC_fh_params_gen(): ", fhp);
9642 return fhp;
9643}
9644
9645/* Make sure that the given Channel Description IE matches the hopping configuration */
9646private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
9647{
9648 var template (present) ChannelDescription tr_cd;
9649 var template (present) MaioHsn tr_maio_hsn;
9650 var uint3_t tn := cd.chan_nr.tn;
9651
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009652 if (fhp.ts[tn].enabled) {
9653 tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009654 tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
9655 } else {
Philipp Maier798d8952021-10-19 14:43:19 +02009656 tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009657 }
9658
9659 if (not match(cd, tr_cd)) {
9660 setverdict(fail, "Channel Description IE does not match: ",
9661 cd, " vs expected ", tr_cd);
9662 }
9663}
9664
9665/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
9666private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
9667 in MobileAllocationLV ma)
9668{
9669 var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
9670
9671 if (not match(ma, tr_ma)) {
9672 setverdict(fail, "Mobile Allocation IE does not match (tn := ",
9673 tn, "): ", ma, " vs expected: ", tr_ma);
9674 } else {
9675 setverdict(pass);
9676 }
9677}
9678
9679private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
9680 in MobileAllocationLV ma)
9681return template MobileAllocationLV {
9682 /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009683 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009684 return { len := 0, ma := ''B };
9685 }
9686
9687 var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
9688 var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
9689 var bitstring ma_mask := ''B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009690
9691 /* Compose the full bit-mask (all channels, up to 1024 entries) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009692 for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
9693 for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
9694 if (full_mask[fhp.ts[i].ma[j]] == '1'B)
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009695 { continue; }
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009696 full_mask[fhp.ts[i].ma[j]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009697 }
9698 }
9699
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009700 /* Take ARFCN of the TRX itself into account */
Philipp Maier798d8952021-10-19 14:43:19 +02009701 full_mask[fhp.arfcn.arfcn] := '1'B;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009702
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009703 /* Compose a bit-mask for the given timeslot number */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009704 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9705 slot_mask[fhp.ts[tn].ma[i]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009706 }
9707
9708 /* Finally, compose the Mobile Allocation bit-mask */
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009709 for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009710 if (full_mask[i] != '1'B)
9711 { continue; }
9712
9713 /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
9714 if (slot_mask[i] == '1'B) {
9715 ma_mask := ma_mask & '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009716 } else {
9717 ma_mask := ma_mask & '0'B;
9718 }
9719 }
9720
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009721 /* ARFCN 0 (if present) goes to the last position of the bit-mask */
9722 if (full_mask[0] == '1'B) {
9723 /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
9724 if (slot_mask[0] == '1'B) {
9725 ma_mask := ma_mask & '1'B;
9726 } else {
9727 ma_mask := ma_mask & '0'B;
9728 }
9729 }
9730
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009731 /* Ensure that ma_mask is octet-aligned */
Vadim Yanitskiy2aa02522020-09-06 14:05:23 +07009732 var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009733 ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
9734
9735 return { len := ma_mask_len, ma := ma_mask };
9736}
9737
Philipp Maier798d8952021-10-19 14:43:19 +02009738/* Configure the appropriate band for a given arfcn, exc */
9739private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
9740{
9741 var charstring band;
9742 var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
9743
9744 select (arfcn_) {
9745 case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
9746 case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
9747 case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
9748 case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
9749 case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
9750 case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
9751 case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
9752 case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
9753 case else { return; }
9754 }
9755
9756 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9757 f_vty_transceive(BSCVTY, "band " & band);
9758 f_vty_transceive(BSCVTY, "end");
9759}
9760
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009761/* Configure the hopping parameters in accordance with the given record */
9762private function f_TC_fh_params_set(in FHParamsTrx fhp,
9763 uint8_t bts_nr := 0,
9764 uint8_t trx_nr := 0)
9765runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009766
9767 f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
9768
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009769 /* Enter the configuration node for the given BTS/TRX numbers */
9770 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9771
Philipp Maier798d8952021-10-19 14:43:19 +02009772 f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009773
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009774 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009775 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9776
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009777 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009778 f_vty_transceive(BSCVTY, "hopping enabled 0");
9779 f_vty_transceive(BSCVTY, "exit"); /* go back */
9780 continue;
9781 }
9782
9783 /* Configure HSN / MAIO values */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009784 f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
9785 f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009786
9787 /* Configure the Mobile Allocation (hopping channels) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009788 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9789 f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009790 }
9791
9792 f_vty_transceive(BSCVTY, "hopping enabled 1");
9793 f_vty_transceive(BSCVTY, "exit"); /* go back */
9794 }
9795
9796 f_vty_transceive(BSCVTY, "end");
9797}
9798
9799/* Disable frequency hopping on all timeslots */
9800private function f_TC_fh_params_unset(in FHParamsTrx fhp,
9801 uint8_t bts_nr := 0,
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009802 uint8_t trx_nr := 0,
Philipp Maier798d8952021-10-19 14:43:19 +02009803 GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009804runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009805
9806 f_TC_set_band_by_arfcn(bts_nr, arfcn);
9807
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009808 /* Enter the configuration node for the given BTS/TRX numbers */
9809 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9810
Philipp Maier798d8952021-10-19 14:43:19 +02009811 f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009812
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009813 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009814 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9815
9816 /* Delete all ARFCNs from the Mobile Allocation (if any) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009817 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9818 f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009819 }
9820
9821 f_vty_transceive(BSCVTY, "hopping enabled 0");
9822 f_vty_transceive(BSCVTY, "exit"); /* go back */
9823 }
9824
9825 f_vty_transceive(BSCVTY, "end");
9826 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9827}
9828
9829/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
9830 * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
9831testcase TC_fh_params_chan_activ() runs on test_CT {
9832 var FHParamsTrx fhp := f_TC_fh_params_gen();
9833 var RSL_Message rsl_msg;
9834 var RSL_IE_Body ie;
9835
9836 f_init_vty();
9837
9838 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9839 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9840
9841 f_init(1);
9842
9843 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9844 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009845 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9846 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009847
9848 /* Make sure that Channel Identification IE is present */
9849 if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
9850 setverdict(fail, "RSL Channel Identification IE is absent");
9851 continue;
9852 }
9853
9854 /* Make sure that hopping parameters (HSN/MAIO) match */
9855 f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
9856
9857 /* "Mobile Allocation shall be included but empty" - let's check this */
9858 if (ie.chan_ident.ma.v.len != 0) {
9859 setverdict(fail, "Mobile Allocation IE is not empty: ",
9860 ie.chan_ident.ma, ", despite it shall be");
9861 continue;
9862 }
9863 }
9864
9865 /* Disable frequency hopping */
9866 f_TC_fh_params_unset(fhp);
9867
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009868 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009869}
9870
9871/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
9872testcase TC_fh_params_imm_ass() runs on test_CT {
9873 var FHParamsTrx fhp := f_TC_fh_params_gen();
9874 var RSL_Message rsl_msg;
9875 var RSL_IE_Body ie;
9876
9877 f_init_vty();
9878
9879 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9880 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9881
9882 f_init(1);
9883
9884 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9885 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009886 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9887 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009888
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009889 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9890 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009891
9892 /* Make sure that Full Immediate Assign Info IE is present */
9893 if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
9894 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
9895 continue;
9896 }
9897
9898 /* Decode the actual Immediate Assignment message */
9899 var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
9900 if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
9901 setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
9902 continue;
9903 }
9904
9905 /* Make sure that hopping parameters (HSN/MAIO) match */
9906 f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
9907
9908 /* Make sure that the Mobile Allocation IE matches */
9909 f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
9910 rr_msg.payload.imm_ass.mobile_allocation);
9911 }
9912
9913 /* Disable frequency hopping */
9914 f_TC_fh_params_unset(fhp);
Philipp Maier82812002020-08-13 18:48:27 +02009915
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009916 f_shutdown_helper();
Philipp Maier82812002020-08-13 18:48:27 +02009917}
9918
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009919/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
9920testcase TC_fh_params_assignment_cmd() runs on test_CT {
9921 var FHParamsTrx fhp := f_TC_fh_params_gen();
9922 var RSL_Message rsl_msg;
9923 var RSL_IE_Body ie;
9924
9925 f_init_vty();
9926
9927 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9928 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9929
9930 f_init(1);
9931
9932 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02009933 vc_MGCP[0].stop;
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009934
9935 var template PDU_BSSAP ass_cmd := f_gen_ass_req();
9936 ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
9937
9938 /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
9939 * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
9940 for (var integer i := 0; i < 3; i := i + 1) {
9941 /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009942 var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009943
9944 /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
9945 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009946 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009947
9948 /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009949 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9950 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009951
9952 /* Make sure that L3 Information IE is present */
9953 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9954 setverdict(fail, "RSL L3 Information IE is absent");
9955 continue;
9956 }
9957
9958 /* Decode the L3 message and make sure it is (RR) Assignment Command */
9959 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9960 if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
9961 setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
9962 continue;
9963 }
9964
9965 /* Make sure that hopping parameters (HSN/MAIO) match */
9966 var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
9967 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9968
9969 /* Make sure that Cell Channel Description IE is present if FH is enabled */
9970 if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
Vadim Yanitskiy38d069d2020-09-02 17:18:57 +07009971 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009972 continue;
9973 }
9974
9975 /* Make sure that the Mobile Allocation IE matches (if present) */
9976 var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
9977 if (chan_desc.h and ma_present) {
9978 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9979 l3_msg.payload.ass_cmd.mobile_allocation.v);
9980 } else if (chan_desc.h and not ma_present) {
9981 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9982 continue;
9983 } else if (not chan_desc.h and ma_present) {
9984 setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
9985 continue;
9986 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009987
9988 f_perform_clear_test_ct(dt);
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009989 }
9990
9991 /* Give the IUT some time to release all channels */
9992 f_sleep(3.0);
9993
9994 /* Disable frequency hopping */
9995 f_TC_fh_params_unset(fhp);
9996
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009997 f_shutdown_helper();
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009998}
9999
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010000/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
10001private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
10002runs on test_CT {
10003 var RSL_Message rsl_msg;
10004 var RSL_IE_Body ie;
10005 var DchanTuple dt;
10006
10007 /* Establish a dedicated channel, so we can trigger handover */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010010008 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyc18ff472021-11-18 20:15:37 +030010009 f_sleep(0.5);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010010
10011 /* Trigger handover from BTS0 to BTS1 */
10012 f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
10013 f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
10014
10015 /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010016 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx := {1, 0});
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010017
10018 /* ACKnowledge channel activation and expect (RR) Handover Command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010019 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33), idx := {1, 0});
10020 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010021
10022 /* Make sure that L3 Information IE is present */
10023 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
10024 setverdict(fail, "RSL L3 Information IE is absent");
10025 return;
10026 }
10027
10028 /* Decode the L3 message and make sure it is (RR) Handover Command */
10029 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
10030 if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
10031 setverdict(fail, "Failed to match Handover Command: ", l3_msg);
10032 return;
10033 }
10034
10035 /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
10036 var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
10037 if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
10038 setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
10039 return;
10040 }
10041
10042 /* Make sure that hopping parameters (HSN/MAIO) match */
10043 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10044
10045 /* Make sure that Cell Channel Description IE is present */
10046 if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
10047 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
10048 return;
10049 }
10050
10051 /* Make sure that the Mobile Allocation (after time) IE is present and matches */
10052 var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
10053 if (ma_present) {
10054 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10055 l3_msg.payload.ho_cmd.mobile_allocation.v);
10056 } else {
10057 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10058 return;
10059 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010060
10061 f_perform_clear_test_ct(dt);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010062}
10063testcase TC_fh_params_handover_cmd() runs on test_CT {
10064 var FHParamsTrx fhp := f_TC_fh_params_gen();
10065
10066 f_init_vty();
10067
10068 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
10069 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
10070
10071 f_vty_transceive(BSCVTY, "timeslot 0");
10072 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10073 f_vty_transceive(BSCVTY, "exit"); /* go back */
10074
10075 f_vty_transceive(BSCVTY, "timeslot 1");
10076 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
10077 f_vty_transceive(BSCVTY, "end"); /* we're done */
10078
10079 f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
10080 f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
10081
10082 f_init(2);
10083
10084 f_TC_fh_params_handover_cmd(fhp);
10085
10086 /* Disable frequency hopping on BTS1 */
10087 f_TC_fh_params_unset(fhp, 1);
10088
10089 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
10090 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
10091
10092 f_vty_transceive(BSCVTY, "timeslot 0");
10093 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
10094 f_vty_transceive(BSCVTY, "exit"); /* go back */
10095
10096 f_vty_transceive(BSCVTY, "timeslot 1");
10097 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10098 f_vty_transceive(BSCVTY, "end"); /* we're done */
10099
10100 f_shutdown_helper();
10101}
10102
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010103/* Verify the hopping parameters in System Information Type 4 */
10104testcase TC_fh_params_si4_cbch() runs on test_CT {
10105 var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
10106 var ASP_RSL_Unitdata rx_rsl_ud;
10107 timer T := 5.0;
10108
10109 f_init_vty();
10110
10111 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
10112 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10113
10114 f_vty_transceive(BSCVTY, "timeslot 0");
10115 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10116 f_vty_transceive(BSCVTY, "exit"); /* go back */
10117
10118 f_vty_transceive(BSCVTY, "timeslot 1");
10119 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
10120 f_vty_transceive(BSCVTY, "end"); /* we're done */
10121
10122 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
10123 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10124
10125 f_init(1);
10126
10127 T.start;
10128 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010129 [] 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 +070010130 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
10131 var SystemInformation si := dec_SystemInformation(ie.other.payload);
10132
10133 /* Make sure that what we decoded is System Information Type 4 */
10134 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
10135 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
10136 repeat;
10137 }
10138
10139 /* Make sure that CBCH Channel Description IE is present */
10140 if (not ispresent(si.payload.si4.cbch_chan_desc)) {
10141 setverdict(fail, "CBCH Channel Description IE is absent");
10142 break;
10143 }
10144
10145 /* Finally, check the hopping parameters (HSN, MAIO) */
10146 var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
10147 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10148
10149 /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
10150 * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
10151 if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
10152 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10153 break;
10154 } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
10155 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10156 si.payload.si4.cbch_mobile_alloc.v);
10157 }
10158 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010159 [] IPA_RSL[0][0].receive { repeat; }
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010160 [] T.timeout {
10161 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
10162 }
10163 }
10164
10165 /* Disable frequency hopping */
10166 f_TC_fh_params_unset(fhp);
10167
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010168 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010169 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10170
10171 f_vty_transceive(BSCVTY, "timeslot 0");
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010172 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010173 f_vty_transceive(BSCVTY, "exit"); /* go back */
10174
10175 f_vty_transceive(BSCVTY, "timeslot 1");
10176 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10177 f_vty_transceive(BSCVTY, "end"); /* we're done */
10178
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010179 f_shutdown_helper();
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010180}
10181
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010182template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
10183 := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
10184
10185private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
10186 template (present) BSSLAP_PDU expect_bsslap)
10187{
10188 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
10189 if (not match(bsslap, expect_bsslap)) {
10190 log("EXPECTING BSSLAP: ", expect_bsslap);
10191 log("GOT BSSLAP: ", bsslap);
10192 setverdict(fail, "BSSLAP is not as expected");
10193 mtc.stop;
10194 }
10195 setverdict(pass);
10196}
10197
10198/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
10199const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
10200
10201private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
10202 var PDU_BSSAP_LE rx_bsslap;
10203 BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
10204 f_match_bsslap(rx_bsslap, expect_rx_bsslap);
10205}
10206
10207/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10208 * Request on Lb interface. Either with or without the SMLC doing a BSSLAP TA Request. */
10209private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
10210 f_sleep(1.0);
10211
10212 f_establish_fully(omit, omit);
10213 f_bssap_le_register_imsi(g_pars.imsi, omit);
10214
10215 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10216 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10217
10218 var PDU_BSSAP_LE plr;
10219 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10220
10221 if (not do_ta_request) {
10222 /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
10223 var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
10224 if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
10225 log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
10226 log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
10227 setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
10228 mtc.stop;
10229 }
10230 var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
10231 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
10232 if (not match(bsslap, expect_ta_layer3)) {
10233 log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
10234 log("GOT BSSLAP: ", bsslap);
10235 setverdict(fail, "BSSLAP is not as expected");
10236 mtc.stop;
10237 }
10238 /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
10239 * has no need to request the TA from the BSC and directly responds. */
10240 } else {
10241 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10242 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10243 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10244 }
10245
10246 /* SMLC got the TA from the BSC, now responds with geo information data. */
10247 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10248 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10249 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10250
10251 /* The LCS was using an active A-interface conn. It should still remain active after this. */
10252 f_mo_l3_transceive();
10253
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010254 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010255
10256 f_sleep(2.0);
10257 setverdict(pass);
10258}
10259
10260/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10261 * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
10262private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
10263 f_lcs_loc_req_for_active_ms(false);
10264}
10265testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
10266 var MSC_ConnHdlr vc_conn;
10267 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10268
10269 f_init(1, true);
10270 f_sleep(1.0);
10271 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
10272 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010273 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010274}
10275
10276/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10277 * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
10278private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
10279 f_lcs_loc_req_for_active_ms(true);
10280}
10281testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
10282 var MSC_ConnHdlr vc_conn;
10283 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10284
10285 f_init(1, true);
10286 f_sleep(1.0);
10287 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
10288 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010289 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010290}
10291
10292/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
10293 * conn without an active lchan. */
10294private function f_clear_A_conn() runs on MSC_ConnHdlr
10295{
10296 var BssmapCause cause := 0;
10297 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10298 BSSAP.receive(tr_BSSMAP_ClearComplete);
10299 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10300
10301 timer no_more_bssap := 5.0;
10302 no_more_bssap.start;
10303 alt {
10304 [] no_more_bssap.timeout { break; }
10305 [] BSSAP.receive(tr_BSSAP_BSSMAP) {
10306 setverdict(fail, "Expected no more BSSAP after Clear Complete");
10307 mtc.stop;
10308 }
10309 }
10310 setverdict(pass);
10311}
10312
10313/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
10314 * for LCS, for cases where there is only an A conn without an active lchan. */
10315private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
10316{
10317 f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
10318
10319 /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
10320 * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
10321 * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
10322 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10323 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10324 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10325
10326 /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
10327 f_clear_A_conn();
10328 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10329 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10330}
10331
10332/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10333 * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
10334 */
10335private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
10336 f_sleep(1.0);
10337
10338 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10339 f_bssap_le_register_imsi(g_pars.imsi, omit);
10340
10341 /* Register to receive the Paging Command */
10342 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10343 g_chan_nr := new_chan_nr;
10344 f_rslem_register(0, g_chan_nr);
10345
10346 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10347 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10348 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10349 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10350
10351 var PDU_BSSAP_LE plr;
10352 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10353
10354 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10355 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10356
10357 /* OsmoBSC needs to Page */
10358 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
10359 f_logp(BSCVTY, "got Paging Command");
10360
10361 /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
10362 * the MSC, and releases the lchan directly. */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +020010363 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV(g_pars.imsi)), do_clear := false, expect_bssmap_l3 := false);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010364 f_expect_lchan_rel(RSL, RSL_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010365
10366 /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
10367
10368 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10369
10370 /* SMLC got the TA from the BSC, now responds with geo information data. */
10371 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10372 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10373
10374 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10375
10376 /* The lchan is gone, the A-interface conn was created for the LCS only.
10377 * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
10378 f_verify_active_A_conn_and_clear();
10379
10380 f_sleep(2.0);
10381 setverdict(pass);
10382}
10383testcase TC_lcs_loc_req_for_idle_ms() runs on test_CT {
10384 var MSC_ConnHdlr vc_conn;
10385 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10386
10387 f_init(1, true);
10388 f_sleep(1.0);
10389
10390 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10391 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10392
10393 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
10394 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010395 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010396}
10397
10398/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
10399 */
10400private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
10401 f_sleep(1.0);
10402
10403 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10404 f_bssap_le_register_imsi(g_pars.imsi, omit);
10405
10406 /* provoke an abort by omitting both IMSI and IMEI */
10407 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10408 valueof(ts_BSSMAP_Perform_Location_Request(omit,
10409 ts_CellId_CGI('262'H, '42'H, 23, 42)))));
10410 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10411
10412 /* BSC tells MSC about failure */
10413 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10414 locationEstimate := omit, positioningData := omit,
10415 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
10416
10417 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10418 f_verify_active_A_conn_and_clear();
10419
10420 f_sleep(2.0);
10421 setverdict(pass);
10422}
10423testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
10424 var MSC_ConnHdlr vc_conn;
10425 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10426
10427 f_init(1, true);
10428 f_sleep(1.0);
10429
10430 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10431 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10432
10433 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
10434 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010435 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010436}
10437
10438/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10439 * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
10440private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
10441 f_sleep(1.0);
10442
10443 f_establish_fully(omit, omit);
10444 f_bssap_le_register_imsi(g_pars.imsi, omit);
10445
10446 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10447 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10448
10449 var PDU_BSSAP_LE plr;
10450 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10451
10452 if (do_ta) {
10453 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10454 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10455 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10456 }
10457
10458 /* SMLC fails to respond, BSC runs into timeout */
10459 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
10460 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10461
10462 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10463 locationEstimate := omit, positioningData := omit,
10464 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
10465
10466 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10467 f_verify_active_A_conn_and_clear();
10468
10469 f_sleep(2.0);
10470 setverdict(pass);
10471}
10472
10473/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10474 * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
10475private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
10476 f_lcs_loc_req_for_active_ms_le_timeout(false);
10477}
10478
10479testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
10480 var MSC_ConnHdlr vc_conn;
10481 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10482
10483 f_init(1, true);
10484 f_sleep(1.0);
10485 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
10486 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010487 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010488}
10489
10490/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10491 * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
10492private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
10493 f_lcs_loc_req_for_active_ms_le_timeout(true);
10494}
10495
10496testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
10497 var MSC_ConnHdlr vc_conn;
10498 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10499
10500 f_init(1, true);
10501 f_sleep(1.0);
10502 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
10503 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010504 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010505}
10506
10507/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
10508private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
10509 f_sleep(1.0);
10510
10511 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10512 f_bssap_le_register_imsi(g_pars.imsi, omit);
10513
10514 /* Register to receive the Paging Command */
10515 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10516 g_chan_nr := new_chan_nr;
10517 f_rslem_register(0, g_chan_nr);
10518
10519 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10520 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10521 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10522 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10523
10524 var PDU_BSSAP_LE plr;
10525 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10526
10527 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10528 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10529
10530 /* OsmoBSC needs to Page */
10531 var PDU_BSSAP_LE rx_bsslap;
10532 alt {
10533 [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
10534 f_logp(BSCVTY, "got Paging Command");
10535 repeat;
10536 }
10537 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10538 /* MS does not respond to Paging, TA Req runs into timeout. */
10539 f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
10540 }
10541 }
10542
10543 /* SMLC responds with failure */
10544 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10545 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10546
10547 /* BSC tells MSC about failure */
10548 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10549 locationEstimate := omit, positioningData := omit,
10550 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
10551
10552 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10553 f_verify_active_A_conn_and_clear();
10554
10555 f_sleep(2.0);
10556 setverdict(pass);
10557}
10558testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
10559 var MSC_ConnHdlr vc_conn;
10560 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10561
10562 f_init(1, true);
10563 f_sleep(1.0);
10564
10565 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10566 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10567
10568 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
10569 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010570 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010571}
10572
10573/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
10574 * over. */
10575private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10576 f_sleep(1.0);
10577
10578 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10579 f_bssap_le_register_imsi(g_pars.imsi, omit);
10580
10581 /* Register to receive the Paging Command */
10582 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10583 g_chan_nr := new_chan_nr;
10584 f_rslem_register(0, g_chan_nr);
10585
10586 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10587 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10588 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10589 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10590
10591 var PDU_BSSAP_LE plr;
10592 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10593
10594 /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
10595 * and establish Layer 3. It should use the existing A-interface conn. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010596 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 +020010597 do_clear := false, expect_bssmap_l3 := true);
10598
10599 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10600 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10601
10602 /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
10603 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10604
10605 /* SMLC got the TA from the BSC, now responds with geo information data. */
10606 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10607 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10608 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10609
10610 /* The lchan should still exist, it was from a CM Service Request. */
10611 f_mo_l3_transceive();
10612
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010613 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010614
10615 f_sleep(2.0);
10616 setverdict(pass);
10617}
10618testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
10619 var MSC_ConnHdlr vc_conn;
10620 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10621
10622 f_init(1, true);
10623 f_sleep(1.0);
10624
10625 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10626 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10627
10628 vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
10629 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010630 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010631}
10632
10633/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
10634 * the new lchan after handover. */
10635private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10636 f_sleep(1.0);
10637
10638 f_establish_fully(omit, omit);
10639 f_bssap_le_register_imsi(g_pars.imsi, omit);
10640
10641 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10642 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10643
10644 var PDU_BSSAP_LE plr;
10645 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10646
10647 /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
10648 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
10649
10650 var HandoverState hs := {
10651 rr_ho_cmpl_seen := false,
10652 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +020010653 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010654 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010655 };
10656 /* issue hand-over command on VTY */
10657 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
10658 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
10659 f_rslem_suspend(RSL1_PROC);
10660
10661 /* From the MGW perspective, a handover is is characterized by
10662 * performing one MDCX operation with the MGW. So we expect to see
10663 * one more MDCX during handover. */
10664 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
10665
10666 alt {
10667 [] as_handover(hs);
10668 }
10669
10670 var PDU_BSSAP_LE rx_bsslap;
10671
10672 interleave {
10673 /* Expect the BSC to inform the MSC about the handover */
10674 [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
10675
10676 /* Expect the BSC to inform the SMLC about the handover */
10677 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10678 f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
10679 }
10680 }
10681
10682 /* SMLC now responds with geo information data. */
10683 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10684 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10685 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10686
10687 /* lchan still active */
10688 f_mo_l3_transceive(RSL1);
10689
10690 /* MSC decides it is done now. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010691 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010692
10693 f_sleep(2.0);
10694 setverdict(pass);
10695}
10696testcase TC_ho_during_lcs_loc_req() runs on test_CT {
10697 var MSC_ConnHdlr vc_conn;
10698 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10699
10700 f_init(2, true);
10701 f_sleep(1.0);
10702 vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
10703 vc_conn.done;
Oliver Smith39f53072022-10-27 14:44:04 +020010704 f_shutdown_helper(ho := true);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010705}
10706
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010707private function f_tc_emerg_call_and_lcs_loc_req(charstring id) runs on MSC_ConnHdlr
10708{
10709 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
10710 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
10711 * another lchan. */
Pau Espin Pedrol1809bce2023-01-03 16:54:41 +010010712 g_pars.ra := f_rnd_ra_emerg();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010713 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010714 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010715
10716 /* Here would usually be a CC Call Proceeding from the MSC, but what does the BSC care about DTAP. */
10717
10718 /* Do a Location Request in-between the CC call setup */
10719 f_bssap_le_register_imsi(g_pars.imsi, omit);
10720 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10721 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10722 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10723 /* SMLC got the TA from the BSC, now responds with geo information data. */
10724 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10725 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10726 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10727
Pau Espin Pedrol14076d32023-01-03 17:07:59 +010010728 f_assignment_emerg_setup_voice();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010729
10730 setverdict(pass);
10731 f_perform_clear();
10732}
10733
10734testcase TC_emerg_call_and_lcs_loc_req() runs on test_CT {
10735 var MSC_ConnHdlr vc_conn;
10736 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10737
10738 f_init(1, true);
10739 f_sleep(1.0);
10740 f_vty_allow_emerg_msc(true);
10741 f_vty_allow_emerg_bts(true, 0);
10742 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req), pars);
10743 vc_conn.done;
10744 f_shutdown_helper();
10745}
10746
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010747private altstep no_bssmap_clear_req() runs on MSC_ConnHdlr {
10748 [] BSSAP.receive(tr_BSSMAP_ClearRequest) {
10749 setverdict(fail, "unexpected BSSMAP Clear Request");
10750 mtc.stop;
10751 }
10752}
10753
10754private type enumerated RslRel {
10755 RSLREL_REL_IND,
10756 RSLREL_CONN_FAIL
10757};
10758
10759private function f_emerg_call_and_lcs_loc_req_early_lchan_release(RslRel rsl_rel) runs on MSC_ConnHdlr
10760{
10761 g_pars.ra := f_rnd_ra_emerg();
10762 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010763 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010764
10765 /* Start a Location Request to locate the emergency */
10766 f_bssap_le_register_imsi(g_pars.imsi, omit);
10767 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10768 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10769 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10770
10771 /* 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
10772 * do a Clear Command when the Location Response arrives. */
10773 activate(no_bssmap_clear_req());
10774
10775 /* the lchan gets interrupted while the Location Request has no response */
10776 select (rsl_rel) {
10777 case (RSLREL_REL_IND) {
10778 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
10779 f_expect_lchan_rel(RSL, RSL_PROC);
10780 }
10781 case (RSLREL_CONN_FAIL) {
10782 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
10783 }
10784 case else {
10785 setverdict(fail, "Unknown RslRel type");
10786 mtc.stop;
10787 }
10788 }
10789
10790 /* Still expect the Location Response to find its way to the MSC. */
10791 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10792 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10793 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10794
10795 setverdict(pass);
10796
10797 select (rsl_rel) {
10798 case (RSLREL_REL_IND) {
10799 f_perform_clear_no_lchan();
10800 }
10801 case (RSLREL_CONN_FAIL) {
10802 f_perform_clear();
10803 }
10804 }
10805}
10806
10807private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind(charstring id) runs on MSC_ConnHdlr
10808{
10809 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_REL_IND);
10810}
10811
10812testcase TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() runs on test_CT {
10813 var MSC_ConnHdlr vc_conn;
10814 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10815
10816 f_init(1, true);
10817 f_sleep(1.0);
10818 f_vty_allow_emerg_msc(true);
10819 f_vty_allow_emerg_bts(true, 0);
10820 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind), pars);
10821 vc_conn.done;
10822 f_shutdown_helper();
10823}
10824
10825private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail(charstring id) runs on MSC_ConnHdlr
10826{
10827 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_CONN_FAIL);
10828}
10829
10830testcase TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() runs on test_CT {
10831 var MSC_ConnHdlr vc_conn;
10832 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10833
10834 f_init(1, true);
10835 f_sleep(1.0);
10836 f_vty_allow_emerg_msc(true);
10837 f_vty_allow_emerg_bts(true, 0);
10838 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail), pars);
10839 vc_conn.done;
10840 f_shutdown_helper();
10841}
10842
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010843/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
10844private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
10845 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10846
10847 /* Also disable attach for the single connected MSC */
10848 f_vty_msc_allow_attach(BSCVTY, { false });
10849
10850 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) ));
10851 f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
10852
10853 /* No MSC is found, expecting a proper release on RSL */
10854 interleave {
10855 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
10856 f_logp(BSCVTY, "Got RSL RR Release");
10857 }
10858 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10859 f_logp(BSCVTY, "Got RSL Deact SACCH");
10860 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010861 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010862 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
10863 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010864 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010865 }
10866 }
10867 setverdict(pass);
10868}
10869testcase TC_no_msc() runs on test_CT {
10870
10871 f_init(1, true);
10872 f_sleep(1.0);
10873 var MSC_ConnHdlr vc_conn;
10874 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10875
10876 f_ctrs_bsc_init(counternames_bsc_mscpool);
10877
10878 vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
10879 vc_conn.done;
10880
10881 f_ctrs_bsc_add("mscpool:subscr:no_msc");
10882 f_ctrs_bsc_verify();
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010883 f_shutdown_helper();
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010884}
10885
Harald Welte0ea2d5e2018-04-07 21:40:29 +020010886/* Dyn PDCH todo:
10887 * activate OSMO as TCH/F
10888 * activate OSMO as TCH/H
10889 * does the BSC-located PCU socket get the updated INFO?
10890 * what if no PCU is connected at the time?
10891 * is the info correct on delayed PCU (re)connect?
10892 */
Harald Welte94e0c342018-04-07 11:33:23 +020010893
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010894private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +020010895 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020010896 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010897
10898 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
10899 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10900 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
10901 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
10902 g_pars.ass_codec_list.codecElements[0];
10903 if (isvalue(g_pars.expect_mr_s0_s7)) {
10904 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
10905 g_pars.expect_mr_s0_s7;
10906 }
10907 }
10908 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
10909 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
10910 log("expecting ASS COMPL like this: ", exp_compl);
10911
10912 f_establish_fully(ass_cmd, exp_compl);
10913
Neels Hofmeyr8746b0d2021-06-01 17:25:39 +020010914 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 +000010915
10916 var RSL_Message rsl;
10917
10918 timer T := 5.0;
10919 T.start;
10920 alt {
10921 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
10922 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
10923 log("Rx L3 from net: ", l3);
10924 if (ischosen(l3.msgs.rrm.channelModeModify)) {
10925 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10926 mtc.stop;
10927 }
10928 }
10929 [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
10930 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10931 mtc.stop;
10932 }
10933 [] T.timeout {
10934 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
10935 setverdict(pass);
10936 }
10937 }
10938 T.stop;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010939
10940 f_perform_clear();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010941}
10942
10943/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
10944 * osmo-bsc. */
10945testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
10946 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10947 var MSC_ConnHdlr vc_conn;
10948
10949 f_init(1, true);
10950 f_sleep(1.0);
10951
10952 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10953 vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
10954 vc_conn.done;
10955 f_shutdown_helper();
10956}
10957
10958/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
10959 */
10960testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
10961 f_init_vty();
10962
10963 f_init(1, false);
10964 f_sleep(1.0);
10965
10966 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
10967
10968 var ASP_RSL_Unitdata rx_rsl_ud;
10969 timer T := 5.0;
10970
10971 T.start;
10972 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010973 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010974 if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
10975 T.stop;
10976 setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
10977 mtc.stop;
10978 }
10979 repeat;
10980 }
10981 [] T.timeout {
10982 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
10983 setverdict(pass);
10984 }
10985 }
10986}
10987
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010988private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
10989 /* First fully set up a speech lchan */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010990 f_assignment_codec(id, do_perform_clear := false);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010991
10992 /* Trigger re-assignment to another lchan */
10993 var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
10994
10995 /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
10996 * one MDCX on MGCP. */
10997 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
10998
10999 /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
11000 * as the old lchan used. */
11001 g_media.bts.ipa_crcx_seen := false;
11002 g_media.bts.ipa_mdcx_seen := false;
11003
11004 /* Send different BTS side RTP port number for the new lchan */
11005 g_media.bts.bts.port_nr := 4223;
11006
11007 f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
11008
11009 /* Trigger re-assignment. */
11010 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
11011
11012 timer T := 5.0;
11013 T.start;
11014 alt {
11015 [] as_assignment(assignment_st);
11016 [] as_Media();
11017 [] T.timeout {
11018 break;
11019 }
11020 }
11021
11022 if (not assignment_st.assignment_done) {
11023 setverdict(fail, "Assignment did not complete");
11024 mtc.stop;
11025 }
11026
11027 f_check_mgcp_expectations()
11028 setverdict(pass);
11029
11030 f_sleep(2.0);
11031 log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
11032
11033 /* Instruct BSC to clear channel */
11034 var BssmapCause cause := 0;
11035 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
11036 interleave {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011037 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
11038 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020011039 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011040 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020011041 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011042 }
11043 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
11044 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11045 }
11046 }
Neels Hofmeyr40a45d12021-09-23 22:57:12 +020011047 f_expect_dlcx_conns();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011048
11049 f_sleep(0.5);
11050}
11051
11052testcase TC_reassignment_fr() runs on test_CT {
11053 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11054 var MSC_ConnHdlr vc_conn;
11055
11056 f_init(1, true);
11057 f_sleep(1.0);
11058
Neels Hofmeyrac432fa2021-11-02 16:45:56 +010011059 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011060
11061 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11062 vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
11063 vc_conn.done;
11064
11065 /* from f_establish_fully() */
11066 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
11067 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
11068 /* from re-assignment */
11069 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
11070 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
11071 f_ctrs_bsc_and_bts_verify();
11072 f_shutdown_helper();
11073}
11074
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011075const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
11076const charstring REEST_CLEAR := "REEST_CLEAR";
11077const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
11078
11079/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
11080 * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
11081 * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
11082 * the MSC as the CM Re-Establishment is handled.
11083 *
11084 * MS bts0 bts1 bsc msc test-component
11085 * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
11086 * | | _1 wait a bit, to settle down
11087 * |<-x x--| | _1 "lose connection"
11088 * | | REEST_LOST_CONNECTION
11089 * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
11090 * | | REEST_CLEAR
11091 * | |<-0---| _1 Clear Command on first A-conn
11092 * | |--0-->| _1 Clear Complete
11093 * | |<----------------->| | _1 Release first channel
11094 * | | REEST_CLEAR_DONE
11095 * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
11096 * |<-----------------|<-------|<-1---| _2 Clear Command, Release
11097 *
11098 */
11099private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
11100 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
11101 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11102
11103 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11104 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11105
11106 f_establish_fully(ass_cmd, exp_compl);
11107
11108 /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
11109 * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
11110 * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
11111 f_sleep(2.0);
11112 COORD.send(REEST_LOST_CONNECTION);
11113
11114 alt {
11115 [] COORD.receive(REEST_CLEAR);
11116 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
11117 setverdict(fail, "Unexpected channel release");
11118 mtc.stop;
11119 }
11120 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
11121 setverdict(fail, "Unexpected channel release");
11122 mtc.stop;
11123 }
11124 }
11125 f_perform_clear()
Neels Hofmeyr969abd02021-09-23 22:24:08 +020011126 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011127 COORD.send(REEST_CLEAR_DONE);
11128}
11129
11130private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
11131 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
11132
11133 /* The MS lost the connection on the first channel, now establishes another one */
11134 COORD.receive(REEST_LOST_CONNECTION);
11135
11136 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
11137 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
11138 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
11139
11140 f_create_bssmap_exp(l3_enc);
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011141 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 +020011142 BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
11143
11144 /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
11145 COORD.send(REEST_CLEAR);
11146 COORD.receive(REEST_CLEAR_DONE);
11147
11148 f_sleep(2.0);
11149
11150 /* Answer the CM Re-Establishment with an Assignment Command. */
11151 var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
11152 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11153 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11154 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11155
11156 var AssignmentState st := valueof(ts_AssignmentStateInit);
11157 st.voice_call := true;
11158 st.is_assignment := true;
11159
11160 var ExpectCriteria mgcpcrit := {
11161 connid := omit,
11162 endpoint := omit,
11163 transid := omit
11164 };
11165 f_create_mgcp_expect(mgcpcrit);
11166
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011167 f_rslem_dchan_queue_enable(RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011168
11169 BSSAP.send(ass_cmd);
11170
11171 var PDU_BSSAP bssap;
11172
11173 alt {
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011174 [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
11175 [] as_Media_ipacc(RSL1, RSL2);
11176 [] as_Media_mgw();
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011177 [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
11178 break;
11179 }
11180 }
11181
11182 f_sleep(3.0);
11183
11184 f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011185 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011186}
11187
11188testcase TC_cm_reestablishment() runs on test_CT {
11189 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
11190 var MSC_ConnHdlr vc_conn1;
11191
11192 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
11193 var MSC_ConnHdlr vc_conn2;
11194 pars2.imsi := pars1.imsi;
11195 pars2.media_nr := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011196 pars2.expect_tsc := c_BtsParams[1].tsc;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011197
11198 f_init(2, true, guard_timeout := 40.0);
11199 f_sleep(1.0);
11200
11201 vc_conn1 := f_start_handler_create(pars1);
11202 vc_conn2 := f_start_handler_create(pars2);
11203 connect(vc_conn1:COORD, vc_conn2:COORD);
11204 f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
11205 f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
11206 vc_conn1.done;
11207 vc_conn2.done;
11208
11209 f_shutdown_helper();
11210}
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011211
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011212function f_exp_ipa_rx_nonfatal(template (present) RSL_Message t_rx,
11213 boolean ignore_other_rx := true,
11214 BtsTrxIdx idx := {0, 0},
11215 float Tval := 2.0)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011216runs on test_CT return template (omit) RSL_Message {
11217 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011218 timer T := Tval;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011219
11220 T.start;
11221 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011222 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011223 T.stop;
11224 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011225 [ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
11226 [not ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011227 log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
11228 T.stop;
11229 return omit;
11230 }
11231 [] T.timeout {
11232 return omit;
11233 }
11234 }
11235 return rx_rsl_ud.rsl;
11236}
11237
11238private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
11239 f_vty_enter_cfg_bts(pt, bts_nr);
11240 f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
11241 f_vty_transceive(pt, "exit");
11242 f_vty_transceive(pt, "exit");
11243 f_vty_transceive(pt, "exit");
11244}
11245
11246private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +030011247 template (present) RslChannelNr chan_nr := ?,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011248 template (present) uint12_t arfcn := ?,
11249 template (present) uint3_t tsc := ?)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011250{
11251 var RSL_IE_Body full_imm_ass_info;
11252 if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
11253 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
11254 mtc.stop;
11255 }
11256
11257 var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
11258 var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
11259 fn := fn,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011260 ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011261 page_mode := ?);
11262 if (not match(rr_imm_ass, expect_imm_ass)) {
11263 log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
11264 setverdict(fail, "Failed to match Immediate Assignment");
11265 mtc.stop;
11266 }
11267}
11268
11269testcase TC_imm_ass_post_chan_ack() runs on test_CT {
11270 var RSL_Message chan_act;
11271 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011272 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011273
11274 f_init(1, false);
11275 f_sleep(1.0);
11276
11277 /* (should be the default anyway, just to make things clear) */
11278 f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
11279
11280 /* RA containing reason=LU */
11281 var GsmFrameNumber fn := 2342;
11282 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011283 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011284
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011285 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011286
11287 /* First send the Chan Act ACK */
11288 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011289 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011290 var RSL_IE_Body chan_ident_ie;
11291 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11292 setverdict(fail, "RSL Channel Identification IE is absent");
11293 mtc.stop;
11294 }
11295
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011296 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011297
11298 /* Then expect the Immediate Assignment, after we ACKed the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011299 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011300
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011301 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11302 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011303
11304 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011305 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011306
11307 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011308 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011309 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011310 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11311
11312 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011313 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011314 f_shutdown_helper();
11315}
11316
11317testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
11318 var RSL_Message chan_act;
11319 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011320 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011321
11322 f_init(1, false);
11323 f_sleep(1.0);
11324
11325 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11326
11327 /* RA containing reason=LU */
11328 var GsmFrameNumber fn := 2342;
11329 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011330 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011331
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011332 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011333 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011334 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011335 var RSL_IE_Body chan_ident_ie;
11336 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11337 setverdict(fail, "RSL Channel Identification IE is absent");
11338 mtc.stop;
11339 }
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011340
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011341 /* (set bts 0 cfg back to default) */
11342 f_vty_set_imm_ass(BSCVTY);
11343
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011344 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011345 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011346 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11347 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011348
11349 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011350 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011351
11352 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011353 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011354
11355 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011356 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011357 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011358 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11359
11360 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011361 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011362 f_shutdown_helper();
11363}
11364
Neels Hofmeyr23158742021-09-07 19:08:07 +020011365testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
11366 var RSL_Message chan_act;
11367 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011368 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr23158742021-09-07 19:08:07 +020011369
11370 f_init(1, false);
11371 f_sleep(1.0);
11372
11373 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11374
11375 /* RA containing reason=LU */
11376 var GsmFrameNumber fn := 2342;
11377 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011378 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011379
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011380 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011381 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011382 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr23158742021-09-07 19:08:07 +020011383 var RSL_IE_Body chan_ident_ie;
11384 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11385 setverdict(fail, "RSL Channel Identification IE is absent");
11386 mtc.stop;
11387 }
11388
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011389 /* (set bts 0 cfg back to default) */
11390 f_vty_set_imm_ass(BSCVTY);
11391
Neels Hofmeyr23158742021-09-07 19:08:07 +020011392 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011393 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011394 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11395 chan_ident_ie.chan_ident.ch_desc.v.tsc);
11396
11397 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011398 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011399
11400 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011401 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011402
11403 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011404 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011405 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr23158742021-09-07 19:08:07 +020011406 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11407
11408 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011409 f_perform_clear_test_ct(dt);
Neels Hofmeyr23158742021-09-07 19:08:07 +020011410 f_shutdown_helper();
11411}
11412
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011413testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
11414 /* change Timeslot 6 before f_init() starts RSL */
11415 f_init_vty();
11416 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11417 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11418
11419 f_init(1, false);
11420 f_sleep(1.0);
11421
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011422 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011423 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11424 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011425 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11426 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011427
11428 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11429 f_ts_set_chcomb(0, 0, 6, "PDCH");
11430
11431 /* block all static timeslots so that the dyn TS will be used */
11432 f_disable_all_tch_f();
11433 f_disable_all_tch_h();
11434 f_disable_all_sdcch();
11435
11436 var RSL_Message chan_act;
11437 var RSL_Message imm_ass;
11438
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011439 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11440
11441 /* RA containing reason=LU */
11442 var GsmFrameNumber fn := 2342;
11443 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011444 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011445
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011446 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011447 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
11448 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011449
11450 /* Now activation as SDCCH8 */
11451 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011452 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011453
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011454 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011455 var RSL_IE_Body chan_ident_ie;
11456 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11457 setverdict(fail, "RSL Channel Identification IE is absent");
11458 mtc.stop;
11459 }
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011460
11461 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011462 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011463 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11464 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011465
11466 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011467 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011468
11469 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011470 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011471
11472 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011473 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011474 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011475 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11476
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011477 /* (set bts 0 cfg back to default) */
11478 f_vty_set_imm_ass(BSCVTY);
11479
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011480 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011481 f_perform_clear_test_ct(dt);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011482 f_shutdown_helper();
11483}
11484
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011485testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
11486 /* change Timeslot 6 before f_init() starts RSL */
11487 f_init_vty();
11488 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11489 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11490
11491 f_init(1, false);
11492 f_sleep(1.0);
11493
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011494 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011495 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11496 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011497 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11498 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011499
11500 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11501 f_ts_set_chcomb(0, 0, 6, "PDCH");
11502
11503 /* block all static timeslots so that the dyn TS will be used */
11504 f_disable_all_tch_f();
11505 f_disable_all_tch_h();
11506 f_disable_all_sdcch();
11507
11508 var RSL_Message chan_act;
11509 var RSL_Message imm_ass;
11510
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011511 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11512
11513 /* RA containing reason=LU */
11514 var GsmFrameNumber fn := 2342;
11515 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011516 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011517
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011518 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011519 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011520
11521 /* And already the Immediate Assignment even before the PDCH Deact ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011522 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011523
11524 /* continue the Osmo style PDCH Deact (usual chan rel) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011525 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011526
11527 /* Now activation as SDCCH8 */
11528 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011529 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011530
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011531 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011532 var RSL_IE_Body chan_ident_ie;
11533 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11534 setverdict(fail, "RSL Channel Identification IE is absent");
11535 mtc.stop;
11536 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011537 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011538
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011539 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11540 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011541
11542 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011543 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011544
11545 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011546 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011547 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011548 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11549
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011550 /* (set bts 0 cfg back to default) */
11551 f_vty_set_imm_ass(BSCVTY);
11552
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011553 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011554 f_perform_clear_test_ct(dt);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011555 f_shutdown_helper();
11556}
11557
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011558/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
11559testcase TC_ctrl_trx_rf_locked() runs on test_CT {
11560 var MSC_ConnHdlr vc_conn;
11561
11562 f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
11563 f_sleep(1.0);
11564
11565 /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
11566 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11567 "0,0,operational,unlocked,on,rsl-up;" &
11568 "1,0,operational,unlocked,on,rsl-up;" &
11569 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011570 "2,1,operational,unlocked,on,rsl-down;" &
11571 "2,2,operational,unlocked,on,rsl-down;" &
11572 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011573 "3,0,inoperational,locked,on,rsl-down;");
11574
11575 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock BTS 1 TRX 0");
11576 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11577 /* give it a moment to settle the FSM status */
11578 f_sleep(1.0);
11579
11580 /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
11581 * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
11582 * of "off"? But that's for a future patch if at all. */
11583 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11584 "0,0,operational,unlocked,on,rsl-up;" &
11585 "1,0,operational,locked,on,rsl-up;" &
11586 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011587 "2,1,operational,unlocked,on,rsl-down;" &
11588 "2,2,operational,unlocked,on,rsl-down;" &
11589 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011590 "3,0,inoperational,locked,on,rsl-down;");
11591
11592 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
11593 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11594 f_sleep(1.0);
11595 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11596 "0,0,operational,unlocked,on,rsl-up;" &
11597 "1,0,operational,locked,on,rsl-up;" &
11598 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011599 "2,1,operational,unlocked,on,rsl-down;" &
11600 "2,2,operational,unlocked,on,rsl-down;" &
11601 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011602 "3,0,inoperational,locked,on,rsl-down;");
11603
11604 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
11605 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
11606 f_sleep(1.0);
11607 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11608 "0,0,operational,unlocked,on,rsl-up;" &
11609 "1,0,operational,unlocked,on,rsl-up;" &
11610 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011611 "2,1,operational,unlocked,on,rsl-down;" &
11612 "2,2,operational,unlocked,on,rsl-down;" &
11613 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011614 "3,0,inoperational,locked,on,rsl-down;");
11615
11616 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
11617 f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
11618 f_sleep(1.0);
11619 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11620 "0,0,operational,unlocked,on,rsl-up;" &
11621 "1,0,operational,unlocked,on,rsl-up;" &
11622 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011623 "2,1,operational,unlocked,on,rsl-down;" &
11624 "2,2,operational,unlocked,on,rsl-down;" &
11625 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011626 "3,0,inoperational,locked,on,rsl-down;");
11627
11628 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
11629 f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
11630 f_sleep(1.0);
11631 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11632 "0,0,operational,unlocked,on,rsl-up;" &
11633 "1,0,operational,unlocked,on,rsl-up;" &
11634 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011635 "2,1,operational,unlocked,on,rsl-down;" &
11636 "2,2,operational,unlocked,on,rsl-down;" &
11637 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011638 "3,0,inoperational,locked,on,rsl-down;");
11639
11640 f_shutdown_helper();
11641}
11642
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011643const CounterNameVals counternames_cm_serv_rej := {
11644 { "cm_serv_rej", 0 },
11645 { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
11646 { "cm_serv_rej:illegal_ms", 0 },
11647 { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
11648 { "cm_serv_rej:imei_not_accepted", 0 },
11649 { "cm_serv_rej:illegal_me", 0 },
11650 { "cm_serv_rej:plmn_not_allowed", 0 },
11651 { "cm_serv_rej:loc_not_allowed", 0 },
11652 { "cm_serv_rej:roaming_not_allowed", 0 },
11653 { "cm_serv_rej:network_failure", 0 },
11654 { "cm_serv_rej:synch_failure", 0 },
11655 { "cm_serv_rej:congestion", 0 },
11656 { "cm_serv_rej:srv_opt_not_supported", 0 },
11657 { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
11658 { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
11659 { "cm_serv_rej:call_can_not_be_identified", 0 },
11660 { "cm_serv_rej:incorrect_message", 0 },
11661 { "cm_serv_rej:invalid_mandantory_inf", 0 },
11662 { "cm_serv_rej:msg_type_not_implemented", 0 },
11663 { "cm_serv_rej:msg_type_not_compatible", 0 },
11664 { "cm_serv_rej:inf_eleme_not_implemented", 0 },
11665 { "cm_serv_rej:condtional_ie_error", 0 },
11666 { "cm_serv_rej:msg_not_compatible", 0 },
11667 { "cm_serv_rej:protocol_error", 0 },
11668 { "cm_serv_rej:retry_in_new_cell", 0 }
11669};
11670
11671private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
11672{
11673 f_create_chan_and_exp();
Vadim Yanitskiya7fc5a62021-12-04 20:10:08 +030011674 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011675 BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011676 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_CM_SERV_REJ));
11677 f_perform_clear();
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011678 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011679}
11680testcase TC_cm_serv_rej() runs on test_CT {
11681 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11682 var MSC_ConnHdlr vc_conn;
11683
11684 f_init(1, true);
11685 f_sleep(1.0);
11686
11687 f_ctrs_bts_init(1, counternames_cm_serv_rej);
11688
11689 vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
11690 vc_conn.done;
11691
11692 f_ctrs_bts_add(0, "cm_serv_rej", 1);
11693 f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
11694 f_ctrs_bts_verify();
11695
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011696 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011697 f_shutdown_helper();
11698}
11699
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011700/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
11701 * Activ Ack (SYS#5627). */
11702private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
11703 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Vadim Yanitskiyf0310e32021-10-26 00:30:59 +030011704
11705 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11706 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011707
11708 var BSSMAP_FIELD_CodecType codecType;
11709 codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
11710
11711 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
11712
11713 /* First establish a signalling lchan */
11714 f_create_chan_and_exp();
11715 f_rslem_dchan_queue_enable();
11716
11717 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011718
11719 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
Oliver Smith735b47c2023-02-15 16:03:54 +010011720 activate(as_Media_mgw());
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011721
11722 var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
11723 f_rslem_register(0, chan_nr);
11724
11725 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
11726 BSSAP.send(ass_cmd);
11727
11728
11729 /* Wait for the Channel Activ for the TCH channel */
11730 var ASP_RSL_Unitdata rx_rsl_ud;
11731 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
11732
11733 /* make the original SDCCH disappear */
11734 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
11735
11736 /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
11737 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
11738
11739 interleave {
11740 [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
11741 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
11742 }
11743
11744 BSSAP.send(ts_BSSMAP_ClearCommand(0));
11745 BSSAP.receive(tr_BSSMAP_ClearComplete);
11746 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11747
11748 var MgcpCommand mgcp;
Vadim Yanitskiy6be4cf42022-06-04 21:25:47 +060011749 var MGCP_RecvFrom mrf;
11750 var template MgcpMessage msg_dlcx := { command := tr_DLCX };
11751 alt {
11752 [g_pars.aoip] MGCP.receive(tr_DLCX) -> value mgcp {
11753 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
11754 }
11755 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
11756 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
11757 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
11758 }));
11759 }
11760 }
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011761
11762 f_sleep(0.5);
11763}
11764testcase TC_lost_sdcch_during_assignment() runs on test_CT {
11765 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11766 var MSC_ConnHdlr vc_conn;
11767
Oliver Smith735b47c2023-02-15 16:03:54 +010011768 pars.fail_on_dlcx := false;
11769
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011770 f_init(1, true);
11771 f_sleep(1.0);
11772
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011773 vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
11774 vc_conn.done;
11775
11776 f_shutdown_helper();
11777}
11778
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011779const CounterNameVals counternames_bsc_bts_all_available_allocated := {
11780 { "all_allocated:sdcch", 0 },
11781 { "all_allocated:static_sdcch", 0 },
11782 { "all_allocated:tch", 0 },
11783 { "all_allocated:static_tch", 0 }
11784}
11785
11786private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
11787{
11788 /* Make sure counters settle first */
11789 f_sleep(1.0);
11790
11791 /* Take a baseline of counters */
11792 f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
11793
11794 /* Elapse some time so that we see changes in counters, hopefully where expected */
11795 f_sleep(2.0);
11796
11797 /* Get new counters */
11798 var charstring_list all_changed := {};
11799 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
11800 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
11801
11802 /* Compare with expectations */
11803 var charstring_list all_expect_changed := {};
11804 for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
11805 all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
11806 }
11807 f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
11808}
11809
11810testcase TC_ratectr_all_available_allocated() runs on test_CT {
11811 var ASP_RSL_Unitdata rsl_ud;
11812 var integer i;
11813 var integer chreq_total, chreq_nochan;
11814
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011815 f_init(1, guard_timeout := 60.0);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011816 f_sleep(1.0);
11817
11818 /* Exhaust all dedicated SDCCH lchans.
11819 /* GSM 44.018 Table 9.1.8.2:
11820 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11821 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011822 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011823 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011824 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 +020011825 }
11826
11827 /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
11828 * level.
11829 * All SDCCH are now occupied. */
11830 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11831
11832 /* Also fill up all remaining (TCH) channels */
11833 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011834 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 +020011835 }
11836
11837 /* All TCH are now also occupied */
11838 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11839 "all_allocated:tch", "all_allocated:static_tch"});
11840
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011841 /* Clean up SDCCH lchans */
11842 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11843 f_perform_clear_test_ct(chan_cleanup[i]);
11844 }
11845
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011846 f_shutdown_helper();
11847}
11848
11849testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
11850 var ASP_RSL_Unitdata rsl_ud;
11851 var integer i;
11852 var integer chreq_total, chreq_nochan;
11853
11854 f_init_vty();
11855 f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
11856 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11857 /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
11858
11859 f_init(1, guard_timeout := 60.0);
11860 f_sleep(1.0);
11861
11862 /* The dyn TS wants to activate PDCH mode, ACK that. */
11863 var RslChannelNr chan_nr;
11864 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011865 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11866 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011867
11868 /* Exhaust all dedicated SDCCH lchans.
11869 /* GSM 44.018 Table 9.1.8.2:
11870 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11871 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011872 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011873 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011874 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 +020011875 }
11876
11877 /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
11878 * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
11879 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
11880
11881 /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
11882 * Will release them later, so remember all the DchanTuples. */
11883 var DchanTuples dyn_sddch := {};
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011884 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 +020011885
11886 /* Also occupy the seven other SDCCH of the dyn TS */
11887 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011888 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 +020011889 }
11890
11891 /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
11892 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11893
11894 /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
11895 for (i := 0; i < 5; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011896 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 +020011897 }
11898
11899 /* All TCH lchans are now also occupied, both static and dynamic */
11900 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11901 "all_allocated:tch", "all_allocated:static_tch"});
11902
11903 /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
11904 * incrementing. */
11905 var BssmapCause cause := 0;
11906 var DchanTuple dt := dyn_sddch[0];
11907 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011908 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011909
11910 /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
11911 * count as occupied, so those still both increment. */
11912 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
11913 "all_allocated:tch", "all_allocated:static_tch"});
11914
11915 /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
11916 for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
11917 dt := dyn_sddch[i];
11918 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011919 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011920 }
11921
11922 /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
11923 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011924 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11925 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011926
11927 /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
11928 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
11929
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011930 /* Clean up SDCCH lchans */
11931 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11932 f_perform_clear_test_ct(chan_cleanup[i]);
11933 }
11934
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011935 /* clean up config */
11936 f_ts_reset_chcomb(0);
11937
11938 f_shutdown_helper();
11939}
11940
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011941private function f_TC_chan_alloc_algo(DchanTuple dt, BtsTrxIdx idx)
11942runs on test_CT {
11943 /* MSC sends an Assignment Request */
11944 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11945 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11946 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11947 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
11948
11949 /* Expect the BSC to allocate a TCH channel on the given BTS/TRX */
11950 var RSL_Message rsl_chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
11951 /* Send CHAN ACT NACK, so that the requested TCH channel becomes BORKEN */
11952 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(rsl_chan_act.ies[0].body.chan_nr, RSL_ERR_EQUIPMENT_FAIL), idx);
11953 /* Expect to receive an Assignment Failure */
11954 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail));
11955}
11956
11957testcase TC_chan_alloc_algo_ascending() runs on test_CT {
11958 /* We need to access BTS2, which has 4 TRXs */
11959 f_init(nr_bts := 3);
11960
11961 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020011962 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011963
11964 f_vty_enter_cfg_bts(BSCVTY, 2);
11965 f_vty_transceive(BSCVTY, "channel allocator ascending");
11966 f_vty_transceive(BSCVTY, "end");
11967
11968 /* Expect the BSC to allocate 4 x TCH/F channels on BTS2/TRX0 */
11969 for (var integer i := 0; i < 4; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011970 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011971 f_TC_chan_alloc_algo(dt, {2, 0});
11972 f_perform_clear_test_ct(dt);
11973 }
11974
11975 /* At this point all 4 x TCH/F channels are BORKEN, but they will be
11976 * resurrected upon the A-bis/OML link re-establishment. */
11977 f_shutdown_helper();
11978}
11979
11980testcase TC_chan_alloc_algo_descending() runs on test_CT {
11981 /* We need to access BTS2, which has 4 TRXs */
11982 f_init(nr_bts := 3);
11983
11984 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020011985 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011986
11987 f_vty_enter_cfg_bts(BSCVTY, 2);
11988 f_vty_transceive(BSCVTY, "channel allocator descending");
11989 f_vty_transceive(BSCVTY, "end");
11990
11991 /* Expect the BSC to allocate 5 x TCH/F channels on BTS2/TRX3 */
11992 for (var integer i := 0; i < 5; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011993 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011994 f_TC_chan_alloc_algo(dt, {2, 3});
11995 f_perform_clear_test_ct(dt);
11996 }
11997
11998 /* At this point all 5 x TCH/F channels are BORKEN, but they will be
11999 * resurrected upon the A-bis/OML link re-establishment. */
12000 f_shutdown_helper();
12001}
12002
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012003testcase TC_chan_alloc_algo_ass_dynamic() runs on test_CT {
12004 const BtsTrxIdx TRX0 := {2, 0};
12005 const BtsTrxIdx TRX3 := {2, 3};
12006
12007 /* We need to access BTS2, which has 4 TRXs */
12008 f_init(nr_bts := 3);
12009
12010 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012011 vc_MGCP[0].stop;
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012012
12013 f_vty_enter_cfg_bts(BSCVTY, 2);
12014 f_vty_transceive(BSCVTY, "channel allocator mode assignment dynamic");
12015 f_vty_transceive(BSCVTY, "channel allocator dynamic-param ul-rxlev thresh 50 avg-num 2");
12016 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 0");
12017 f_vty_transceive(BSCVTY, "end");
12018
12019 var DchanTuple dt;
12020
12021 f_logp(BSCVTY, "Case a) Unknown Uplink RxLev, fall-back to ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012022 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012023 f_TC_chan_alloc_algo(dt, TRX0);
12024 f_perform_clear_test_ct(dt);
12025
12026 f_logp(BSCVTY, "Case b) Not enough RxLev samples, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012027 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012028 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12029 ts_RSL_IE_UplinkMeas(30, 0),
12030 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012031 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012032 f_TC_chan_alloc_algo(dt, TRX0);
12033 f_perform_clear_test_ct(dt);
12034
12035 f_logp(BSCVTY, "Case c) Uplink RxLev below the threshold, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012036 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012037 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12038 ts_RSL_IE_UplinkMeas(45, 0),
12039 ts_RSL_IE_BS_Power(0)), TRX0);
12040 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12041 ts_RSL_IE_UplinkMeas(48, 0),
12042 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012043 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012044 f_TC_chan_alloc_algo(dt, TRX0);
12045 f_perform_clear_test_ct(dt);
12046
12047 f_logp(BSCVTY, "Case d) Uplink RxLev above the threshold, use descending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012048 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012049 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12050 ts_RSL_IE_UplinkMeas(50, 0),
12051 ts_RSL_IE_BS_Power(0)), TRX0);
12052 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12053 ts_RSL_IE_UplinkMeas(58, 0),
12054 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012055 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012056 f_TC_chan_alloc_algo(dt, TRX3);
12057 f_perform_clear_test_ct(dt);
12058
12059 f_vty_enter_cfg_bts(BSCVTY, 2);
12060 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 90");
12061 f_vty_transceive(BSCVTY, "end");
12062
12063 f_logp(BSCVTY, "Case e) Uplink RxLev above the threshold, but C0 load is not");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012064 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012065 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12066 ts_RSL_IE_UplinkMeas(50, 0),
12067 ts_RSL_IE_BS_Power(0)), TRX0);
12068 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12069 ts_RSL_IE_UplinkMeas(58, 0),
12070 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012071 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012072 f_TC_chan_alloc_algo(dt, TRX0);
12073 f_perform_clear_test_ct(dt);
12074
12075 f_vty_enter_cfg_bts(BSCVTY, 2);
12076 f_vty_transceive(BSCVTY, "channel allocator ascending");
12077 f_vty_transceive(BSCVTY, "end");
12078
12079 /* At this point some TCH/F channels are BORKEN, but they will be
12080 * resurrected upon the A-bis/OML link re-establishment. */
12081 f_shutdown_helper();
12082}
12083
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012084private function f_vty_mgw_enable(integer mgw_nr := 1) runs on test_CT {
12085 var rof_charstring cmds := {
12086 "remote-ip " & mp_test_ip,
12087 "remote-port " & int2str(2427 + mgw_nr)
12088 };
12089 f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
12090 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " reconnect")
12091}
12092private function f_vty_mgw_disable(integer mgw_nr := 1) runs on test_CT {
12093 f_vty_config3(BSCVTY, {"network"}, { "no mgw " &int2str(mgw_nr) });
12094}
12095private function f_vty_mgw_block(integer mgw_nr := 1, boolean blocked := true) runs on test_CT {
12096 var charstring arg;
12097 if (blocked) {
12098 arg := "block";
12099 } else {
12100 arg := "unblock";
12101 }
12102 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " " & arg);
12103}
12104private const charstring COORD_CMD_ESTABLISHED := "COORD_CMD_ESTABLISHED";
12105private function f_TC_mgwpool_call_seq_1(charstring id) runs on MSC_ConnHdlr {
12106 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12107 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12108 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12109 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12110
12111 f_establish_fully(ass_cmd, exp_compl);
12112 COORD.send(COORD_CMD_ESTABLISHED);
12113
12114 COORD.receive(COORD_CMD_ESTABLISHED);
12115 f_perform_clear()
12116 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12117}
12118private function f_TC_mgwpool_call_seq_2(charstring id) runs on MSC_ConnHdlr {
12119 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12120 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12121 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12122 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12123
12124
12125 COORD.receive(COORD_CMD_ESTABLISHED);
12126 f_establish_fully(ass_cmd, exp_compl);
12127 COORD.send(COORD_CMD_ESTABLISHED);
12128
12129 f_perform_clear()
12130 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12131}
12132/* Test load is spread around 2 available MGWs */
12133testcase TC_mgwpool_all_used() runs on test_CT {
12134 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12135 var MSC_ConnHdlr vc_conn1;
12136 pars1.mgwpool_idx := 0;
12137
12138 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12139 var MSC_ConnHdlr vc_conn2;
12140 pars2.mgwpool_idx := 1;
12141
12142 f_init(1, true, nr_mgw := 2);
12143 f_sleep(1.0);
12144
12145 f_vty_mgw_enable(1);
12146
12147 vc_conn1 := f_start_handler_create(pars1);
12148 vc_conn2 := f_start_handler_create(pars2);
12149 connect(vc_conn1:COORD, vc_conn2:COORD);
12150 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12151 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12152 vc_conn1.done;
12153 vc_conn2.done;
12154
12155 f_vty_mgw_disable(1);
12156
12157 f_shutdown_helper();
12158}
12159
12160/* Test blocked MGW in the pool are not selected */
12161testcase TC_mgwpool_blocked_not_used() runs on test_CT {
12162 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12163 var MSC_ConnHdlr vc_conn1;
12164 pars1.mgwpool_idx := 0;
12165
12166 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12167 var MSC_ConnHdlr vc_conn2;
12168 pars2.mgwpool_idx := 0; /* expect it in the first one, since the second will be blocked */
12169 pars2.media_nr := 2;
12170
12171 f_init(1, true, nr_mgw := 2);
12172 f_sleep(1.0);
12173
12174 f_vty_mgw_enable(1);
12175 f_vty_mgw_block(1, true);
12176
12177 vc_conn1 := f_start_handler_create(pars1);
12178 vc_conn2 := f_start_handler_create(pars2);
12179 connect(vc_conn1:COORD, vc_conn2:COORD);
12180 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12181 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12182 vc_conn1.done;
12183 vc_conn2.done;
12184
12185 f_vty_mgw_disable(1);
12186
12187 f_shutdown_helper();
12188}
12189
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012190/* Test BTS pinning to an MGW is applied */
12191testcase TC_mgwpool_pin_bts() runs on test_CT {
12192 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12193 var MSC_ConnHdlr vc_conn1;
12194 pars1.mgwpool_idx := 0;
12195
12196 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12197 var MSC_ConnHdlr vc_conn2;
12198 pars2.mgwpool_idx := 0; /* expect it in the first one, since the BTS is pinned to the first MGW */
12199 pars2.media_nr := 2;
12200
12201 f_init(1, true, nr_mgw := 2);
12202 f_sleep(1.0);
12203
12204 f_vty_mgw_enable(1);
12205 f_vty_cfg_bts(BSCVTY, 0, { "mgw pool-target 0" });
12206
12207 vc_conn1 := f_start_handler_create(pars1);
12208 vc_conn2 := f_start_handler_create(pars2);
12209 connect(vc_conn1:COORD, vc_conn2:COORD);
12210 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12211 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12212 vc_conn1.done;
12213 vc_conn2.done;
12214
12215 f_vty_cfg_bts(BSCVTY, 0, { "no mgw pool-target" } );
Vadim Yanitskiy389d7e02022-10-25 17:44:05 +070012216 f_vty_mgw_disable(1);
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012217
12218 f_shutdown_helper();
12219}
12220
Oliver Smithc9a5f532022-10-21 11:32:23 +020012221private function f_tc_ho_meas_rep_multi_band(charstring id) runs on MSC_ConnHdlr {
12222 g_pars := f_gen_test_hdlr_pars();
12223 var PDU_BSSAP ass_req := f_gen_ass_req();
12224 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12225 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12226 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12227 f_establish_fully(ass_req, exp_compl);
12228
12229 /* Send a measurement report with bad rxlev except on 3rd entry. The
12230 * measurement report is divided into two sub lists, as described in
12231 * 3GPP TS 04.08 § 10.5.2.20. */
12232 var NcellReports neighbor_rep := {
12233 /* Sub list 1: same band */
Oliver Smitha6773042022-10-24 12:56:30 +020012234 { rxlev := 0, bcch_freq := 0, bsic := 12 }, /* ARFCN 800, band 1800, LAC 98 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012235 /* Sub list 2: different band */
Oliver Smitha6773042022-10-24 12:56:30 +020012236 { rxlev := 0, bcch_freq := 1, bsic := 13 }, /* ARFCN 200, band 850, LAC 97 */
12237 { rxlev := 40, bcch_freq := 2, bsic := 14 }, /* ARFCN 1000, band 900, LAC 99 */
12238 { rxlev := 0, bcch_freq := 3, bsic := 11 } /* ARFCN 0, band 900, LAC 96 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012239 };
12240 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
12241 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
12242 l3_mr, 0));
12243
12244 /* Expect a handover to the third entry. If the BSC parsed the report
Oliver Smitha6773042022-10-24 12:56:30 +020012245 * correctly, the third entry has LAC 99. */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012246 var template BSSMAP_FIELD_CellIdentificationList cid_list := {
Oliver Smitha6773042022-10-24 12:56:30 +020012247 cIl_LAC := { ts_BSSMAP_CI_LAC(99) }
Oliver Smithc9a5f532022-10-21 11:32:23 +020012248 };
12249 alt {
12250 [] BSSAP.receive(tr_BSSMAP_HandoverRequired(cid_list := cid_list)) {
12251 setverdict(pass);
12252 }
12253 [] BSSAP.receive(tr_BSSMAP_HandoverRequired()) {
12254 setverdict(fail, "Handover has unexpected LAC in Cell Identification List. The BSC probably"
12255 & " didn't parse the multi-band measurement report correctly.");
12256 }
12257 }
12258
12259 f_ho_out_of_this_bsc(skip_meas_rep := true);
12260}
12261testcase TC_ho_meas_rep_multi_band() runs on test_CT {
12262 /* Verify that the BSC parses the measurement report correctly when
12263 * neighbors in multiple bands are configured (OS#5717). See
12264 * gsm_arfcn2band_rc() in libosmocore src/gsm/gsm_utils.c for the
12265 * ARFCN -> band mapping. The MS is connected to band 1800. */
12266 var MSC_ConnHdlr vc_conn;
12267
12268 f_init_vty();
12269 f_bts_0_cfg(BSCVTY,
12270 {"neighbor-list mode automatic",
12271 "handover 1",
12272 "handover algorithm 2",
12273 "handover2 window rxlev averaging 1",
12274 "no neighbors",
12275 "neighbor lac 99 arfcn 1000 bsic any", /* band 900 */
12276 "neighbor lac 98 arfcn 800 bsic any", /* band 1800 */
12277 "neighbor lac 97 arfcn 200 bsic any", /* band 850 */
Oliver Smitha6773042022-10-24 12:56:30 +020012278 "neighbor lac 96 arfcn 0 bsic any"}); /* band 900 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012279 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
12280
12281 f_init(1, true);
12282 f_sleep(1.0);
12283
12284 f_ctrs_bsc_and_bts_handover_init();
12285
12286 vc_conn := f_start_handler(refers(f_tc_ho_meas_rep_multi_band));
12287 vc_conn.done;
12288
12289 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
12290 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
12291 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
12292 f_ctrs_bsc_and_bts_add(0, "handover:completed");
12293 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
12294 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
12295 f_ctrs_bsc_and_bts_verify();
12296 f_shutdown_helper(ho := true);
12297}
12298
Harald Welte28d943e2017-11-25 15:00:50 +010012299control {
Harald Welte898113b2018-01-31 18:32:21 +010012300 /* CTRL interface testing */
Harald Welte4003d112017-12-09 22:35:39 +010012301 execute( TC_ctrl_msc_connection_status() );
Stefan Sperlingb041b3d2018-01-03 17:14:55 +010012302 execute( TC_ctrl_msc0_connection_status() );
Neels Hofmeyrf65ce872021-09-23 18:40:10 +020012303 /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
12304 * these in the AoIP test suite. */
12305 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12306 execute( TC_stat_num_msc_connected_1() );
12307 execute( TC_stat_num_msc_connected_2() );
12308 execute( TC_stat_num_msc_connected_3() );
12309 }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020012310 execute( TC_stat_num_bts_connected_1() );
12311 execute( TC_stat_num_bts_connected_2() );
12312 execute( TC_stat_num_bts_connected_3() );
Harald Welte96c94412017-12-09 03:12:45 +010012313 execute( TC_ctrl() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012314 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +020012315 execute( TC_ctrl_location() );
12316 }
Harald Welte898113b2018-01-31 18:32:21 +010012317
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012318 execute( TC_si_default() );
Neels Hofmeyr66aeba42020-07-06 02:21:21 +020012319 execute( TC_si2quater_2_earfcns() );
12320 execute( TC_si2quater_3_earfcns() );
12321 execute( TC_si2quater_4_earfcns() );
12322 execute( TC_si2quater_5_earfcns() );
12323 execute( TC_si2quater_6_earfcns() );
Neels Hofmeyrad132f22020-07-08 02:20:16 +020012324 execute( TC_si2quater_12_earfcns() );
12325 execute( TC_si2quater_23_earfcns() );
12326 execute( TC_si2quater_32_earfcns() );
12327 execute( TC_si2quater_33_earfcns() );
12328 execute( TC_si2quater_42_earfcns() );
12329 execute( TC_si2quater_48_earfcns() );
12330 execute( TC_si2quater_49_earfcns() );
Pau Espin Pedrol85a84432020-07-20 18:45:03 +020012331 execute( TC_si_acc_rotate() );
Alexander Couzens4ad3a352020-09-10 22:29:12 +020012332 execute( TC_si_acc_ramp_rotate() );
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012333
Harald Welte898113b2018-01-31 18:32:21 +010012334 /* RSL DCHAN Channel ACtivation / Deactivation */
Harald Welteae026692017-12-09 01:03:01 +010012335 execute( TC_chan_act_noreply() );
Harald Welte4003d112017-12-09 22:35:39 +010012336 execute( TC_chan_act_counter() );
Harald Welteae026692017-12-09 01:03:01 +010012337 execute( TC_chan_act_ack_noest() );
Philipp Maier9c60a622020-07-09 15:08:46 +020012338 execute( TC_chan_act_ack_noest_emerg() );
Philipp Maier606f07d2020-08-12 17:21:58 +020012339 execute( TC_chan_rqd_emerg_deny() );
Harald Welteae026692017-12-09 01:03:01 +010012340 execute( TC_chan_act_ack_est_ind_noreply() );
12341 execute( TC_chan_act_ack_est_ind_refused() );
Harald Welte618ef642017-12-14 14:58:20 +010012342 execute( TC_chan_act_nack() );
Harald Welte799c97b2017-12-14 17:50:30 +010012343 execute( TC_chan_exhaustion() );
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +070012344 execute( TC_chan_deact_silence() );
Harald Welte4003d112017-12-09 22:35:39 +010012345 execute( TC_chan_rel_rll_rel_ind() );
12346 execute( TC_chan_rel_conn_fail() );
12347 execute( TC_chan_rel_hard_clear() );
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +020012348 execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
12349 execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
Harald Welte99787102019-02-04 10:41:36 +010012350 execute( TC_chan_rel_hard_clear_csfb() );
Harald Welted8c36cd2017-12-09 23:05:31 +010012351 execute( TC_chan_rel_hard_rlsd() );
Harald Welte550daf92018-06-11 19:22:13 +020012352 execute( TC_chan_rel_hard_rlsd_ms_dead() );
Harald Welte85804d42017-12-10 14:11:58 +010012353 execute( TC_chan_rel_a_reset() );
Pau Espin Pedrolc675b612020-01-09 19:55:40 +010012354 execute( TC_chan_rel_sccp_tiar_timeout() );
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +020012355 execute( TC_chan_rel_rr_cause() );
Harald Welte6f521d82017-12-11 19:52:02 +010012356
Harald Weltecfe2c962017-12-15 12:09:32 +010012357 execute( TC_outbound_connect() );
Harald Welte898113b2018-01-31 18:32:21 +010012358
12359 /* Assignment related */
Harald Welte16a4adf2017-12-14 18:54:01 +010012360 execute( TC_assignment_cic_only() );
Harald Welte235ebf12017-12-15 14:18:16 +010012361 execute( TC_assignment_csd() );
12362 execute( TC_assignment_ctm() );
12363 execute( TC_assignment_sign() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012364 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12365 execute( TC_assignment_aoip_tla_v6() );
12366 }
Harald Welte235ebf12017-12-15 14:18:16 +010012367 execute( TC_assignment_fr_a5_0() );
12368 execute( TC_assignment_fr_a5_1() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012369 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte8f67d1d2018-05-25 20:38:42 +020012370 execute( TC_assignment_fr_a5_1_codec_missing() );
12371 }
Harald Welte235ebf12017-12-15 14:18:16 +010012372 execute( TC_assignment_fr_a5_3() );
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +020012373 execute( TC_assignment_fr_a5_4() );
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +020012374 execute( TC_assignment_fr_a5_4_fail() );
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +020012375 execute( TC_assignment_fr_a5_not_sup() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012376 execute( TC_ciph_mode_a5_0() );
12377 execute( TC_ciph_mode_a5_1() );
Oliver Smith50b98122021-07-09 15:00:28 +020012378 execute( TC_ciph_mode_a5_2_0() );
Oliver Smith1dff88d2021-07-09 08:45:51 +020012379 execute( TC_ciph_mode_a5_2_1() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012380 execute( TC_ciph_mode_a5_3() );
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +020012381 execute( TC_ciph_mode_a5_4() );
Harald Welte16a4adf2017-12-14 18:54:01 +010012382
Harald Welte60aa5762018-03-21 19:33:13 +010012383 execute( TC_assignment_codec_fr() );
Neels Hofmeyr559d5d02021-04-16 16:50:49 +020012384 execute( TC_assignment_codec_fr_by_mode_modify() );
Harald Welte60aa5762018-03-21 19:33:13 +010012385 execute( TC_assignment_codec_hr() );
12386 execute( TC_assignment_codec_efr() );
12387 execute( TC_assignment_codec_amr_f() );
12388 execute( TC_assignment_codec_amr_h() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012389
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012390 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier8a581d22019-03-26 18:32:48 +010012391 execute( TC_assignment_codec_amr_f_S1() );
12392 execute( TC_assignment_codec_amr_h_S1() );
12393 execute( TC_assignment_codec_amr_f_S124() );
12394 execute( TC_assignment_codec_amr_h_S124() );
12395 execute( TC_assignment_codec_amr_f_S0() );
12396 execute( TC_assignment_codec_amr_f_S02() );
12397 execute( TC_assignment_codec_amr_f_S024() );
12398 execute( TC_assignment_codec_amr_f_S0247() );
12399 execute( TC_assignment_codec_amr_h_S0() );
12400 execute( TC_assignment_codec_amr_h_S02() );
12401 execute( TC_assignment_codec_amr_h_S024() );
12402 execute( TC_assignment_codec_amr_h_S0247() );
12403 execute( TC_assignment_codec_amr_f_S01234567() );
12404 execute( TC_assignment_codec_amr_f_S0234567() );
12405 execute( TC_assignment_codec_amr_f_zero() );
12406 execute( TC_assignment_codec_amr_f_unsupp() );
12407 execute( TC_assignment_codec_amr_h_S7() );
Neels Hofmeyr21863562020-11-26 00:34:33 +000012408 execute( TC_assignment_codec_amr_f_start_mode_auto() );
12409 execute( TC_assignment_codec_amr_h_start_mode_auto() );
Neels Hofmeyr3eb94562020-11-26 02:40:26 +000012410 execute( TC_assignment_codec_amr_f_start_mode_4() );
12411 execute( TC_assignment_codec_amr_h_start_mode_4() );
Neels Hofmeyr454d7922020-11-26 02:24:57 +000012412 execute( TC_assignment_codec_amr_startmode_cruft() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012413 }
Harald Welte60aa5762018-03-21 19:33:13 +010012414
Philipp Maierac09bfc2019-01-08 13:41:39 +010012415 execute( TC_assignment_codec_fr_exhausted_req_hr() );
12416 execute( TC_assignment_codec_fr_exhausted_req_fr() );
12417 execute( TC_assignment_codec_fr_exhausted_req_fr_hr() );
12418 execute( TC_assignment_codec_fr_exhausted_req_hr_fr() );
12419 execute( TC_assignment_codec_hr_exhausted_req_fr() );
12420 execute( TC_assignment_codec_hr_exhausted_req_hr() );
12421 execute( TC_assignment_codec_hr_exhausted_req_hr_fr() );
12422 execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
12423 execute( TC_assignment_codec_req_hr_fr() );
12424 execute( TC_assignment_codec_req_fr_hr() );
Pau Espin Pedrol14475352021-07-22 15:48:16 +020012425 execute( TC_assignment_sdcch_exhausted_req_signalling() );
12426 execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
12427 execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
Philipp Maierac09bfc2019-01-08 13:41:39 +010012428
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +020012429 execute( TC_assignment_codec_hr_osmux_on() );
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +020012430 execute( TC_assignment_osmux() );
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020012431 execute( TC_assignment_osmux_cn() );
12432 execute( TC_assignment_osmux_bts() );
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +020012433
Harald Welte898113b2018-01-31 18:32:21 +010012434 /* RLL Establish Indication on inactive DCHAN / SAPI */
Harald Welte5cd20ed2017-12-13 21:03:20 +010012435 execute( TC_rll_est_ind_inact_lchan() );
12436 execute( TC_rll_est_ind_inval_sapi1() );
12437 execute( TC_rll_est_ind_inval_sapi3() );
12438 execute( TC_rll_est_ind_inval_sacch() );
12439
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +070012440 /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
12441 execute( TC_tch_dlci_link_id_sapi() );
12442
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012443 /* SAPI N Reject triggered by RLL establishment failures */
12444 execute( TC_rll_rel_ind_sapi_n_reject() );
12445 execute( TC_rll_err_ind_sapi_n_reject() );
12446 execute( TC_rll_timeout_sapi_n_reject() );
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +070012447 execute( TC_rll_sapi_n_reject_dlci_cc() );
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012448
Harald Welte898113b2018-01-31 18:32:21 +010012449 /* Paging related tests */
Harald Welte6f521d82017-12-11 19:52:02 +010012450 execute( TC_paging_imsi_nochan() );
12451 execute( TC_paging_tmsi_nochan() );
12452 execute( TC_paging_tmsi_any() );
12453 execute( TC_paging_tmsi_sdcch() );
12454 execute( TC_paging_tmsi_tch_f() );
12455 execute( TC_paging_tmsi_tch_hf() );
12456 execute( TC_paging_imsi_nochan_cgi() );
12457 execute( TC_paging_imsi_nochan_lac_ci() );
12458 execute( TC_paging_imsi_nochan_ci() );
12459 execute( TC_paging_imsi_nochan_lai() );
12460 execute( TC_paging_imsi_nochan_lac() );
12461 execute( TC_paging_imsi_nochan_all() );
Harald Welte751d3eb2018-01-31 15:51:06 +010012462 execute( TC_paging_imsi_nochan_plmn_lac_rnc() );
12463 execute( TC_paging_imsi_nochan_rnc() );
12464 execute( TC_paging_imsi_nochan_lac_rnc() );
12465 execute( TC_paging_imsi_nochan_lacs() );
12466 execute( TC_paging_imsi_nochan_lacs_empty() );
Stefan Sperling049a86e2018-03-20 15:51:00 +010012467 execute( TC_paging_imsi_nochan_cgi_unknown_cid() );
Harald Welte10985002017-12-12 09:29:15 +010012468 execute( TC_paging_imsi_a_reset() );
Harald Weltee65d40e2017-12-13 00:09:06 +010012469 execute( TC_paging_imsi_load() );
Philipp Maier779a7922018-02-16 11:00:37 +010012470 execute( TC_paging_counter() );
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +010012471 execute( TC_paging_resp_unsol() );
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +020012472 execute( TC_paging_500req() );
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +020012473 execute( TC_paging_450req_no_paging_load_ind() );
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +010012474 execute( TC_paging_imsi_nochan_ci_resp_invalid_mi() );
Harald Welte4e9b9cc2017-12-14 18:31:02 +010012475
12476 execute( TC_rsl_drop_counter() );
Stefan Sperling830dc9d2018-02-12 21:08:28 +010012477 execute( TC_rsl_unknown_unit_id() );
12478
12479 execute( TC_oml_unknown_unit_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012480
12481 execute( TC_classmark() );
Harald Welteeddf0e92020-06-21 19:42:15 +020012482 execute( TC_common_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012483 execute( TC_unsol_ass_fail() );
Harald Welteea99a002018-01-31 20:46:43 +010012484 execute( TC_unsol_ass_compl() );
Harald Weltefbf9b5e2018-01-31 20:41:23 +010012485 execute( TC_unsol_ho_fail() );
Harald Weltee3bd6582018-01-31 22:51:25 +010012486 execute( TC_err_82_short_msg() );
Harald Weltee9e02e42018-01-31 23:36:25 +010012487 execute( TC_err_84_unknown_msg() );
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012488
Harald Welte261af4b2018-02-12 21:20:39 +010012489 execute( TC_ho_int() );
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +020012490 execute( TC_ho_int_a5_0() );
12491 execute( TC_ho_int_a5_1() );
12492 execute( TC_ho_int_a5_3() );
12493 execute( TC_ho_int_a5_4() );
Neels Hofmeyr5f144212020-11-03 15:41:58 +000012494 execute( TC_ho_int_radio_link_failure() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012495
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012496 /* TC_ho_out_of_this_bsc is run last, see comment below */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +020012497 execute( TC_ho_out_fail_no_msc_response() );
12498 execute( TC_ho_out_fail_rr_ho_failure() );
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +020012499 execute( TC_ho_out_fail_no_result_after_ho_cmd() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012500
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012501 execute( TC_ho_into_this_bsc() );
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +020012502 execute( TC_ho_into_this_bsc_a5_0() );
12503 execute( TC_ho_into_this_bsc_a5_1() );
12504 execute( TC_ho_into_this_bsc_a5_3() );
12505 execute( TC_ho_into_this_bsc_a5_4() );
Neels Hofmeyr93182e02022-02-17 21:59:07 +010012506 execute( TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() );
12507 execute( TC_ho_into_this_bsc_a5_1_3() );
Neels Hofmeyr907b23b2022-02-17 21:58:47 +010012508 execute( TC_ho_into_this_bsc_a5_mismatch() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012509 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12510 execute( TC_ho_into_this_bsc_tla_v6() );
12511 }
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +020012512 execute( TC_srvcc_eutran_to_geran() );
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +030012513 execute( TC_srvcc_eutran_to_geran_a5_3() );
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +010012514 execute( TC_srvcc_eutran_to_geran_src_sai() );
Pau Espin Pedrol35801c32021-04-19 13:03:20 +020012515 execute( TC_srvcc_eutran_to_geran_ho_out() );
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +020012516 execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
12517 execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012518 execute( TC_ho_in_fail_msc_clears() );
12519 execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
12520 execute( TC_ho_in_fail_no_detect() );
12521 execute( TC_ho_in_fail_no_detect2() );
Oliver Smith7a8594a2023-02-13 14:30:49 +010012522 execute( TC_ho_in_fail_mgw_mdcx_timeout() );
Oliver Smith4eed06f2023-02-15 15:43:19 +010012523 execute( TC_ho_in_fail_ipa_crcx_timeout() );
Neels Hofmeyra23f3b12022-03-02 19:57:12 +010012524 execute( TC_ho_into_this_bsc_sccp_cr_without_bssap() );
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012525
Neels Hofmeyr91401012019-07-11 00:42:35 +020012526 execute( TC_ho_neighbor_config_1() );
12527 execute( TC_ho_neighbor_config_2() );
12528 execute( TC_ho_neighbor_config_3() );
12529 execute( TC_ho_neighbor_config_4() );
12530 execute( TC_ho_neighbor_config_5() );
12531 execute( TC_ho_neighbor_config_6() );
12532 execute( TC_ho_neighbor_config_7() );
12533
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012534 execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() );
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010012535 execute( TC_bssmap_clear_does_not_cause_bssmap_reset() );
Neels Hofmeyrfd445c32018-03-09 15:39:31 +010012536 execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() );
Harald Welte94e0c342018-04-07 11:33:23 +020012537
12538 execute( TC_dyn_pdch_ipa_act_deact() );
12539 execute( TC_dyn_pdch_ipa_act_nack() );
12540 execute( TC_dyn_pdch_osmo_act_deact() );
12541 execute( TC_dyn_pdch_osmo_act_nack() );
Pau Espin Pedrol37a4c152021-11-16 19:02:23 +010012542 execute( TC_dyn_ts_sdcch8_act_deact() );
12543 execute( TC_dyn_ts_sdcch8_all_subslots_used() );
12544 execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
12545 execute( TC_dyn_ts_sdcch8_act_nack() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012546
Stefan Sperling0796a822018-10-05 13:01:39 +020012547 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +020012548 execute( TC_chopped_ipa_payload() );
Stefan Sperling0796a822018-10-05 13:01:39 +020012549
Pau Espin Pedrol8f773632019-11-05 11:46:53 +010012550 /* Power control related */
12551 execute( TC_assignment_verify_ms_power_params_ie() );
Vadim Yanitskiy4b233042021-06-30 00:58:43 +020012552 execute( TC_c0_power_red_mode() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012553
12554 /* MSC pooling */
12555 /* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
12556 * RESET->RESET-ACK is unconditionally negotiated for all configured MSCs, they always all appear as connected
12557 * to osmo-bsc. The MSC pooling tests however require disconnecting selected MSCs, and hence don't work out as
12558 * intended on SCCPlite. So for now, run these only for SCCP/M3UA. */
12559 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12560 execute( TC_mscpool_L3Compl_on_1_msc() );
12561 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
12562 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
12563 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
12564 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
12565 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
12566 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
12567 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
12568 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
12569 execute( TC_mscpool_paging_and_response_imsi() );
12570 execute( TC_mscpool_paging_and_response_tmsi() );
12571 execute( TC_mscpool_no_allow_attach_round_robin() );
12572 execute( TC_mscpool_no_allow_attach_valid_nri() );
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +020012573
12574 execute( TC_mscpool_sccp_n_pcstate_detaches_msc() );
Neels Hofmeyr38632aa2023-04-05 03:50:51 +020012575 execute( TC_mscpool_sccp_n_pcstate_attaches_msc() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012576 }
12577
Harald Welte99f3ca02018-06-14 13:40:29 +020012578 execute( TC_early_conn_fail() );
12579 execute( TC_late_conn_fail() );
Oliver Smithaf03bef2021-08-24 15:34:51 +020012580 execute( TC_stats_conn_fail() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012581
Philipp Maier783681c2020-07-16 16:47:06 +020012582 /* Emergency call handling (deny / allow) */
12583 execute( TC_assignment_emerg_setup_allow() );
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +010012584 execute( TC_assignment_emerg_setup_allow_imei() );
Philipp Maier783681c2020-07-16 16:47:06 +020012585 execute( TC_assignment_emerg_setup_deny_msc() );
12586 execute( TC_assignment_emerg_setup_deny_bts() );
Philipp Maier82812002020-08-13 18:48:27 +020012587 execute( TC_emerg_premption() );
12588
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +070012589 /* Frequency hopping parameters handling */
12590 execute( TC_fh_params_chan_activ() );
12591 execute( TC_fh_params_imm_ass() );
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070012592 execute( TC_fh_params_assignment_cmd() );
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070012593 execute( TC_fh_params_handover_cmd() );
Vadim Yanitskiyca974032020-09-01 07:20:39 +070012594 execute( TC_fh_params_si4_cbch() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012595
12596 if (mp_enable_lcs_tests) {
12597 execute( TC_lcs_loc_req_for_active_ms() );
12598 execute( TC_lcs_loc_req_for_active_ms_ta_req() );
12599 execute( TC_lcs_loc_req_for_idle_ms() );
12600 execute( TC_lcs_loc_req_no_subscriber() );
12601 execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
12602 execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
12603 execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
12604 execute( TC_cm_service_during_lcs_loc_req() );
12605 execute( TC_ho_during_lcs_loc_req() );
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020012606 execute( TC_emerg_call_and_lcs_loc_req() );
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020012607 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() );
12608 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012609 }
Neels Hofmeyrbf037052020-10-28 22:52:02 +000012610
12611 execute( TC_no_msc() );
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000012612
12613 execute( TC_refuse_chan_act_to_vamos() );
12614 execute( TC_refuse_mode_modif_to_vamos() );
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000012615
12616 execute( TC_reassignment_fr() );
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020012617
12618 execute( TC_cm_reestablishment() );
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020012619
12620 execute( TC_imm_ass_post_chan_ack() );
12621 execute( TC_imm_ass_pre_chan_ack() );
Neels Hofmeyr23158742021-09-07 19:08:07 +020012622 execute( TC_imm_ass_pre_ts_ack() );
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020012623 execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020012624 execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020012625
12626 execute( TC_ctrl_trx_rf_locked() );
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012627
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012628 execute( TC_ratectr_all_available_allocated() );
12629 execute( TC_ratectr_all_available_allocated_dyn() );
12630
Neels Hofmeyrb7581872021-11-07 14:02:49 +010012631 execute( TC_cm_serv_rej() );
12632
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012633 execute( TC_lost_sdcch_during_assignment() );
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012634
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012635 /* Channel allocator */
12636 execute( TC_chan_alloc_algo_ascending() );
12637 execute( TC_chan_alloc_algo_descending() );
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012638 execute( TC_chan_alloc_algo_ass_dynamic() );
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012639
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012640 /* MGW pool */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +010012641 execute( TC_mgwpool_all_used() );
12642 execute( TC_mgwpool_blocked_not_used() );
12643 execute( TC_mgwpool_pin_bts() );
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012644
Oliver Smithc9a5f532022-10-21 11:32:23 +020012645 execute( TC_ho_meas_rep_multi_band() );
12646
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012647 /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
12648 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
12649 execute( TC_ho_out_of_this_bsc() );
Harald Welte28d943e2017-11-25 15:00:50 +010012650}
12651
12652}