blob: 878083e63f46bf9f80421801bafea35b1fefb5b9 [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
Oliver Smith545492d2023-04-19 13:05:30 +02001852private function f_tc_assignment_csd(charstring data_rate_str, OCT1 data_rate, boolean transp := true) runs on MSC_ConnHdlr {
Oliver Smithdd002752023-02-21 13:35:00 +01001853 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
Oliver Smith545492d2023-04-19 13:05:30 +02001860 /* Non-transparent service (3GPP TS 48.008 § 3.2.2.11, oct 5, bit 7) */
1861 if (not transp) {
1862 data_rate := data_rate or4b '40'O;
1863 }
1864
Oliver Smithcb617912023-04-18 11:29:10 +02001865 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := data_rate;
1866
1867 log("-----------------------------------------------");
1868 log("Assignment req with data rate: " & data_rate_str);
1869 log("-----------------------------------------------");
Oliver Smithdd002752023-02-21 13:35:00 +01001870
1871 f_establish_fully(ass_cmd, exp_compl);
Oliver Smithbc392a82023-04-17 14:06:42 +02001872
1873 if (g_media.bts.rtp_pt != enum2int(pt_csd)) {
1874 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("unexpected RTP payload type: ", g_media.bts.rtp_pt));
1875 }
1876
Oliver Smithdd002752023-02-21 13:35:00 +01001877 f_perform_clear();
1878}
Oliver Smithcb617912023-04-18 11:29:10 +02001879private function f_tc_assignment_csd_all(charstring id) runs on MSC_ConnHdlr {
1880 /* Data rates that require multi-slot HSCSD assignment are not tested
Oliver Smith545492d2023-04-19 13:05:30 +02001881 * on purpose (not supported): T_32k0, T_28k8, NT_43k5, NT_29k0 */
Oliver Smithcb617912023-04-18 11:29:10 +02001882 f_tc_assignment_csd("T_14k4", GSM0808_DATA_RATE_TRANSP_14k4);
1883 f_tc_assignment_csd("T_9k6", GSM0808_DATA_RATE_TRANSP_9k6);
1884 f_tc_assignment_csd("T_4k8", GSM0808_DATA_RATE_TRANSP_4k8);
1885 f_tc_assignment_csd("T_2k4", GSM0808_DATA_RATE_TRANSP_2k4);
1886 f_tc_assignment_csd("T_1k2", GSM0808_DATA_RATE_TRANSP_1k2);
1887 f_tc_assignment_csd("T_600", GSM0808_DATA_RATE_TRANSP_600);
1888 f_tc_assignment_csd("T_1200_75", GSM0808_DATA_RATE_TRANSP_1200_75);
Oliver Smith545492d2023-04-19 13:05:30 +02001889
1890 f_tc_assignment_csd("NT_12000_6000", GSM0808_DATA_RATE_NON_TRANSP_12000_6000, false);
1891 f_tc_assignment_csd("NT_14k5", GSM0808_DATA_RATE_NON_TRANSP_14k5, false);
1892 f_tc_assignment_csd("NT_12k0", GSM0808_DATA_RATE_NON_TRANSP_12k0, false);
1893 f_tc_assignment_csd("NT_6k0", GSM0808_DATA_RATE_NON_TRANSP_6k0, false);
Oliver Smithcb617912023-04-18 11:29:10 +02001894}
Oliver Smithdd002752023-02-21 13:35:00 +01001895testcase TC_assignment_csd() runs on test_CT {
1896 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.10.0 */
1897 var MSC_ConnHdlr vc_conn;
1898 var TestHdlrParams pars := f_gen_test_hdlr_pars();
1899 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
1900
Oliver Smith545492d2023-04-19 13:05:30 +02001901 f_init(1, true, guard_timeout := 120.0);
Oliver Smithdd002752023-02-21 13:35:00 +01001902 f_sleep(1.0);
Oliver Smithcb617912023-04-18 11:29:10 +02001903 vc_conn := f_start_handler(refers(f_tc_assignment_csd_all), pars);
Oliver Smithdd002752023-02-21 13:35:00 +01001904 vc_conn.done;
1905 } else {
1906 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
1907 var PDU_BSSAP ass_cmd := f_gen_ass_req();
1908 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
1909 //exp_fail.pdu.bssmap.assignmentFailure.cause.causeValue := int2bit(enum2int(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL), 7);
1910 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for CSD");
1911 f_perform_clear_test_ct(dt);
1912 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001913 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001914}
1915
1916testcase TC_assignment_ctm() runs on test_CT {
1917 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001918 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001919 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
1920 //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 +01001921 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
1922 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001923 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001924}
1925
Harald Welte4003d112017-12-09 22:35:39 +01001926type record DchanTuple {
1927 integer sccp_conn_id,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001928 RslChannelNr rsl_chan_nr,
1929 BtsTrxIdx idx
Harald Weltea5d2ab22017-12-09 14:21:42 +01001930}
1931
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +02001932type record of DchanTuple DchanTuples;
1933
Harald Welted6939652017-12-13 21:02:46 +01001934/* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001935private function f_chreq_act_ack(OCT1 ra := '23'O,
1936 GsmFrameNumber fn := 23,
1937 BtsTrxIdx idx := {0, 0})
Harald Welted6939652017-12-13 21:02:46 +01001938runs on test_CT return RslChannelNr {
1939 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001940 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
1941 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Harald Welted6939652017-12-13 21:02:46 +01001942 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001943 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10), idx);
1944 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Harald Welted6939652017-12-13 21:02:46 +01001945 return chan_nr;
1946}
1947
Harald Welte4003d112017-12-09 22:35:39 +01001948/* helper function to establish a dedicated channel via BTS and MSC */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001949function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1950 BtsTrxIdx idx := {0, 0})
Harald Welte4003d112017-12-09 22:35:39 +01001951runs on test_CT return DchanTuple {
1952 var BSSAP_N_CONNECT_ind rx_c_ind;
Harald Welte4003d112017-12-09 22:35:39 +01001953 var DchanTuple dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001954
Harald Welte4003d112017-12-09 22:35:39 +01001955 /* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001956 dt.rsl_chan_nr := f_chreq_act_ack(ra, fn, idx);
Harald Welte4003d112017-12-09 22:35:39 +01001957
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001958 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 +01001959
1960 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1961 dt.sccp_conn_id := rx_c_ind.connectionId;
1962 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1963
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001964 dt.idx := idx;
Harald Welte4003d112017-12-09 22:35:39 +01001965 return dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001966}
1967
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001968/* 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 +06001969function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1970 BtsTrxIdx idx := {0, 0})
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001971runs on test_CT return DchanTuple {
1972 var BSSAP_N_CONNECT_ind rx_c_ind;
1973 var DchanTuple dt;
1974
1975 /* Send CHAN RQD */
1976 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001977 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001978
1979 /* The dyn TS first deactivates PDCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001980 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 +02001981 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001982 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001983
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001984 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001985 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1986
1987 /* Now activates the signalling channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001988 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10), idx);
1989 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001990
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001991 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 +02001992
1993 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1994 dt.sccp_conn_id := rx_c_ind.connectionId;
1995 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1996
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001997 dt.idx := idx;
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001998 return dt;
1999}
2000
Harald Welte641fcbe2018-06-14 10:58:35 +02002001/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002002private function f_exp_chan_rel_and_clear(DchanTuple dt)
2003runs on test_CT {
Harald Welte641fcbe2018-06-14 10:58:35 +02002004 var RSL_Message rx_rsl;
2005 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002006 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 +02002007 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002008 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), dt.idx);
Harald Welte641fcbe2018-06-14 10:58:35 +02002009
2010 /* expect Clear Complete from BSC */
2011 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2012
2013 /* MSC disconnects as instructed. */
2014 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2015}
2016
Harald Welte4003d112017-12-09 22:35:39 +01002017/* Test behavior of channel release after unilateral RLL REL IND (DISC from MS) */
2018testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002019 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002020 var DchanTuple dt;
Harald Welte96c94412017-12-09 03:12:45 +01002021
Harald Welte89d42e82017-12-17 16:42:41 +01002022 f_init(1);
Harald Welte96c94412017-12-09 03:12:45 +01002023
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002024 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002025
2026 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002027 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Harald Welte4003d112017-12-09 22:35:39 +01002028
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002029 /* expect Clear Request on MSC side */
2030 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2031
2032 /* Instruct BSC to clear channel */
2033 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2034 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2035
Harald Welte4003d112017-12-09 22:35:39 +01002036 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002037 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002038
2039 /* wait for SCCP emulation to do its job */
2040 f_sleep(1.0);
Harald Welte4003d112017-12-09 22:35:39 +01002041
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002042 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002043}
2044
2045/* Test behavior of channel release after CONN FAIL IND from BTS */
2046testcase TC_chan_rel_conn_fail() runs on test_CT {
2047 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002048 var DchanTuple dt;
2049
Harald Welte89d42e82017-12-17 16:42:41 +01002050 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002051
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002052 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002053
Vadim Yanitskiy01d0a902022-12-14 22:41:42 +07002054 /* Sending CONN FAIL IND immediately may trigger a race condition.
2055 * Give the BSC some time to process a new SCCP connection (OS#5823). */
2056 f_sleep(0.2);
2057
Harald Welte4003d112017-12-09 22:35:39 +01002058 /* simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002059 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte4003d112017-12-09 22:35:39 +01002060 /* TODO: different cause values? */
2061
Harald Welte4003d112017-12-09 22:35:39 +01002062 /* expect Clear Request from BSC */
2063 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2064
2065 /* Instruct BSC to clear channel */
2066 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2067 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2068
Harald Welte6ff76ea2018-01-28 13:08:01 +01002069 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002070 f_exp_chan_rel_and_clear(dt);
Harald Welte4003d112017-12-09 22:35:39 +01002071
2072 /* wait for SCCP emulation to do its job */
2073 f_sleep(1.0);
2074
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002075 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002076}
2077
Harald Welte99f3ca02018-06-14 13:40:29 +02002078/* Test behavior of early CONN FAIL IND from BTS (before EST IND!) */
2079/* See also https://www.osmocom.org/issues/3182 */
2080testcase TC_early_conn_fail() runs on test_CT {
2081 var RSL_Message rx_rsl;
2082 var DchanTuple dt;
2083
2084 f_init(1);
2085
2086 /* BTS->BSC: Send CHAN RQD and wait for allocation; acknowledge it */
Harald Weltec46ea3c2020-10-10 18:46:12 +02002087 dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_ra_cs(), 23);
Harald Welte99f3ca02018-06-14 13:40:29 +02002088
2089 /* BTS->BSC: simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002090 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002091
2092 /* BTS->BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002093 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002094
2095 /* BTS<-BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002096 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002097
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002098 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002099}
2100
2101/* Test behavior of late CONN FAIL IND from BTS (ater REL IND!) */
2102/* See also https://www.osmocom.org/issues/3182 */
2103testcase TC_late_conn_fail() runs on test_CT {
2104 var RSL_Message rx_rsl;
2105 var DchanTuple dt;
2106
2107 f_init(1);
2108
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002109 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99f3ca02018-06-14 13:40:29 +02002110
2111 /* BSC<-MSC: Instruct BSC to clear connection */
2112 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(0)));
2113
2114 /* BTS->BSC: expect BSC to deactivate SACCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002115 rx_rsl := f_exp_ipa_rx(tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002116
2117 /* BTS->BSC: simulate a late CONN FAIL IND from BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002118 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002119
2120 /* BTS<-BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002121 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002122 /* BTS->BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002123 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002124
2125 /* BSC->MSC: expect Clear Complete from BSC */
2126 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2127
2128 /* BSC<-MSC: MSC disconnects as requested. */
2129 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2130
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002131 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002132}
2133
Oliver Smithaf03bef2021-08-24 15:34:51 +02002134private function f_TC_stats_conn_fail(charstring id) runs on MSC_ConnHdlr {
2135 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
2136 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2137
2138 f_statsd_reset();
2139
Oliver Smith15890b42023-03-08 14:12:28 +01002140 /* Establish SDCCH (invalid DataIndicator for exp_fail) */
Oliver Smithaf03bef2021-08-24 15:34:51 +02002141 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smith15890b42023-03-08 14:12:28 +01002142 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := 'ff'O;
Oliver Smithaf03bef2021-08-24 15:34:51 +02002143 f_establish_fully(ass_cmd, exp_fail);
2144
2145 /* Expect stats to be 0 */
2146 var StatsDExpects expect := {
2147 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
2148 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
2149 };
2150 f_statsd_expect(expect);
2151
2152 /* Simulate CONN FAIL IND on SDCCH */
2153 RSL.send(ts_ASP_RSL_UD(
2154 ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
2155 IPAC_PROTO_RSL_TRX0));
2156
Neels Hofmeyr58be48a2021-09-07 18:39:21 +02002157 f_sleep(1.0);
2158
Oliver Smithaf03bef2021-08-24 15:34:51 +02002159 /* Expect stats to be 1 */
2160 expect := {
2161 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
2162 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
2163 };
2164 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002165 BSSAP.receive(tr_BSSMAP_ClearRequest);
2166 f_perform_clear();
Oliver Smithaf03bef2021-08-24 15:34:51 +02002167}
2168testcase TC_stats_conn_fail() runs on test_CT {
2169 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2170 var MSC_ConnHdlr vc_conn;
2171
2172 f_init(1, true);
2173 f_sleep(1.0);
2174
2175 vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
2176 vc_conn.done;
2177
2178 f_shutdown_helper();
2179}
2180
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002181function f_expect_chan_rel(RslChannelNr rsl_chan_nr,
2182 BtsTrxIdx idx := {0, 0},
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002183 boolean expect_deact_sacch := true,
2184 boolean expect_rr_chan_rel := true,
2185 boolean expect_rll_rel_req := true,
Harald Welte99787102019-02-04 10:41:36 +01002186 boolean handle_rll_rel := true,
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002187 template CellSelIndValue expect_cells := omit,
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002188 template (present) RR_Cause expect_rr_cause := ?
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002189 ) runs on test_CT {
Harald Welte91d54a52018-01-28 15:35:07 +01002190
2191 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002192 var boolean got_deact_sacch := false;
2193 var boolean got_rr_chan_rel := false;
2194 var boolean got_rll_rel_req := false;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002195 var ASP_RSL_Unitdata ud;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002196 var RSL_IE_Body l3_ie;
2197 var PDU_ML3_NW_MS l3;
2198 var RR_Cause got_cause;
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002199 log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
2200 " expect_rll_rel_req=", expect_rll_rel_req);
Harald Welte91d54a52018-01-28 15:35:07 +01002201 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002202 [] 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 +01002203 got_deact_sacch := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002204 repeat;
2205 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002206 [] 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 +01002207 got_rr_chan_rel := true;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002208
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002209 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2210 setverdict(fail, "cannot find L3");
2211 mtc.stop;
2212 }
2213 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2214
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002215 if (not istemplatekind(expect_cells, "omit")) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002216 var CellSelIndValue cells := dec_CellSelIndValue(
2217 l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
2218
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002219 log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
2220 if (match(cells, expect_cells)) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002221 setverdict(pass);
2222 } else {
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002223 log("EXPECTED CELLS: ", expect_cells);
2224 setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002225 }
2226 }
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002227
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002228 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2229 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2230 if (match(got_cause, expect_rr_cause)) {
2231 setverdict(pass);
2232 } else {
2233 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2234 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002235 }
Harald Welte99787102019-02-04 10:41:36 +01002236 repeat;
2237 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002238 [] 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 +01002239 got_rll_rel_req := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002240 /* FIXME: Why are we getting this for LinkID SACCH? */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002241 if (handle_rll_rel) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002242 f_ipa_tx(ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002243 }
Harald Welte91d54a52018-01-28 15:35:07 +01002244 repeat;
2245 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002246 [] 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 +01002247 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002248 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
Harald Welte91d54a52018-01-28 15:35:07 +01002249 }
2250 /* ignore any user data */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002251 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002252 repeat;
2253 }
2254 }
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002255
2256 log("f_expect_chan_rel() summary: got_deact_sacch=", got_deact_sacch, " got_rr_chan_rel=", got_rr_chan_rel,
2257 " got_rll_rel_req=", got_rll_rel_req);
2258
2259 if (expect_deact_sacch != got_deact_sacch) {
2260 setverdict(fail, "f_expect_chan_rel(): expect_deact_sacch=", expect_deact_sacch, " got_deact_sacch=", got_deact_sacch);
2261 }
2262 if (expect_rr_chan_rel != got_rr_chan_rel) {
2263 setverdict(fail, "f_expect_chan_rel(): expect_rr_chan_rel=", expect_rr_chan_rel, " got_rr_chan_rel=", got_rr_chan_rel);
2264 }
2265 if (expect_rll_rel_req != got_rll_rel_req) {
2266 setverdict(fail, "f_expect_chan_rel(): expect_rll_rel_req=", expect_rll_rel_req, " got_rll_rel_req=", got_rll_rel_req);
2267 }
Harald Welte91d54a52018-01-28 15:35:07 +01002268}
2269
Harald Welte4003d112017-12-09 22:35:39 +01002270/* Test behavior of channel release after hard Clear Command from MSC */
2271testcase TC_chan_rel_hard_clear() runs on test_CT {
2272 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002273 var DchanTuple dt;
Harald Welte4003d112017-12-09 22:35:39 +01002274
Harald Welte89d42e82017-12-17 16:42:41 +01002275 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002276
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002277 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002278
2279 /* Instruct BSC to clear channel */
2280 var BssmapCause cause := 0;
2281 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2282
2283 /* expect Clear Complete from BSC on A */
2284 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2285 /* release the SCCP connection */
2286 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2287 }
2288
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002289 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002290 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002291}
2292
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002293function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
2294 var BSSAP_N_DATA_ind rx_di;
2295 var DchanTuple dt;
2296
2297 f_init(1);
2298
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002299 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002300 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2301 /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
2302 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
2303
2304 /* Instruct BSC to clear channel */
2305 var BssmapCause cause := 0;
2306 if (tx_csfb_ind) {
2307 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2308 } else {
2309 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2310 }
2311
2312 /* expect Clear Complete from BSC on A */
2313 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2314 /* release the SCCP connection */
2315 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2316 }
2317
2318 /* 1 neighbor is added by default in osmo-bts.cfg and
2319 SystemInformationConfig_default, use that: */
2320 var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
2321
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002322 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 +02002323 f_shutdown_helper();
2324}
2325
2326/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
2327 from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
2328 PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2329 EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
2330 Indicator or not shouldn't matter at all. */
2331testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
2332 f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
2333}
2334
2335/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
2336 MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
2337 Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2338 EUTRAN neighbor list sent later on by BSC in RR Channel. */
2339testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
2340 f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
2341}
2342
2343/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
2344 MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
2345 Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
2346 CSFB Indicator should not be used anymore, and hence, there should be no
2347 EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
2348 Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
Harald Welte99787102019-02-04 10:41:36 +01002349testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
2350 var BSSAP_N_DATA_ind rx_di;
2351 var DchanTuple dt;
2352
2353 f_init(1);
2354
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002355 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99787102019-02-04 10:41:36 +01002356
2357 /* Instruct BSC to clear channel */
2358 var BssmapCause cause := 0;
2359 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2360
2361 /* expect Clear Complete from BSC on A */
2362 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2363 /* release the SCCP connection */
2364 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2365 }
2366
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002367 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002368 f_shutdown_helper();
Harald Welte99787102019-02-04 10:41:36 +01002369}
2370
Harald Welted8c36cd2017-12-09 23:05:31 +01002371/* Test behavior of channel release after hard RLSD from MSC */
2372testcase TC_chan_rel_hard_rlsd() runs on test_CT {
Harald Welted8c36cd2017-12-09 23:05:31 +01002373 var DchanTuple dt;
Harald Welted8c36cd2017-12-09 23:05:31 +01002374
Harald Welte89d42e82017-12-17 16:42:41 +01002375 f_init(1);
Harald Welted8c36cd2017-12-09 23:05:31 +01002376
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002377 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welted8c36cd2017-12-09 23:05:31 +01002378
2379 /* release the SCCP connection */
2380 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2381
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002382 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002383 f_shutdown_helper();
Harald Welted8c36cd2017-12-09 23:05:31 +01002384}
2385
Harald Welte550daf92018-06-11 19:22:13 +02002386/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
2387testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
2388 var DchanTuple dt;
2389
2390 f_init(1);
2391
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002392 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte550daf92018-06-11 19:22:13 +02002393
2394 /* release the SCCP connection */
2395 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2396
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002397 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002398 f_shutdown_helper();
Harald Welte550daf92018-06-11 19:22:13 +02002399}
2400
Harald Welte85804d42017-12-10 14:11:58 +01002401/* Test behavior of channel release after BSSMAP RESET from MSC */
2402testcase TC_chan_rel_a_reset() runs on test_CT {
Harald Welte85804d42017-12-10 14:11:58 +01002403 var DchanTuple dt;
Harald Welte85804d42017-12-10 14:11:58 +01002404
Harald Welte89d42e82017-12-17 16:42:41 +01002405 f_init(1);
Harald Welte85804d42017-12-10 14:11:58 +01002406
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002407 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte85804d42017-12-10 14:11:58 +01002408
2409 /* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002410 IPA_RSL[0][0].clear;
Harald Welte85804d42017-12-10 14:11:58 +01002411
2412 /* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002413 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 +01002414 interleave {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002415 [] 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 +01002416 [] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
2417 }
2418
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002419 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002420 f_shutdown_helper();
Harald Welte85804d42017-12-10 14:11:58 +01002421}
2422
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002423/* Verify T(iar) triggers and releases the channel */
2424testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
2425 var DchanTuple dt;
2426
2427 /* Set T(iar) in BSC low enough that it will trigger before other side
2428 has time to keep alive with a T(ias). Keep recommended ratio of
2429 T(iar) >= T(ias)*2 */
2430 g_bsc_sccp_timer_ias := 2;
2431 g_bsc_sccp_timer_iar := 5;
2432
2433 f_init(1);
2434
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002435 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002436 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002437 f_shutdown_helper();
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002438}
2439
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002440private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause,
2441 template (present) RR_Cause expect_rr_cause)
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002442runs on test_CT
2443{
2444 var DchanTuple dt;
2445
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002446 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002447 var BssmapCause cause := 0;
2448 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
2449 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2450 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2451 }
2452
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002453 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 +02002454}
2455
2456/* Test that Clear Command cause codes affect the RR Channel Release cause code */
2457testcase TC_chan_rel_rr_cause() runs on test_CT {
2458 f_init(1);
2459
2460 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
2461 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
2462 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
2463 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
2464 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
2465 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
Vadim Yanitskiye18aebb2021-01-03 13:10:43 +01002466
2467 f_shutdown_helper();
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002468}
2469
Harald Welte5cd20ed2017-12-13 21:03:20 +01002470/* Test behavior if RSL EST IND for non-active channel */
2471testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
2472 timer T := 2.0;
2473
Harald Welte89d42e82017-12-17 16:42:41 +01002474 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002475
Harald Welte5cd20ed2017-12-13 21:03:20 +01002476 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002477 var octetstring l3_payload := gen_l3_valid_payload();
2478 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002479
2480 T.start;
2481 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002482 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002483 setverdict(fail, "MSC received COMPL L3 for non-active lchan");
2484 }
2485 [] BSSAP.receive {}
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002486 [] IPA_RSL[0][0].receive {}
Harald Welte5cd20ed2017-12-13 21:03:20 +01002487 [] T.timeout {}
2488 }
2489
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002490 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002491}
2492
2493/* Test behavior if RSL EST IND for invalid SAPI */
2494testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
2495 var RslChannelNr chan_nr;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002496 var octetstring l3_payload;
Harald Welte5cd20ed2017-12-13 21:03:20 +01002497
Harald Welte89d42e82017-12-17 16:42:41 +01002498 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002499
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002500 chan_nr := f_chreq_act_ack();
2501 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(1)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002504
2505 timer T := 2.0;
2506 T.start;
2507 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002508 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002509 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
2510 }
2511 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002512 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002513 [] T.timeout {}
2514 }
2515
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002516 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002517}
2518
2519/* Test behavior if RSL EST IND for invalid SAPI */
2520testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
2521 timer T := 2.0;
2522
Harald Welte89d42e82017-12-17 16:42:41 +01002523 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002524
2525 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002526 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002527
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002528 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002529
2530 T.start;
2531 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002532 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002533 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
2534 }
2535 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002536 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002537 [] T.timeout {}
2538 }
2539
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002540 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002541}
2542
2543/* Test behavior if RSL EST IND for invalid SACCH */
2544testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
2545 timer T := 2.0;
2546
Harald Welte89d42e82017-12-17 16:42:41 +01002547 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002548
2549 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002550 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002551
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002552 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002553
2554 T.start;
2555 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002556 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002557 setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
2558 }
2559 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002560 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002561 [] T.timeout {}
2562 }
2563
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002564 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002565}
2566
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002567/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
2568private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
2569 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
2570 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2571
2572 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
2573 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
2574
2575 f_establish_fully(ass_cmd, exp_compl);
2576
2577 /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
2578 RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
2579 /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
2580 BSSAP.receive(PDU_BSSAP:{
2581 discriminator := '1'B,
2582 spare := '0000000'B,
2583 dlci := 'C3'O,
2584 lengthIndicator := ?,
2585 pdu := { dtap := '0904'O }
2586 });
2587
2588 /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
2589 for (var integer i := 0; i < 32; i := i + 1) {
2590 var octetstring l3 := '09'O & f_rnd_octstring(14);
2591 var template (value) RslLinkId link_id;
2592 var template (value) OCT1 dlci;
2593
2594 if (i mod 2 == 0) {
2595 /* SAPI0 on FACCH or SDCCH */
2596 link_id := ts_RslLinkID_DCCH(0);
2597 dlci := '80'O;
2598 } else {
2599 /* SAPI3 on SACCH */
2600 link_id := ts_RslLinkID_SACCH(3);
2601 dlci := 'C3'O;
2602 }
2603
2604 /* Send MO message: RSL -> BSSAP */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002605 f_mo_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002606 /* Send MT message: BSSAP -> RSL */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002607 f_mt_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002608 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002609 f_perform_clear();
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002610}
2611testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
2612 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2613 var MSC_ConnHdlr vc_conn;
2614
2615 f_init(1, true);
2616 f_sleep(1.0);
2617
2618 vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
2619 vc_conn.done;
2620
2621 f_shutdown_helper();
2622}
2623
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002624private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002625 template (present) myBSSMAP_Cause cause := ?,
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002626 template (present) BIT2 cc := ?,
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002627 float T_val := 2.0)
2628runs on test_CT {
2629 var BSSAP_N_DATA_ind rx_di;
2630 timer T;
2631
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002632 var template (present) BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
2633 var template (present) PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002634
2635 T.start(T_val);
2636 alt {
2637 [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
2638 var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
2639 if (not match(rx_cause, tr_cause)) {
2640 setverdict(fail, "Rx unexpected Cause IE: ",
2641 rx_cause, " vs expected ", tr_cause);
2642 }
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002643
2644 /* Who ever on the earth decided to define this field as two separate bits?!? */
2645 var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
2646 & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
2647 if (not match(rx_cc, cc)) {
2648 setverdict(fail, "Rx unexpected Control Channel type: ",
2649 rx_cc, " vs expected ", cc);
2650 }
2651
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002652 setverdict(pass);
2653 }
2654 [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
2655 setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
2656 }
2657 [] T.timeout {
2658 setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
2659 }
2660 }
2661}
2662
2663/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
2664testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002665 var RSL_Message rx_rsl;
2666 var DchanTuple dt;
2667
2668 f_init(1);
2669
2670 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002671 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002672
2673 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002674 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 +07002675 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002676 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 +07002677
2678 /* MS sends unexpected RELease INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002679 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002680 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2681 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
2682
2683 /* Clean up the connection */
2684 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002685 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002686
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002687 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002688}
2689
2690/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
2691testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002692 var RSL_Message rx_rsl;
2693 var DchanTuple dt;
2694
2695 f_init(1);
2696
2697 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002698 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002699
2700 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002701 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 +07002702 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002703 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 +07002704
2705 /* BTS sends unexpected ERROR INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002706 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002707 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2708 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
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
2717/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
2718testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +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 Yanitskiy6ef5dfa2020-08-28 18:04:41 +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 Yanitskiy6ef5dfa2020-08-28 18:04:41 +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 Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002731
2732 /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
2733 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
2734
2735 /* Clean up the connection */
2736 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002737 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002738
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002739 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002740}
2741
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002742/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
2743testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002744 var RSL_Message rx_rsl;
2745 var DchanTuple dt;
2746
2747 f_init(1);
2748
2749 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002750 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002751
2752 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002753 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 +07002754 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002755 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 +07002756
2757 /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002758 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Pau Espin Pedrol121f27f2022-01-12 12:02:10 +01002759 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, '10'B);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002760
2761 /* Clean up the connection */
2762 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002763 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002764
2765 f_shutdown_helper();
2766}
2767
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002768testcase TC_si_default() runs on test_CT {
2769 f_init(0);
2770 f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002771 f_shutdown_helper();
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002772}
Harald Welte4003d112017-12-09 22:35:39 +01002773
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002774/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
2775 * the entire value range. This function provides the same EARFCN numbers for the same earfcn_index */
2776private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uint16_t
2777{
2778 select (earfcn_index) {
2779 case (0) {
2780 /* E-ARFCN 111 is already added in the osmo-bsc.cfg */
2781 return 111;
2782 }
2783 case (1) {
2784 return 1;
2785 }
2786 case (2) {
2787 return 0;
2788 }
2789 case (3) {
2790 return 65535;
2791 }
2792 case else {
2793 return 23 * (earfcn_index - 3);
2794 }
2795 }
2796}
2797
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002798function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
2799 template CellSelIndValue expect_cells := omit) runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002800
2801 f_init(0);
2802
2803 /* E-ARFCN 111 is already added in the osmo-bsc.cfg, so only add more arfcns if total_earfcns > 1 */
2804 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002805 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2806 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002807 }
2808
2809 f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
2810
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002811 if (not istemplatekind(expect_cells, "omit")) {
2812 /* Also check that RR Channel Release contains these EARFCNs.
2813 * (copied code from TC_chan_rel_hard_clear_csfb) */
2814 var BSSAP_N_DATA_ind rx_di;
2815 var DchanTuple dt;
2816
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002817 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrold0046312021-04-19 16:35:58 +02002818 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2819 * yet when generating the EUTRAN neigh list in RR CHannel Release) */
2820 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002821
2822 /* Instruct BSC to clear channel */
2823 var BssmapCause cause := 0;
2824 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2825
2826 /* expect Clear Complete from BSC on A */
2827 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2828 /* release the SCCP connection */
2829 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2830 }
2831
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002832 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := expect_cells);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002833 }
2834
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002835 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002836 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 +02002837 }
2838}
2839
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002840private function f_tr_si2quater_earfcns(integer count) return template SI2quaterRestOctetsList
2841{
2842 var template SI2quaterRestOctetsList si2quater := {};
2843 var integer si2quater_count := (count + 2) / 3;
2844
2845 for (var integer i := 0; i < count; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002846 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002847 var integer index := i / 3;
2848 var integer earfcn_index := i mod 3;
2849 if (index >= lengthof(si2quater)) {
2850 si2quater[index] := tr_SI2quaterRestOctets_EUTRAN(index := index, count := si2quater_count - 1);
2851 }
2852 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);
2853 }
2854
2855 return si2quater;
2856}
2857
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002858private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
2859{
2860 var template CellSelIndValue_EUTRAN_Descrs cells := {};
2861
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002862 /* the lte neighbors must match the config & vty to pass this test */
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002863 for (var integer i := 0; i < count; i := i + 1) {
2864 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002865 cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002866 }
2867
2868 return tr_CellSelIndValue_EUTRAN(cells);
2869}
2870
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002871private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
2872{
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002873 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrol8ab62e42020-12-18 16:19:11 +01002874 sic.si2quater := f_tr_si2quater_earfcns(n);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002875 var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
2876 f_test_si2quater(n, sic, cells);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002877}
2878
2879testcase TC_si2quater_2_earfcns() runs on test_CT {
2880 f_tc_si2quater_n_earfcns(2);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002881 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002882}
2883
2884testcase TC_si2quater_3_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002885 f_tc_si2quater_n_earfcns(3);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002886 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002887}
2888
2889testcase TC_si2quater_4_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002890 f_tc_si2quater_n_earfcns(4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002891 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002892}
2893
2894testcase TC_si2quater_5_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002895 f_tc_si2quater_n_earfcns(5);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002896 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002897}
2898
2899testcase TC_si2quater_6_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002900 f_tc_si2quater_n_earfcns(6);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002901 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002902}
2903
2904testcase TC_si2quater_12_earfcns() runs on test_CT {
2905 f_tc_si2quater_n_earfcns(12);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002906 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002907}
2908
2909testcase TC_si2quater_23_earfcns() runs on test_CT {
2910 f_tc_si2quater_n_earfcns(23);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002911 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002912}
2913
2914testcase TC_si2quater_32_earfcns() runs on test_CT {
2915 f_tc_si2quater_n_earfcns(32);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002916 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002917}
2918
2919testcase TC_si2quater_33_earfcns() runs on test_CT {
2920 f_tc_si2quater_n_earfcns(33);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002921 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002922}
2923
2924testcase TC_si2quater_42_earfcns() runs on test_CT {
2925 f_tc_si2quater_n_earfcns(42);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002926 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002927}
2928
2929testcase TC_si2quater_48_earfcns() runs on test_CT {
2930 f_tc_si2quater_n_earfcns(48);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002931 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002932}
2933
2934/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
2935 * 48 EARFCNs. */
2936testcase TC_si2quater_49_earfcns() runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002937 var template SystemInformationConfig sic := SystemInformationConfig_default;
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002938 sic.si2quater := f_tr_si2quater_earfcns(48); /* 48, not 49! */
2939 f_init(0);
2940
2941 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002942 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2943 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002944 }
2945
2946 /* The 49th EARFCN no longer fits, expect VTY error */
2947 f_vty_enter_cfg_bts(BSCVTY, 0);
2948 var charstring vty_error;
2949 vty_error := f_vty_transceive_ret(BSCVTY,
2950 "si2quater neighbor-list add earfcn 70 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3")
2951 f_vty_transceive(BSCVTY, "end");
2952
2953 if (f_strstr(vty_error, "Unable to add ARFCN 70") >= 0) {
2954 log("Got expected VTY error: ", vty_error);
2955 setverdict(pass);
2956 } else {
2957 setverdict(fail, "Expected the 49th EUTRAN ARFCN to be rejected by vty config, got: ", vty_error);
2958 }
2959
2960 f_init_bts_and_check_sysinfo(0, expect_si := sic);
2961
2962 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002963 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 +02002964 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002965 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002966}
2967
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002968private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
2969{
2970 var uint8_t count := 0;
2971 for (var integer i := 5; i < 16; i := i + 1) {
2972 if (acc[i] == '0'B) { /* the list marks barred, we count allowed */
2973 count := count + 1;
2974 }
2975 }
2976 return count;
2977}
2978
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002979private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return SystemInformationType1
2980{
2981 var ASP_RSL_Unitdata rx_rsl_ud;
2982 var SystemInformationType1 last_si1;
2983
2984 timer T := 30.0;
2985 T.start;
2986 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002987 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
2988 tr_RSL_BCCH_INFO,
2989 tr_RSL_NO_SACCH_FILL,
2990 tr_RSL_SACCH_FILL))) -> value rx_rsl_ud {
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002991 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
2992 if (g_system_information[rsl_idx].si1 == omit) {
2993 repeat;
2994 }
2995 last_si1 := g_system_information[rsl_idx].si1;
2996 g_system_information[rsl_idx].si1 := omit;
2997 T.stop;
2998 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002999 [] IPA_RSL[rsl_idx][0].receive { repeat; }
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003000 [] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
3001 }
3002 return last_si1;
3003}
3004
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003005/* verify ACC rotate feature */
3006testcase TC_si_acc_rotate() runs on test_CT {
3007 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003008 var SystemInformationType1 last_si1;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003009 var AccessControlClass acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003010 var uint8_t count;
3011 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3012
3013 f_init(0, guard_timeout := 60.0);
3014
3015 f_bts_0_cfg(BSCVTY, {"rach access-control-class 5 barred",
3016 "access-control-class-rotate 3",
3017 "access-control-class-rotate-quantum 1"});
3018
3019 /* Init and get first sysinfo */
3020 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3021
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003022 for (var integer i:= 0; i < 20; i := i + 1) {
3023 last_si1 := f_recv_next_si1(0);
3024 acc := last_si1.rach_control.acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003025 count := f_acc09_count_allowed(acc);
3026 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3027
3028 if (count != 3) {
3029 log("RSL: EXPECTED SI ACC len=3");
3030 setverdict(fail, "received SI does not match expectations");
3031 break;
3032 }
3033
3034 for (var integer j := 0; j < 10; j := j + 1) {
3035 if (acc[16 - 1 - j] == '0'B) { /* the list marks barred, we count allowed */
3036 times_allowed[j] := times_allowed[j] + 1;
3037 }
3038 }
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003039 }
3040
3041 for (var integer j := 0; j < 10; j := j + 1) {
3042 log("ACC", j, " allowed ", times_allowed[j], " times" );
3043 if (j != 5 and times_allowed[j] < 3) {
3044 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " < 1 times");
3045 } else if (j == 5 and times_allowed[j] > 0) {
3046 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " > 0 times");
3047 }
3048 }
3049
3050 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3051 "rach access-control-class 5 allowed"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003052 f_shutdown_helper();
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003053}
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02003054
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003055/* verify ACC startup ramp+rotate feature */
3056testcase TC_si_acc_ramp_rotate() runs on test_CT {
3057 var template SystemInformationConfig sic := SystemInformationConfig_default;
3058 var SystemInformationType1 last_si1;
3059 var AccessControlClass acc;
3060 var ASP_RSL_Unitdata rx_rsl_ud;
3061 var uint8_t count;
3062 var uint8_t prev_count;
3063 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3064
3065 f_init(0, guard_timeout := 80.0);
3066
3067 f_bts_0_cfg(BSCVTY, {"rach access-control-class 4 barred",
3068 "access-control-class-rotate 0",
3069 "access-control-class-rotate-quantum 1",
3070 "access-control-class-ramping",
3071 "access-control-class-ramping-step-interval 5",
3072 "access-control-class-ramping-step-size 5"});
3073
3074 /* Init and get first sysinfo */
3075 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3076 last_si1 := g_system_information[0].si1;
3077 acc := last_si1.rach_control.acc;
3078 count := f_acc09_count_allowed(acc);
3079 /* Adm subset size was set to 0 above, so wait until all ACC are barred */
3080 while (count > 0) {
3081 last_si1 := f_recv_next_si1(0);
3082 acc := last_si1.rach_control.acc;
3083 count := f_acc09_count_allowed(acc);
3084 log("RSL: wait len()=0: GOT SI1 ACC len=", count, ": ", acc);
3085 }
3086
3087 /* Increase adm subset size, we should see ramping start up */
3088 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10"});
3089 prev_count := 0;
3090 while (true) {
3091 last_si1 := f_recv_next_si1(0);
3092 acc := last_si1.rach_control.acc;
3093 count := f_acc09_count_allowed(acc);
3094 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3095
3096 if (prev_count > count) {
3097 setverdict(fail, "ACC allowed count dropped while expecting grow: ", prev_count, " -> ", count);
3098 break;
3099 }
3100
3101 if (count == 9) {
3102 break; /* Maximum reached (10 - 1 perm barred), done here */
3103 }
3104
3105 prev_count := count;
3106 }
3107
3108 setverdict(pass);
3109
3110 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3111 "rach access-control-class 4 allowed",
3112 "no access-control-class-ramping"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003113 f_shutdown_helper();
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003114}
3115
Harald Welte4003d112017-12-09 22:35:39 +01003116testcase TC_ctrl_msc_connection_status() runs on test_CT {
3117 var charstring ctrl_resp;
3118
Harald Welte89d42e82017-12-17 16:42:41 +01003119 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003120
3121 /* See https://osmocom.org/issues/2729 */
3122 f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003123 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01003124}
3125
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003126testcase TC_ctrl_msc0_connection_status() runs on test_CT {
3127 var charstring ctrl_resp;
3128
3129 f_init(1);
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003130
3131 f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003132 f_shutdown_helper();
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003133}
3134
Neels Hofmeyr0bc470d2021-08-21 13:37:13 +02003135/* Verify correct stats on the number of configured and connected MSCs */
3136private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
3137 g_pars := f_gen_test_hdlr_pars();
3138 var StatsDExpects expect := {
3139 { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
3140 { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
3141 };
3142 f_statsd_expect(expect);
3143}
3144
3145private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
3146{
3147 var MSC_ConnHdlr vc_conn;
3148
3149 f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
3150 f_sleep(1.0);
3151 vc_conn := f_start_handler(tc_fn);
3152 vc_conn.done;
3153
3154 /* Also verify stat exposed on CTRL interface */
3155 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
3156 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
3157
3158 f_shutdown_helper();
3159}
3160
3161/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
3162private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
3163 f_tc_stat_num_msc_connected_msc_connhdlr(1);
3164}
3165testcase TC_stat_num_msc_connected_1() runs on test_CT {
3166 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
3167}
3168
3169/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
3170private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
3171 f_tc_stat_num_msc_connected_msc_connhdlr(2);
3172}
3173testcase TC_stat_num_msc_connected_2() runs on test_CT {
3174 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
3175}
3176
3177/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
3178private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
3179 f_tc_stat_num_msc_connected_msc_connhdlr(3);
3180}
3181testcase TC_stat_num_msc_connected_3() runs on test_CT {
3182 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
3183}
3184
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003185/* Verify correct stats on the number of configured and connected MSCs */
3186private 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 +06003187 var integer num_trx_connected := 0;
3188 var integer num_trx_total := 0;
3189
3190 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3191 var integer trx_num := c_BtsParams[i].trx_num;
3192 num_trx_total := num_trx_total + trx_num;
3193 if (i < expect_num_bts_connected) {
3194 num_trx_connected := num_trx_connected + trx_num;
3195 }
3196 }
3197
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003198 var StatsDExpects expect := {
3199 { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
3200 { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3201 { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003202 { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := num_trx_connected, max := num_trx_connected },
3203 { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := num_trx_total, max := num_trx_total }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003204 };
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003205
3206 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003207 f_statsd_expect(expect);
3208}
3209
3210private 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 +06003211 var integer num_trx_connected := 0;
3212 var integer num_trx_total := 0;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003213 var MSC_ConnHdlr vc_conn;
3214
3215 f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
3216 f_sleep(1.0);
3217 vc_conn := f_start_handler(tc_fn);
3218 vc_conn.done;
3219
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003220 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3221 var integer trx_num := c_BtsParams[i].trx_num;
3222 num_trx_total := num_trx_total + trx_num;
3223 if (i < nr_bts) {
3224 num_trx_connected := num_trx_connected + trx_num;
3225 }
3226 }
3227
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003228 /* Also verify stat exposed on CTRL interface */
3229 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
3230 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 +06003231 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(num_trx_connected));
3232 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 +02003233
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003234 /* Verify rf_states exposed on CTRL interface */
3235 var charstring expect_net_rf_states := "";
3236 for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003237 var charstring expect_bts_rf_states := "";
3238
3239 for (var integer j := 0; j < c_BtsParams[i].trx_num; j := j + 1) {
3240 expect_bts_rf_states := expect_bts_rf_states &
3241 int2str(i) & "," & int2str(j) & ",";
3242 if (i < NUM_BTS) {
3243 /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
3244 expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
3245 } else {
3246 /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
3247 expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
3248 }
3249 /* The RF policy is still global in osmo-bsc, i.e. always "on" */
3250 expect_bts_rf_states := expect_bts_rf_states & "on,";
3251 if (i < nr_bts) {
3252 /* For BTS where RSL is connected, the RSL state will be "up" */
3253 expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
3254 } else {
3255 expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
3256 }
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003257 }
3258
3259 f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
3260 expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
3261 }
3262 f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
3263
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003264 f_shutdown_helper();
3265}
3266
3267/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
3268private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
3269 f_tc_stat_num_bts_connected_msc_connhdlr(1);
3270}
3271testcase TC_stat_num_bts_connected_1() runs on test_CT {
3272 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
3273}
3274
3275/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
3276private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
3277 f_tc_stat_num_bts_connected_msc_connhdlr(2);
3278}
3279testcase TC_stat_num_bts_connected_2() runs on test_CT {
3280 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
3281}
3282
3283/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
3284private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
3285 f_tc_stat_num_bts_connected_msc_connhdlr(3);
3286}
3287testcase TC_stat_num_bts_connected_3() runs on test_CT {
3288 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
3289}
3290
Harald Welte4003d112017-12-09 22:35:39 +01003291testcase TC_ctrl() runs on test_CT {
3292 var charstring ctrl_resp;
3293
Harald Welte89d42e82017-12-17 16:42:41 +01003294 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003295
3296 /* all below values must match the osmo-bsc.cfg config file used */
3297
Harald Welte6a129692018-03-17 17:30:14 +01003298 f_ctrl_get_exp(IPA_CTRL, "mcc", "001");
3299 f_ctrl_get_exp(IPA_CTRL, "mnc", "01");
Oliver Smith75aa0202019-08-19 14:17:50 +02003300 f_ctrl_get_exp(IPA_CTRL, "number-of-bts", "4");
Harald Welte4003d112017-12-09 22:35:39 +01003301
3302 var integer bts_nr := 0;
3303 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "location-area-code", "1");
3304 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "cell-identity", "0");
3305 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "oml-connection-state", "connected");
3306 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "gprs-mode", "gprs");
3307 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "rf_state", "operational,unlocked,on");
3308 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "arfcn", "871");
3309 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "max-power-reduction", "20");
3310
3311 var integer uptime := str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime"));
3312 f_sleep(2.0);
3313 if (str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime")) < uptime+1) {
3314 setverdict(fail, "oml-uptime not incrementing as expected");
3315 }
3316 /* TODO: Disconnect RSL, imply that OML is disconnected and check for uptime zero? */
3317
3318 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
3319
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003320 f_shutdown_helper();
Harald Welte96c94412017-12-09 03:12:45 +01003321}
3322
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003323/* Verify that Upon receival of SET "location", BSC forwards a TRAP
3324 "location-state" over the SCCPlite IPA conn */
3325testcase TC_ctrl_location() runs on test_CT {
3326 var MSC_ConnHdlr vc_conn;
3327 var integer bts_nr := 0;
3328
3329 f_init(1, true);
3330 f_sleep(1.0);
3331
3332 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234567,fix3d,0.340000,0.560000,0.780000");
3333 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3334 "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
3335
3336 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "1");
3337 f_sleep(2.0);
3338
3339 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234888,fix3d,0.350000,0.570000,0.790000");
3340 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3341 "1234888,fix3d,0.350000,0.570000,0.790000,operational,locked,off,001,01");
3342
3343 /* should match the one from config */
3344 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
3345
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003346 f_shutdown_helper();
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003347}
3348
Harald Welte6f521d82017-12-11 19:52:02 +01003349
3350/***********************************************************************
3351 * Paging Testing
3352 ***********************************************************************/
3353
3354type record Cell_Identity {
3355 GsmMcc mcc,
3356 GsmMnc mnc,
3357 GsmLac lac,
3358 GsmCellId ci
3359};
Harald Welte24135bd2018-03-17 19:27:53 +01003360private const Cell_Identity cid := { '001'H, '01'H, 1, 0 };
Stefan Sperling049a86e2018-03-20 15:51:00 +01003361private const Cell_Identity unknown_cid := { '678'H, 'f90'H, 1, 0 };
Harald Welte6f521d82017-12-11 19:52:02 +01003362
Harald Welte5d1a2202017-12-13 19:51:29 +01003363type set of integer BtsIdList;
3364
3365private function f_bts_in_list(integer bts_id, BtsIdList bts_ids) return boolean {
3366 for (var integer j := 0; j < sizeof(bts_ids); j := j + 1) {
3367 if (bts_id == bts_ids[j]) {
3368 return true;
3369 }
3370 }
3371 return false;
3372}
Harald Welte6f521d82017-12-11 19:52:02 +01003373
3374/* core paging test helper function; used by most paging test cases */
3375private function f_pageing_helper(hexstring imsi,
3376 template BSSMAP_FIELD_CellIdentificationList cid_list,
Harald Welte5d1a2202017-12-13 19:51:29 +01003377 BtsIdList bts_ids := { 0 },
Harald Welte6f521d82017-12-11 19:52:02 +01003378 template RSL_ChanNeeded rsl_chneed := omit,
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003379 template (omit) OCT4 tmsi := omit) runs on test_CT
Harald Welte6f521d82017-12-11 19:52:02 +01003380{
3381 var template BSSMAP_IE_ChannelNeeded bssmap_chneed;
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003382 var template MobileIdentityV mi;
Harald Welte6f521d82017-12-11 19:52:02 +01003383 var RSL_Message rx_rsl;
3384 var integer paging_group := hex2int(imsi[lengthof(imsi)-1]);
Harald Welte5d1a2202017-12-13 19:51:29 +01003385 var integer i;
Harald Welte6f521d82017-12-11 19:52:02 +01003386
3387 f_init();
Harald Welte6f521d82017-12-11 19:52:02 +01003388
3389 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Harald Weltec3068592018-03-17 19:55:31 +01003390 for (i := 0; i < NUM_BTS; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003391 IPA_RSL[i][0].clear;
Harald Welte5d1a2202017-12-13 19:51:29 +01003392 }
Harald Welte6f521d82017-12-11 19:52:02 +01003393
3394 if (isvalue(rsl_chneed)) {
3395 /* The values of 08.08 3.2.2.36 and 08.58 9.3.40 are luckily identical */
3396 bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
3397 } else {
3398 bssmap_chneed := omit;
3399 }
3400
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003401 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
3402 ts_BSSMAP_Paging(imsi, cid_list, tmsi, bssmap_chneed)));
Harald Welte6f521d82017-12-11 19:52:02 +01003403
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003404 if (not istemplatekind(tmsi, "omit")) {
3405 mi := t_MI_TMSI(tmsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003406 } else {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003407 mi := tr_MI_IMSI(imsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003408 }
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003409
Harald Welte5d1a2202017-12-13 19:51:29 +01003410 for (i := 0; i < sizeof(bts_ids); i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003411 rx_rsl := f_exp_ipa_rx(tr_RSL_PAGING_CMD(mi), idx := {bts_ids[i], 0});
Harald Welte5d1a2202017-12-13 19:51:29 +01003412 /* check channel type, paging group */
3413 if (rx_rsl.ies[1].body.paging_group != paging_group) {
3414 setverdict(fail, "Paging for wrong paging group");
3415 }
3416 if (ispresent(rsl_chneed) and
3417 rx_rsl.ies[3].body.chan_needed.chan_needed != valueof(rsl_chneed)) {
3418 setverdict(fail, "RSL Channel Needed != BSSMAP Channel Needed");
3419 }
Harald Welte6f521d82017-12-11 19:52:02 +01003420 }
Harald Welte2fccd982018-01-31 15:48:19 +01003421 f_sleep(2.0);
Harald Welte5d1a2202017-12-13 19:51:29 +01003422 /* do a quick check on all not-included BTSs if they received paging */
3423 for (i := 0; i < NUM_BTS; i := i + 1) {
3424 timer T := 0.1;
3425 if (f_bts_in_list(i, bts_ids)) {
3426 continue;
3427 }
3428 T.start;
3429 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003430 [] IPA_RSL[i][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003431 setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
3432 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003433 [] IPA_RSL[i][0].receive { repeat; }
Harald Welte5d1a2202017-12-13 19:51:29 +01003434 [] T.timeout { }
3435 }
Harald Welte6f521d82017-12-11 19:52:02 +01003436 }
3437
3438 setverdict(pass);
3439}
3440
Harald Welte5d1a2202017-12-13 19:51:29 +01003441const BtsIdList c_BtsId_all := { 0, 1, 2 };
Harald Welte751d3eb2018-01-31 15:51:06 +01003442const BtsIdList c_BtsId_none := { };
Harald Welte5d1a2202017-12-13 19:51:29 +01003443const BtsIdList c_BtsId_LAC1 := { 0, 1 };
3444const BtsIdList c_BtsId_LAC2 := { 2 };
3445
Harald Welte6f521d82017-12-11 19:52:02 +01003446/* PAGING by IMSI + TMSI */
3447testcase TC_paging_imsi_nochan() runs on test_CT {
3448 var BSSMAP_FIELD_CellIdentificationList cid_list;
3449 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Philipp Maier8c04b0a2018-02-23 13:48:48 +01003450 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, omit);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003451 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003452}
3453
3454/* PAGING by IMSI + TMSI */
3455testcase TC_paging_tmsi_nochan() runs on test_CT {
3456 var BSSMAP_FIELD_CellIdentificationList cid_list;
3457 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003458 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, 'A1B2C301'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003459 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003460}
3461
3462/* Paging with different "channel needed' values */
3463testcase TC_paging_tmsi_any() runs on test_CT {
3464 var BSSMAP_FIELD_CellIdentificationList cid_list;
3465 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003466 f_pageing_helper('001010100000002'H, cid_list, c_BtsId_all, RSL_CHANNEED_ANY, 'A1B2C302'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003467 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003468}
3469testcase TC_paging_tmsi_sdcch() runs on test_CT {
3470 var BSSMAP_FIELD_CellIdentificationList cid_list;
3471 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003472 f_pageing_helper('001010100000003'H, cid_list, c_BtsId_all, RSL_CHANNEED_SDCCH, 'A1B2C303'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003473 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003474}
3475testcase TC_paging_tmsi_tch_f() runs on test_CT {
3476 var BSSMAP_FIELD_CellIdentificationList cid_list;
3477 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003478 f_pageing_helper('001010000000004'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_F, 'A1B2C304'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003479 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003480}
3481testcase TC_paging_tmsi_tch_hf() runs on test_CT {
3482 var BSSMAP_FIELD_CellIdentificationList cid_list;
3483 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003484 f_pageing_helper('001010000000005'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_ForH, 'A1B2C305'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003485 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003486}
3487
3488/* Paging by CGI */
3489testcase TC_paging_imsi_nochan_cgi() runs on test_CT {
3490 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3491 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(cid.mcc, cid.mnc, cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003492 f_pageing_helper('001010000000006'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003493 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003494}
3495
3496/* Paging by LAC+CI */
3497testcase TC_paging_imsi_nochan_lac_ci() runs on test_CT {
3498 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3499 cid_list := { cIl_LAC_CI := { ts_BSSMAP_CI_LAC_CI(cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003500 f_pageing_helper('001010000000007'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003501 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003502}
3503
3504/* Paging by CI */
3505testcase TC_paging_imsi_nochan_ci() runs on test_CT {
3506 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3507 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003508 f_pageing_helper('001010000000008'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003509 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003510}
3511
3512/* Paging by LAI */
3513testcase TC_paging_imsi_nochan_lai() runs on test_CT {
3514 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3515 cid_list := { cIl_LAI := { ts_BSSMAP_CI_LAI(cid.mcc, cid.mnc, cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003516 f_pageing_helper('001010000000009'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003517 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003518}
3519
3520/* Paging by LAC */
3521testcase TC_paging_imsi_nochan_lac() runs on test_CT {
3522 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3523 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003524 f_pageing_helper('001010000000010'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003525 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003526}
3527
3528/* Paging by "all in BSS" */
3529testcase TC_paging_imsi_nochan_all() runs on test_CT {
3530 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3531 cid_list := { cIl_allInBSS := ''O };
Harald Welte5d1a2202017-12-13 19:51:29 +01003532 f_pageing_helper('001010000000011'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003533 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003534}
3535
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003536/* Paging by PLMN+LAC+RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003537testcase TC_paging_imsi_nochan_plmn_lac_rnc() runs on test_CT {
3538 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3539 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 +01003540 f_pageing_helper('001010000000012'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003541 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003542}
Harald Welte6f521d82017-12-11 19:52:02 +01003543
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003544/* Paging by RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003545testcase TC_paging_imsi_nochan_rnc() runs on test_CT {
3546 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3547 cid_list := { cIl_RNC := { int2oct(13, 2) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003548 f_pageing_helper('001010000000013'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003549 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003550}
3551
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003552/* Paging by LAC+RNC; We do not implement; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003553testcase TC_paging_imsi_nochan_lac_rnc() runs on test_CT {
3554 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3555 cid_list := { cIl_LAC_RNC := { ts_BSSMAP_CI_LAC_RNC(cid.lac, 14) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003556 f_pageing_helper('001010000000014'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003557 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003558}
3559
Harald Welte6f521d82017-12-11 19:52:02 +01003560/* Paging on multiple cells (multiple entries in list): Verify all of them page */
Harald Welte751d3eb2018-01-31 15:51:06 +01003561testcase TC_paging_imsi_nochan_lacs() runs on test_CT {
3562 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3563 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(1), ts_BSSMAP_CI_LAC(2) } };
3564 f_pageing_helper('001010000000015'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003565 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003566}
3567
3568/* Paging on empty list: Verify none of them page */
3569testcase TC_paging_imsi_nochan_lacs_empty() runs on test_CT {
3570 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3571 cid_list := { cIl_LAC := { } };
3572 f_pageing_helper('001010000000016'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003573 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003574}
3575
Stefan Sperling049a86e2018-03-20 15:51:00 +01003576/* Paging by CGI with unknown MCC/MNC: Verify nothing is paged. */
3577testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
3578 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3579 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(unknown_cid.mcc, unknown_cid.mnc, unknown_cid.lac, unknown_cid.ci) } };
3580 f_pageing_helper('001010000000006'H, cid_list, c_BtsId_none);
3581 f_shutdown_helper();
3582}
3583
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +01003584/* Send paging response containing invalid (wrongly formatted) MobileIdentity IE. */
3585testcase TC_paging_imsi_nochan_ci_resp_invalid_mi() runs on test_CT {
3586 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3587 var BSSAP_N_CONNECT_ind rx_c_ind;
3588 var DchanTuple dt;
3589 var octetstring rr_pag_resp := '06270003535992617965720000'O;
3590 /* { 06 27 } is { GSM48_PDISC_RR, GSM48_MT_RR_PAG_RESP }
3591 * see 3GPP TS 44.018, table 9.1.25.1
3592 * { 00 } or { 01 } is CKSN + Spare Half Octet, not important
3593 * { 03 53 59 92 } is Mobile Station Classmark
3594 * { 61 79 65 72 00 00 } is the invalid Mobile Identity IE (3GPP TS 24.008, 10.5.1.4),
3595 * Length is 0x61 (97 in decimal).
3596 */
3597
3598 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
3599 f_pageing_helper('001010000000008'H, cid_list, { 0 });
3600
3601 /* Send CHAN RQD and wait for allocation; acknowledge it */
3602 dt.rsl_chan_nr := f_chreq_act_ack();
3603 dt.idx := {0, 0};
3604
3605 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
3606 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), rr_pag_resp));
3607
3608 /* Expevct a CR with a matching Paging response on the A-Interface */
3609 timer T := 5.0;
3610 T.start;
3611 alt {
3612 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
3613 setverdict(pass);
3614 dt.sccp_conn_id := rx_c_ind.connectionId;
3615 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
3616 }
3617 [] BSSAP.receive {
3618 setverdict(fail, "Received unexpected message on A-Interface!");
3619 }
3620 [] T.timeout {
3621 setverdict(fail, "Received nothing on A-Interface!");
3622 }
3623 }
3624
3625 f_perform_clear_test_ct(dt);
3626 f_shutdown_helper();
3627}
3628
Harald Welte6f521d82017-12-11 19:52:02 +01003629/* Verify paging retransmission interval + count */
3630/* Verify paging stops after channel establishment */
Harald Welte6f521d82017-12-11 19:52:02 +01003631/* Test behavior under paging overload */
Harald Welteae026692017-12-09 01:03:01 +01003632
Harald Weltee65d40e2017-12-13 00:09:06 +01003633/* Verify PCH load */
3634testcase TC_paging_imsi_load() runs on test_CT {
3635 var BSSMAP_FIELD_CellIdentificationList cid_list;
3636 timer T := 4.0;
Harald Welte2caa1062018-03-17 18:19:05 +01003637 timer T_retrans := 1.0;
Harald Weltee65d40e2017-12-13 00:09:06 +01003638 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003639 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Weltee65d40e2017-12-13 00:09:06 +01003640
3641 /* tell BSC there is no paging space anymore */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003642 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte3b57ab52018-03-17 18:01:10 +01003643 f_sleep(0.2);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003644 IPA_RSL[0][0].clear;
Harald Weltee65d40e2017-12-13 00:09:06 +01003645
3646 /* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
3647 * there would be 8 retransmissions during 4 seconds */
3648 T.start;
Harald Welte2caa1062018-03-17 18:19:05 +01003649 T_retrans.start;
Harald Weltee65d40e2017-12-13 00:09:06 +01003650 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003651 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Weltee65d40e2017-12-13 00:09:06 +01003652 setverdict(fail, "Received PAGING after LOAD_IND(0)");
Daniel Willmannafce8662018-07-06 23:11:32 +02003653 mtc.stop;
Harald Weltee65d40e2017-12-13 00:09:06 +01003654 }
Harald Welte2caa1062018-03-17 18:19:05 +01003655 [] T_retrans.timeout {
3656 /* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003657 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte2caa1062018-03-17 18:19:05 +01003658 T_retrans.start;
3659 repeat;
3660 }
Harald Weltee65d40e2017-12-13 00:09:06 +01003661 [] T.timeout {
3662 setverdict(pass);
3663 }
3664 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003665
3666 f_shutdown_helper();
Harald Weltee65d40e2017-12-13 00:09:06 +01003667}
3668
Harald Welte235ebf12017-12-15 14:18:16 +01003669/* Verify Paging Counter */
Harald Welte1ff69992017-12-14 12:31:17 +01003670testcase TC_paging_counter() runs on test_CT {
3671 var BSSMAP_FIELD_CellIdentificationList cid_list;
3672 timer T := 4.0;
3673 var integer i;
3674 var integer paging_attempted_bsc;
3675 var integer paging_attempted_bts[NUM_BTS];
Oliver Smith8b343d32021-11-26 13:01:42 +01003676 var integer paging_expired_bsc;
Harald Welte1ff69992017-12-14 12:31:17 +01003677 var integer paging_expired_bts[NUM_BTS];
3678 cid_list := valueof(ts_BSSMAP_CIL_noCell);
3679
3680 f_init();
3681
3682 /* read counters before paging */
3683 paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003684 paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
Harald Welte1ff69992017-12-14 12:31:17 +01003685 for (i := 0; i < NUM_BTS; i := i+1) {
3686 paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
3687 paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
3688 }
3689
3690 f_pageing_helper('001230000000001'H, cid_list, c_BtsId_all);
3691
3692 /* expect the attempted pages on BSC and each BTSs to have incremented by one */
3693 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", paging_attempted_bsc+1);
3694 for (i := 0; i < NUM_BTS; i := i+1) {
3695 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted",
3696 paging_attempted_bts[i]+1);
3697 }
3698
3699 /* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
3700 f_sleep(12.0);
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003701 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
Harald Welte1ff69992017-12-14 12:31:17 +01003702 for (i := 0; i < NUM_BTS; i := i+1) {
3703 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
3704 paging_expired_bts[i]+1);
3705 }
Harald Welte1ff69992017-12-14 12:31:17 +01003706
Philipp Maier282ca4b2018-02-27 17:17:00 +01003707 f_shutdown_helper();
Harald Welte1ff69992017-12-14 12:31:17 +01003708}
3709
3710
Harald Welte10985002017-12-12 09:29:15 +01003711/* Verify paging stops after A-RESET */
3712testcase TC_paging_imsi_a_reset() runs on test_CT {
3713 var BSSMAP_FIELD_CellIdentificationList cid_list;
3714 timer T := 3.0;
3715 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003716 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Welte10985002017-12-12 09:29:15 +01003717
3718 /* Perform a BSSMAP Reset and wait for ACK */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003719 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 +01003720 alt {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003721 [] 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 +01003722 [] BSSAP.receive { repeat; }
3723 }
3724
Daniel Willmanncbef3982018-07-30 09:22:40 +02003725 /* Wait to avoid a possible race condition if a paging message is
3726 * received right before the reset ACK. */
3727 f_sleep(0.2);
3728
Harald Welte10985002017-12-12 09:29:15 +01003729 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Philipp Maier1e6b4422018-02-23 14:02:13 +01003730 for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003731 IPA_RSL[i][0].clear;
Philipp Maier1e6b4422018-02-23 14:02:13 +01003732 }
Harald Welte10985002017-12-12 09:29:15 +01003733
3734 /* Wait for 3 seconds if any more PAGING CMD are received on RSL */
3735 T.start;
3736 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003737 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte10985002017-12-12 09:29:15 +01003738 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003739 mtc.stop;
Harald Welte10985002017-12-12 09:29:15 +01003740 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003741 [] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003742 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003743 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003744 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003745 [] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003746 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003747 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003748 }
Harald Welte10985002017-12-12 09:29:15 +01003749 [] T.timeout {
3750 setverdict(pass);
3751 }
3752 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003753
3754 f_shutdown_helper();
Harald Welte10985002017-12-12 09:29:15 +01003755}
Harald Welteae026692017-12-09 01:03:01 +01003756
Philipp Maierf45824a2019-08-14 14:44:10 +02003757/* Verify how we handle unsolicited Paging Response. In case of an unsolicit
3758 * paging response we can not know which MSC is in charge, so we will blindly
3759 * pick the first configured MSC. This behavior is required in order to make
3760 * MT-CSFB calls working because in those cases the BSC can not know that the
3761 * MSC has already paged the subscriver via SGs. So any MT-CSFB call will look
3762 * like an unsolicited Paging Response to the MSC.
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003763 */
3764testcase TC_paging_resp_unsol() runs on test_CT {
3765
3766 f_init(1);
Philipp Maierf45824a2019-08-14 14:44:10 +02003767 timer T := 5.0;
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003768
3769 var BSSAP_N_CONNECT_ind rx_c_ind;
3770 var DchanTuple dt;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02003771 var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010008880018'H)));
Philipp Maierf45824a2019-08-14 14:44:10 +02003772 var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003773
3774 /* Send CHAN RQD and wait for allocation; acknowledge it */
3775 dt.rsl_chan_nr := f_chreq_act_ack();
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003776 dt.idx := {0, 0};
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003777
3778 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
Pau Espin Pedrole8a51012023-01-03 11:59:59 +01003779 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 +01003780
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003781
Philipp Maierf45824a2019-08-14 14:44:10 +02003782 /* Expevct a CR with a matching Paging response on the A-Interface */
3783 T.start;
3784 alt {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003785 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
Philipp Maierf45824a2019-08-14 14:44:10 +02003786 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003787 dt.sccp_conn_id := rx_c_ind.connectionId;
3788 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
Philipp Maierf45824a2019-08-14 14:44:10 +02003789 }
3790 [] BSSAP.receive {
3791 setverdict(fail, "Received unexpected message on A-Interface!");
3792 }
3793 [] T.timeout {
3794 setverdict(fail, "Received nothing on A-Interface!");
3795 }
3796 }
3797
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003798 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003799 f_shutdown_helper();
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003800}
3801
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003802/* Verify BSC can schedule N paging requests under one minute if BTS buffer is good enough */
3803function f_TC_paging_Nreq(integer num_subscribers, boolean send_pag_load_ind) runs on test_CT {
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003804 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003805 var Hexstrings imsis := {};
3806 var Booleans rx_paging_done := {};
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003807 var integer rx_paging_num := 0;
3808 var integer i;
3809 timer T_rx := 60.0;
3810 timer T_load_ind := 1.0;
3811
3812 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003813 imsis := imsis & {f_gen_imsi(i)};
3814 rx_paging_done := rx_paging_done & { false };
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003815 }
3816
3817 f_init(1, guard_timeout := 100.0);
3818
3819 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003820 IPA_RSL[0][0].clear;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003821 if (send_pag_load_ind) {
3822 /* Tell there's plenty of space at the BTS (UINT16_MAX): */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003823 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(65535));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003824 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003825
3826 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003827 /* Page on LAC-CI of BTS0: */
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003828 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 +02003829 ts_BSSMAP_Paging(imsis[i], valueof(ts_BSSMAP_CIL_LAC_CI({ts_BSSMAP_CI_LAC_CI(1, 0)})),
3830 omit, omit)));
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003831 }
3832
3833 T_rx.start;
3834 T_load_ind.start;
3835 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003836 [] 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 +02003837 var hexstring imsi := rx_rsl_ud.rsl.ies[2].body.ms_identity.mobileIdentityV.oddEvenInd_identity.imsi.digits;
3838 var hexstring imsi_suffix := substr(imsi, lengthof(imsi)-6, 6);
3839 var charstring imsi_str := hex2str(imsi_suffix);
3840 var integer imsi_idx := str2int(imsi_str);
3841 if (rx_paging_done[imsi_idx] == false) {
3842 rx_paging_done[imsi_idx] := true;
3843 rx_paging_num := rx_paging_num + 1;
Pau Espin Pedrolef7ef632022-04-25 13:34:57 +02003844 } else {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003845 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 +02003846 mtc.stop;
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003847 }
3848 if (rx_paging_num < num_subscribers) {
3849 repeat;
3850 }
3851 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003852 [] IPA_RSL[0][0].receive { repeat; }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003853 [] T_load_ind.timeout {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003854 log("[CCH Load Ind timer] received paging requests so far: ", rx_paging_num);
3855 if (send_pag_load_ind) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003856 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(40));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003857 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003858 T_load_ind.start;
3859 repeat;
3860 }
3861 [] T_rx.timeout {
3862 setverdict(fail, "Timeout expecting paging requests, so far ", rx_paging_num);
3863 mtc.stop;
3864 }
3865 }
3866
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003867 /* Drop OML connection to have all paging requests flushed: */
3868 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
3869
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003870 f_shutdown_helper();
3871}
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003872/* Verify BSC can schedule 500 paging requests under one minute if BTS buffer is good enough */
3873testcase TC_paging_500req() runs on test_CT {
3874 f_TC_paging_Nreq(500, true);
3875}
3876/* Same as TC_paging_500req, but without sending CCCH Load Indication, which
3877 * means BTS is always under CCH Load Threshold, aka capable of sending tons of requests.
3878 * Since No CCCH Load Ind, BSC uses a conservative estimation of BTS load, which
3879 * for current config yields ~8req/sec, so 480req/min maximum. */
3880testcase TC_paging_450req_no_paging_load_ind() runs on test_CT {
3881 f_TC_paging_Nreq(450, false);
3882}
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003883
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003884/* Test RSL link drop causes counter increment */
3885testcase TC_rsl_drop_counter() runs on test_CT {
3886 var integer rsl_fail;
3887
Harald Welte89d42e82017-12-17 16:42:41 +01003888 f_init(1);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003889
3890 rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
3891
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003892 f_ipa_rsl_stop(bts[0][0].rsl);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003893
3894 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
3895
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003896 f_shutdown_helper();
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003897}
3898
3899/* TODO: Test OML link drop causes counter increment */
3900
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003901/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
3902function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003903 var IPA_Client client;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003904 timer T := 10.0;
3905
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003906 client.id := "IPA-BTS0-TRX0-RSL";
3907 client.vc_IPA := IPA_Emulation_CT.create(client.id & "-IPA") alive;
3908 client.ccm_pars := c_IPA_default_ccm_pars;
3909 client.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
3910 client.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003911
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01003912 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003913
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003914 f_init_mgcp(0, "VirtMGW");
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003915
3916 /* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003917 map(client.vc_IPA:IPA_PORT, system:IPA);
3918 connect(client.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0][0]);
3919 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 +01003920
3921 /* wait for IPA OML link to connect and then disconnect */
3922 T.start;
3923 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003924 [] IPA_RSL[0][0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003925 T.stop;
3926 return true;
3927 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003928 [] IPA_RSL[0][0].receive { repeat }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003929 [] T.timeout {
Daniel Willmannafce8662018-07-06 23:11:32 +02003930 return false;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003931 }
3932 }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003933 return false;
3934}
3935
3936/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3937testcase TC_rsl_unknown_unit_id() runs on test_CT {
3938 if (f_ipa_unknown_unit_id(mp_bsc_rsl_port)) {
3939 setverdict(pass);
3940 } else {
3941 setverdict(fail, "Timeout RSL waiting for connection to close");
3942 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003943 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003944}
3945
3946
3947/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3948testcase TC_oml_unknown_unit_id() runs on test_CT {
3949 if (f_ipa_unknown_unit_id(mp_bsc_oml_port)) {
3950 setverdict(pass);
3951 } else {
3952 setverdict(fail, "Timeout OML waiting for connection to close");
3953 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003954 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003955}
3956
3957
Harald Weltec1a2fff2017-12-17 11:06:19 +01003958/***********************************************************************
Harald Welte6811d102019-04-14 22:23:14 +02003959 * "New world" test cases using RSL_Emulation + RAN_Emulation
Harald Weltec1a2fff2017-12-17 11:06:19 +01003960 ***********************************************************************/
3961
Harald Welte6811d102019-04-14 22:23:14 +02003962import from RAN_Emulation all;
Harald Welte47cd0e32020-08-21 12:39:11 +02003963import from BSSAP_LE_Emulation all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01003964import from RSL_Emulation all;
3965import from MSC_ConnectionHandler all;
3966
3967type function void_fn(charstring id) runs on MSC_ConnHdlr;
3968
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003969/* helper function to create and connect a MSC_ConnHdlr component
3970 * TODO: allow connecting to TRX1..N, not only TRX0 */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003971private 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 +02003972 connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003973 connect(vc_conn:RSL, bts[0][0].rsl.vc_RSL:CLIENT_PT);
3974 connect(vc_conn:RSL_PROC, bts[0][0].rsl.vc_RSL:RSL_PROC);
3975 if (isvalue(bts[1][0])) {
3976 connect(vc_conn:RSL1, bts[1][0].rsl.vc_RSL:CLIENT_PT);
3977 connect(vc_conn:RSL1_PROC, bts[1][0].rsl.vc_RSL:RSL_PROC);
Philipp Maier956a92f2018-02-16 10:58:07 +01003978 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003979 if (isvalue(bts[2][0])) {
3980 connect(vc_conn:RSL2, bts[2][0].rsl.vc_RSL:CLIENT_PT);
3981 connect(vc_conn:RSL2_PROC, bts[2][0].rsl.vc_RSL:RSL_PROC);
Neels Hofmeyr91401012019-07-11 00:42:35 +02003982 }
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003983 connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02003984 if (mp_enable_lcs_tests) {
3985 connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
3986 connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
3987 }
Daniel Willmannebdecc02020-08-12 15:30:17 +02003988 connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003989 connect(vc_conn:MGCP_PROC, vc_MGCP[mgwpool_idx]:MGCP_PROC);
3990 connect(vc_conn:MGCP, vc_MGCP[mgwpool_idx]:MGCP_CLIENT);
3991 connect(vc_conn:MGCP_MULTI, vc_MGCP[mgwpool_idx]:MGCP_CLIENT_MULTI);
Harald Welte336820c2018-05-31 20:34:52 +02003992}
3993
Neels Hofmeyrda436782021-07-20 22:09:06 +02003994function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
Harald Welte336820c2018-05-31 20:34:52 +02003995runs on test_CT return MSC_ConnHdlr {
3996 var charstring id := testcasename();
3997 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003998 var integer bssap_idx := 0;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003999 var integer mgwpool_idx := 0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004000 if (isvalue(pars)) {
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004001 var TestHdlrParams pars_val := valueof(pars);
4002 bssap_idx := pars_val.mscpool.bssap_idx;
4003 mgwpool_idx := pars_val.mgwpool_idx;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004004 }
Harald Welte336820c2018-05-31 20:34:52 +02004005 vc_conn := MSC_ConnHdlr.create(id);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004006 f_connect_handler(vc_conn, bssap_idx, mgwpool_idx);
Neels Hofmeyrda436782021-07-20 22:09:06 +02004007 return vc_conn;
4008}
4009
4010function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
4011runs on test_CT return MSC_ConnHdlr {
4012 var charstring id := testcasename();
Harald Weltea0630032018-03-20 21:09:55 +01004013 vc_conn.start(f_handler_init(fn, id, pars));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004014 return vc_conn;
4015}
4016
Neels Hofmeyrda436782021-07-20 22:09:06 +02004017function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
4018runs on test_CT return MSC_ConnHdlr {
4019 return f_start_handler_run(f_start_handler_create(pars), fn, pars);
4020}
4021
Harald Weltea0630032018-03-20 21:09:55 +01004022/* first function inside ConnHdlr component; sets g_pars + starts function */
4023private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
4024runs on MSC_ConnHdlr {
4025 if (isvalue(pars)) {
4026 g_pars := valueof(pars);
4027 }
4028 fn.apply(id);
4029}
4030
Oliver Smith26a3db72021-07-09 13:51:29 +02004031private function f_vty_encryption_a5(charstring options) runs on test_CT {
4032 f_vty_transceive(BSCVTY, "configure terminal");
4033 f_vty_transceive(BSCVTY, "network");
4034 f_vty_transceive(BSCVTY, "encryption a5 " & options);
4035 f_vty_transceive(BSCVTY, "exit");
4036 f_vty_transceive(BSCVTY, "exit");
4037}
4038
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004039const charstring VTY_A5_DEFAULT := "0 1 3";
4040
Oliver Smith26a3db72021-07-09 13:51:29 +02004041private function f_vty_encryption_a5_reset() runs on test_CT {
4042 /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004043 f_vty_encryption_a5(VTY_A5_DEFAULT);
Oliver Smith26a3db72021-07-09 13:51:29 +02004044}
4045
Harald Welte3c86ea02018-05-10 22:28:05 +02004046/* Establish signalling channel (non-assignment case) followed by cipher mode */
4047private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004048 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4049 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte3c86ea02018-05-10 22:28:05 +02004050 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Philipp Maier23000732018-05-18 11:25:37 +02004051 ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode := omit;
4052 ass_cmd.pdu.bssmap.assignmentRequest.aoIPTransportLayer := omit;
4053 exp_compl.pdu.bssmap.assignmentComplete.circuitIdentityCode := omit;
4054 exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
Harald Welte3c86ea02018-05-10 22:28:05 +02004055
Philipp Maier23000732018-05-18 11:25:37 +02004056 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004057 f_perform_clear();
Harald Welte3c86ea02018-05-10 22:28:05 +02004058}
4059testcase TC_ciph_mode_a5_0() runs on test_CT {
4060 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004061 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004062 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
4063
4064 f_init(1, true);
4065 f_sleep(1.0);
4066 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4067 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004068 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004069}
4070testcase TC_ciph_mode_a5_1() runs on test_CT {
4071 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004072 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004073 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
4074
4075 f_init(1, true);
4076 f_sleep(1.0);
4077 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4078 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004079 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004080}
Oliver Smith50b98122021-07-09 15:00:28 +02004081/* OS#4975: verify that A5/2 is preferred over A5/0 */
4082testcase TC_ciph_mode_a5_2_0() runs on test_CT {
4083 var MSC_ConnHdlr vc_conn;
4084 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4085
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004086 pars.encr := f_encr_params('05'O, '04'O); /* A5/0 and A5/2 (0x01|0x04)*/
Oliver Smith50b98122021-07-09 15:00:28 +02004087
4088 f_init(1, true);
4089 f_vty_encryption_a5("0 1 2 3");
4090 f_sleep(1.0);
4091 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4092 vc_conn.done;
4093 f_vty_encryption_a5_reset();
4094 f_shutdown_helper();
4095}
Oliver Smith1dff88d2021-07-09 08:45:51 +02004096/* OS#4975: verify that A5/1 is preferred over A5/2 */
4097testcase TC_ciph_mode_a5_2_1() runs on test_CT {
4098 var MSC_ConnHdlr vc_conn;
4099 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4100
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004101 pars.encr := f_encr_params('06'O, '02'O); /* A5/1 and A5/2 (0x02|0x04)*/
Oliver Smith1dff88d2021-07-09 08:45:51 +02004102
4103 f_init(1, true);
4104 f_vty_encryption_a5("1 2");
4105 f_sleep(1.0);
4106 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4107 vc_conn.done;
4108 f_vty_encryption_a5_reset();
4109 f_shutdown_helper();
4110}
Harald Welte3c86ea02018-05-10 22:28:05 +02004111testcase TC_ciph_mode_a5_3() runs on test_CT {
4112 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004113 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004114 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
4115
4116 f_init(1, true);
4117 f_sleep(1.0);
4118 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4119 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004120 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004121}
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004122/* Establish a Signalling channel with A5/4 encryption. */
4123testcase TC_ciph_mode_a5_4() runs on test_CT {
4124 var MSC_ConnHdlr vc_conn;
4125 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4126 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Harald Welte3c86ea02018-05-10 22:28:05 +02004127
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004128 f_init(1, true);
Oliver Smith26a3db72021-07-09 13:51:29 +02004129 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004130 f_sleep(1.0);
4131 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4132 vc_conn.done;
Oliver Smith26a3db72021-07-09 13:51:29 +02004133 f_vty_encryption_a5_reset();
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004134 f_shutdown_helper();
4135}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004136/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
4137private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
4138 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4139 var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
4140 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4141 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4142
4143 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004144 f_perform_clear();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004145}
4146testcase TC_assignment_aoip_tla_v6() runs on test_CT {
4147 var MSC_ConnHdlr vc_conn;
4148 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4149
4150 f_init(1, true);
4151 f_sleep(1.0);
4152 vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
4153 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004154 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004155}
4156
Harald Welte3c86ea02018-05-10 22:28:05 +02004157
4158/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
Harald Welte651fcdc2018-05-10 20:23:16 +02004159private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004160 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4161 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004162
Harald Welte552620d2017-12-16 23:21:36 +01004163 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4164 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte73cd2712017-12-17 00:44:52 +01004165
Harald Weltea0630032018-03-20 21:09:55 +01004166 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004167 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004168}
Harald Welte552620d2017-12-16 23:21:36 +01004169testcase TC_assignment_fr_a5_0() runs on test_CT {
4170 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004171 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004172 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
Harald Welte552620d2017-12-16 23:21:36 +01004173
Harald Welte89d42e82017-12-17 16:42:41 +01004174 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004175 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004176 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004177 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004178 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004179}
Harald Welte552620d2017-12-16 23:21:36 +01004180testcase TC_assignment_fr_a5_1() runs on test_CT {
Harald Weltec1a2fff2017-12-17 11:06:19 +01004181 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004182 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004183 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004184
Harald Welte89d42e82017-12-17 16:42:41 +01004185 f_init(1, true);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004186 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004187 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4188 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004189 f_shutdown_helper();
Harald Welte651fcdc2018-05-10 20:23:16 +02004190}
4191testcase TC_assignment_fr_a5_3() runs on test_CT {
4192 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004193 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004194 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004195
Harald Welte651fcdc2018-05-10 20:23:16 +02004196 f_init(1, true);
4197 f_sleep(1.0);
4198 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004199 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004200 f_shutdown_helper();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004201}
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004202/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
4203testcase TC_assignment_fr_a5_4() runs on test_CT {
4204 var MSC_ConnHdlr vc_conn;
4205 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4206 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
4207
4208 f_init(1, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02004209 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004210 f_sleep(1.0);
4211 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4212 vc_conn.done;
Oliver Smith7eabd312021-07-12 14:18:56 +02004213 f_vty_encryption_a5_reset();
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004214 f_shutdown_helper();
4215}
Harald Weltec1a2fff2017-12-17 11:06:19 +01004216
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +02004217/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
4218testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
4219 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4220 var MSC_ConnHdlr vc_conn;
4221
4222 f_init(1, true);
4223 f_sleep(1.0);
4224
4225 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
4226 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
4227 vc_conn.done;
4228 f_shutdown_helper();
4229}
4230
Harald Welte552620d2017-12-16 23:21:36 +01004231/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
4232private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004233 g_pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004234 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02004235 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004236
4237 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02004238 /* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
4239
Harald Weltea0630032018-03-20 21:09:55 +01004240 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004241 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004242}
Harald Welte552620d2017-12-16 23:21:36 +01004243testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
4244 var MSC_ConnHdlr vc_conn;
4245
Harald Welte89d42e82017-12-17 16:42:41 +01004246 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004247 f_sleep(1.0);
4248
Harald Welte8863fa12018-05-10 20:15:27 +02004249 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
Harald Welte552620d2017-12-16 23:21:36 +01004250 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004251 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004252}
4253
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004254private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
4255 var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
4256 var PDU_BSSAP exp_ass_req := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004257
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004258 exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4259 exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4260
4261 /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
4262
4263 var BSSMAP_FIELD_CodecType codecType;
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004264
4265 codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
4266 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
4267
4268 f_create_chan_and_exp();
4269 /* we should now have a COMPL_L3 at the MSC */
4270
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004271 /* Start ciphering, expect Cipher Mode Reject */
Neels Hofmeyr6c388f22021-06-11 02:36:56 +02004272 f_cipher_mode(g_pars.encr, exp_fail := true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004273 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004274}
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004275testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
4276 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004277 var MSC_ConnHdlr vc_conn;
4278
Harald Welte89d42e82017-12-17 16:42:41 +01004279 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004280 f_sleep(1.0);
4281
Neels Hofmeyr0588cad2021-06-11 01:38:18 +02004282 pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004283 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004284 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004285 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004286}
4287
4288
Harald Welte4532e0a2017-12-23 02:05:44 +01004289private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004290 g_pars := f_gen_test_hdlr_pars();
Harald Welte4532e0a2017-12-23 02:05:44 +01004291 var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
Philipp Maier48604732018-10-09 15:00:37 +02004292 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte4532e0a2017-12-23 02:05:44 +01004293 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004294
4295 f_statsd_reset();
Harald Weltea0630032018-03-20 21:09:55 +01004296 f_establish_fully(ass_cmd, exp_compl);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004297
4298 var StatsDExpects expect := {
Daniel Willmannc5398f72020-09-21 10:41:35 +02004299 { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
4300 { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
Daniel Willmannebdecc02020-08-12 15:30:17 +02004301 { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
4302 { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
4303 };
4304 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004305 f_perform_clear();
Harald Welte4532e0a2017-12-23 02:05:44 +01004306}
4307
4308testcase TC_assignment_sign() runs on test_CT {
4309 var MSC_ConnHdlr vc_conn;
4310
4311 f_init(1, true);
4312 f_sleep(1.0);
4313
Harald Welte8863fa12018-05-10 20:15:27 +02004314 vc_conn := f_start_handler(refers(f_tc_assignment_sign));
Harald Welte4532e0a2017-12-23 02:05:44 +01004315 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004316 f_shutdown_helper();
Harald Welte4532e0a2017-12-23 02:05:44 +01004317}
4318
Harald Welte60aa5762018-03-21 19:33:13 +01004319/***********************************************************************
4320 * Codec (list) testing
4321 ***********************************************************************/
4322
4323/* check if the given rsl_mode is compatible with the a_elem */
4324private function f_match_codec(BSSMAP_FIELD_CodecElement a_elem, RSL_IE_ChannelMode rsl_mode)
4325return boolean {
4326 select (a_elem.codecType) {
4327 case (GSM_FR) {
4328 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1))) {
4329 return true;
4330 }
4331 }
4332 case (GSM_HR) {
4333 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1))) {
4334 return true;
4335 }
4336 }
4337 case (GSM_EFR) {
4338 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2))) {
4339 return true;
4340 }
4341 }
4342 case (FR_AMR) {
4343 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3))) {
4344 return true;
4345 }
4346 }
4347 case (HR_AMR) {
4348 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3))) {
4349 return true;
4350 }
4351 }
4352 case else { }
4353 }
4354 return false;
4355}
4356
4357/* check if the given rsl_mode is compatible with the a_list */
4358private function f_match_codecs(BSSMAP_IE_SpeechCodecList a_list, RSL_IE_ChannelMode rsl_mode)
4359return boolean {
4360 for (var integer i := 0; i < sizeof(a_list); i := i+1) {
4361 if (f_match_codec(a_list.codecElements[i], rsl_mode)) {
4362 return true;
4363 }
4364 }
4365 return false;
4366}
4367
4368/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
Philipp Maier61f6b572018-07-06 14:03:38 +02004369function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
Harald Welte60aa5762018-03-21 19:33:13 +01004370return BSSMAP_IE_ChannelType {
4371 /* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
4372 var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
4373 select (a_elem.codecType) {
4374 case (GSM_FR) {
4375 ret.channelRateAndType := ChRate_TCHF;
4376 ret.speechId_DataIndicator := Spdi_TCHF_FR;
4377 }
4378 case (GSM_HR) {
4379 ret.channelRateAndType := ChRate_TCHH;
4380 ret.speechId_DataIndicator := Spdi_TCHH_HR;
4381 }
4382 case (GSM_EFR) {
4383 ret.channelRateAndType := ChRate_TCHF;
4384 ret.speechId_DataIndicator := Spdi_TCHF_EFR;
4385 }
4386 case (FR_AMR) {
4387 ret.channelRateAndType := ChRate_TCHF;
4388 ret.speechId_DataIndicator := Spdi_TCHF_AMR;
4389 }
4390 case (HR_AMR) {
4391 ret.channelRateAndType := ChRate_TCHH;
4392 ret.speechId_DataIndicator := Spdi_TCHH_AMR;
4393 }
4394 case else {
4395 setverdict(fail, "Unsupported codec ", a_elem);
Daniel Willmannafce8662018-07-06 23:11:32 +02004396 mtc.stop;
Harald Welte60aa5762018-03-21 19:33:13 +01004397 }
4398 }
4399 return ret;
4400}
4401
Harald Weltea63b9102018-03-22 20:36:16 +01004402private function f_rsl_chmod_tmpl_from_codec(BSSMAP_FIELD_CodecElement a_elem)
4403return template RSL_IE_Body {
4404 var template RSL_IE_Body mode_ie := {
4405 chan_mode := {
4406 len := ?,
4407 reserved := ?,
4408 dtx_d := ?,
4409 dtx_u := ?,
4410 spd_ind := RSL_SPDI_SPEECH,
4411 ch_rate_type := -,
Oliver Smith0033b122023-02-28 13:30:53 +01004412 u := { speech := - }
Harald Weltea63b9102018-03-22 20:36:16 +01004413 }
4414 }
4415
4416 select (a_elem.codecType) {
4417 case (GSM_FR) {
4418 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004419 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004420 }
4421 case (GSM_HR) {
4422 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004423 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004424 }
4425 case (GSM_EFR) {
4426 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004427 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM2;
Harald Weltea63b9102018-03-22 20:36:16 +01004428 }
4429 case (FR_AMR) {
4430 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004431 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004432 }
4433 case (HR_AMR) {
4434 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004435 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004436 }
4437 }
4438 return mode_ie;
4439}
4440
Harald Welte60aa5762018-03-21 19:33:13 +01004441type record CodecListTest {
4442 BSSMAP_IE_SpeechCodecList codec_list,
4443 charstring id
4444}
4445type record of CodecListTest CodecListTests
4446
4447private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004448 f_assignment_codec(id);
4449}
4450
4451private function f_assignment_codec(charstring id, boolean do_perform_clear := true) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02004452 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02004453 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welte60aa5762018-03-21 19:33:13 +01004454
4455 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004456 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte79f3f542018-05-25 20:02:37 +02004457 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4458 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
4459 g_pars.ass_codec_list.codecElements[0];
Philipp Maierd0e64b02019-03-13 14:15:23 +01004460 if (isvalue(g_pars.expect_mr_s0_s7)) {
4461 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
4462 g_pars.expect_mr_s0_s7;
4463 }
Harald Welte79f3f542018-05-25 20:02:37 +02004464 }
Harald Welte60aa5762018-03-21 19:33:13 +01004465 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4466 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
Harald Welte60aa5762018-03-21 19:33:13 +01004467 log("expecting ASS COMPL like this: ", exp_compl);
4468
4469 f_establish_fully(ass_cmd, exp_compl);
Harald Weltea63b9102018-03-22 20:36:16 +01004470
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004471 if (not g_pars.expect_channel_mode_modify) {
4472 /* Verify that the RSL-side activation actually matches our expectations */
4473 var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
Harald Weltea63b9102018-03-22 20:36:16 +01004474
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004475 var RSL_IE_Body mode_ie;
4476 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
4477 setverdict(fail, "Couldn't find CHAN_MODE IE");
Daniel Willmannafce8662018-07-06 23:11:32 +02004478 mtc.stop;
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004479 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004480 var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
4481 if (not match(mode_ie, t_mode_ie)) {
4482 log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
4483 setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004484 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004485
4486 var RSL_IE_Body mr_conf;
4487 if (g_pars.expect_mr_conf_ie != omit) {
4488 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
4489 setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
4490 mtc.stop;
4491 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004492 log("found RSL MR CONFIG IE: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004493
4494 if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
Vadim Yanitskiy8b189372022-09-14 17:31:17 +07004495 setverdict(fail, "RSL MR CONFIG IE does not match expectation. ",
4496 "Expected: ", g_pars.expect_mr_conf_ie, ", got: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004497 }
4498 } else {
4499 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
4500 log("found RSL MR CONFIG IE: ", mr_conf);
4501 setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
4502 mtc.stop;
4503 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004504 }
4505 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004506
4507 if (do_perform_clear) {
4508 f_perform_clear();
4509 }
Harald Welte60aa5762018-03-21 19:33:13 +01004510}
4511
Philipp Maierd0e64b02019-03-13 14:15:23 +01004512private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
4513
4514 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4515 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4516
4517 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004518 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maierd0e64b02019-03-13 14:15:23 +01004519 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4520 }
4521 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4522 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
4523 log("expecting ASS FAIL like this: ", exp_fail);
4524
4525 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004526 f_perform_clear();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004527}
4528
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004529const CounterNameVals counternames_bsc_bts_assignment := {
4530 { "assignment:attempted", 0 },
4531 { "assignment:completed", 0 },
4532 { "assignment:stopped", 0 },
4533 { "assignment:no_channel", 0 },
4534 { "assignment:timeout", 0 },
4535 { "assignment:failed", 0 },
4536 { "assignment:error", 0 }
4537};
4538
4539const CounterNameVals counternames_bts_assignment := {
4540 { "assignment:attempted_sign", 0 },
4541 { "assignment:attempted_speech", 0 },
4542 { "assignment:completed_sign", 0 },
4543 { "assignment:completed_speech", 0 },
4544 { "assignment:stopped_sign", 0 },
4545 { "assignment:stopped_speech", 0 },
4546 { "assignment:no_channel_sign", 0 },
4547 { "assignment:no_channel_speech", 0 },
4548 { "assignment:timeout_sign", 0 },
4549 { "assignment:timeout_speech", 0 },
4550 { "assignment:failed_sign", 0 },
4551 { "assignment:failed_speech", 0 },
4552 { "assignment:error_sign", 0 },
4553 { "assignment:error_speech", 0 }
4554};
4555
4556function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
4557 var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
4558 f_ctrs_bts_init(bts_count, bts_names);
4559 f_ctrs_bsc_init(counternames_bsc_bts_assignment);
4560}
4561
Harald Welte60aa5762018-03-21 19:33:13 +01004562testcase TC_assignment_codec_fr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004563 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004564 var MSC_ConnHdlr vc_conn;
4565
4566 f_init(1, true);
4567 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004568 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004569
4570 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004571 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004572 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004573
4574 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4575 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4576 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4577 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4578 f_ctrs_bts_verify();
4579
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004580 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004581}
4582
4583testcase TC_assignment_codec_hr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004584 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004585 var MSC_ConnHdlr vc_conn;
4586
4587 f_init(1, true);
4588 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004589 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004590
4591 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004592 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004593 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004594
4595 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4596 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4597 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4598 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4599 f_ctrs_bts_verify();
4600
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004601 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004602}
4603
4604testcase TC_assignment_codec_efr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004605 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004606 var MSC_ConnHdlr vc_conn;
4607
4608 f_init(1, true);
4609 f_sleep(1.0);
4610
4611 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004612 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004613 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004614 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004615}
4616
Philipp Maierd0e64b02019-03-13 14:15:23 +01004617/* Allow 5,90k only (current default config) */
4618private function f_allow_amr_rate_5_90k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004619 f_vty_cfg_msc(BSCVTY, 0, {
4620 "amr-config 12_2k forbidden",
4621 "amr-config 10_2k forbidden",
4622 "amr-config 7_95k forbidden",
4623 "amr-config 7_40k forbidden",
4624 "amr-config 6_70k forbidden",
4625 "amr-config 5_90k allowed",
4626 "amr-config 5_15k forbidden",
4627 "amr-config 4_75k forbidden"
4628 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004629}
4630
4631/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
4632 * ("Config-NB-Code = 1") */
4633private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004634 f_vty_cfg_msc(BSCVTY, 0, {
4635 "amr-config 12_2k allowed",
4636 "amr-config 10_2k forbidden",
4637 "amr-config 7_95k forbidden",
4638 "amr-config 7_40k allowed",
4639 "amr-config 6_70k forbidden",
4640 "amr-config 5_90k allowed",
4641 "amr-config 5_15k forbidden",
4642 "amr-config 4_75k allowed"
4643 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004644}
4645
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004646private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
4647 var charstring tch;
4648 if (fr) {
4649 tch := "tch-f";
4650 } else {
4651 tch := "tch-h";
4652 }
4653 f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
4654}
4655
4656/* Set the AMR start-mode for this TCH back to the default configuration. */
4657private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
4658 f_vty_amr_start_mode_set(fr, "auto");
4659}
4660
Harald Welte60aa5762018-03-21 19:33:13 +01004661testcase TC_assignment_codec_amr_f() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004662 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004663 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004664
4665 /* Note: This setups the codec configuration. The parameter payload in
4666 * mr_conf must be consistant with the parameter codecElements in pars
4667 * and also must match the amr-config in osmo-bsc.cfg! */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004668 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004669 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004670 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004671 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004672
Harald Welte60aa5762018-03-21 19:33:13 +01004673 f_init(1, true);
4674 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004675 f_vty_amr_start_mode_set(true, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004676 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004677
Harald Welte8863fa12018-05-10 20:15:27 +02004678 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004679 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004680
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004681 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4682 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4683 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4684 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4685 f_ctrs_bts_verify();
4686
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004687 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004688 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004689}
4690
4691testcase TC_assignment_codec_amr_h() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004692 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004693 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004694
4695 /* See note above */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004696 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004697 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004698 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004699 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004700
Harald Welte60aa5762018-03-21 19:33:13 +01004701 f_init(1, true);
4702 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004703 f_vty_amr_start_mode_set(false, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004704 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004705
Harald Welte8863fa12018-05-10 20:15:27 +02004706 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004707 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004708
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004709 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4710 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4711 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4712 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4713 f_ctrs_bts_verify();
4714
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004715 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004716 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004717}
4718
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004719/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
4720testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
4721 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4722 var MSC_ConnHdlr vc_conn;
4723
4724 f_init(1, true);
4725 f_sleep(1.0);
4726
4727 /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
4728 * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
4729 * expecting a Channel Mode Modify if the channel type is compatible. */
4730 f_disable_all_sdcch();
4731 f_disable_all_tch_h();
4732
4733 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4734 pars.expect_channel_mode_modify := true;
4735 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4736 vc_conn.done;
4737
4738 f_enable_all_sdcch();
4739 f_enable_all_tch();
4740 f_shutdown_helper();
4741}
4742
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004743/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
4744testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
4745 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4746 var MSC_ConnHdlr vc_conn;
4747
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004748 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4749 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
4750 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy36fe9582022-09-14 15:25:04 +07004751 pars.expect_mr_conf_ie := c_mr_conf_5_90;
4752 pars.expect_mr_conf_ie.multirate_cfg.icmi := false; /* expect ICMI=0, smod=00: */
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004753
4754 f_init(1, true);
4755 f_sleep(1.0);
4756
4757 /* First set nonzero start mode bits */
4758 f_vty_amr_start_mode_set(true, "4");
4759 /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
4760 * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
4761 * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
4762 f_vty_amr_start_mode_set(true, "auto");
4763
4764 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4765 vc_conn.done;
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004766
4767 /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
4768 f_vty_amr_start_mode_set(true, "1");
4769 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004770 f_shutdown_helper();
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004771}
4772
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004773function f_TC_assignment_codec_amr(boolean fr, RSL_IE_MultirateCfg mr_cfg,
4774 bitstring s8_s0, bitstring exp_s8_s0,
4775 charstring start_mode := "1")
Philipp Maierd0e64b02019-03-13 14:15:23 +01004776runs on test_CT {
4777
4778 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4779 var MSC_ConnHdlr vc_conn;
4780
Philipp Maierd0e64b02019-03-13 14:15:23 +01004781 if (fr) {
4782 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4783 } else {
4784 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4785 }
4786 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4787 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004788 pars.expect_mr_conf_ie := { multirate_cfg := mr_cfg };
Philipp Maierd0e64b02019-03-13 14:15:23 +01004789 pars.expect_mr_s0_s7 := exp_s8_s0;
4790
4791 f_init(1, true);
4792 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004793 f_vty_amr_start_mode_set(fr, start_mode);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004794 f_sleep(1.0);
4795
4796 vc_conn := f_start_handler(refers(f_TC_assignment_codec), 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
4802function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
4803runs on test_CT {
4804
4805 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4806 var MSC_ConnHdlr vc_conn;
4807
4808 if (fr) {
4809 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4810 } else {
4811 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4812 }
4813 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4814 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4815
4816 f_init(1, true);
4817 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004818 f_vty_amr_start_mode_set(fr, "1");
Philipp Maierd0e64b02019-03-13 14:15:23 +01004819 f_sleep(1.0);
4820
4821 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
4822 vc_conn.done;
4823 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004824 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004825}
4826
Philipp Maierd0e64b02019-03-13 14:15:23 +01004827/* Set S1, we expect an AMR multirate configuration IE with all four rates
4828 * set. */
4829testcase TC_assignment_codec_amr_f_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004830 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4831 params := '20882208'O));
4832 f_TC_assignment_codec_amr(true, mr_cfg, '00000011'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004833 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004834}
4835
4836/* Set S1, we expect an AMR multirate configuration IE with the lower three
4837 * rates set. */
4838testcase TC_assignment_codec_amr_h_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004839 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4840 params := '208820'O));
4841 f_TC_assignment_codec_amr(false, mr_cfg, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004842 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004843}
4844
4845/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4846 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4847testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004848 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4849 params := '20882208'O));
4850 f_TC_assignment_codec_amr(true, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004851 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004852}
4853
4854/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4855 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4856testcase TC_assignment_codec_amr_h_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004857 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4858 params := '208820'O));
4859 f_TC_assignment_codec_amr(false, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004860 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004861}
4862
4863/* The following block of tests selects more and more rates until all four
4864 * possible rates are in the active set (full rate) */
4865testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004866 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4867 f_TC_assignment_codec_amr(true, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004868 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004869}
4870
4871testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004872 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4873 params := '2080'O));
4874 f_TC_assignment_codec_amr(true, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004875 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004876}
4877
4878testcase TC_assignment_codec_amr_f_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004879 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4880 params := '208820'O));
4881 f_TC_assignment_codec_amr(true, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004882 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004883}
4884
4885testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004886 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4887 params := '20882208'O));
4888 f_TC_assignment_codec_amr(true, mr_cfg, '10010101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004889 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004890}
4891
4892/* The following block of tests selects more and more rates until all three
4893 * possible rates are in the active set (half rate) */
4894testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004895 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4896 f_TC_assignment_codec_amr(false, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004897 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004898}
4899
4900testcase TC_assignment_codec_amr_h_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004901 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4902 params := '2080'O));
4903 f_TC_assignment_codec_amr(false, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004904 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004905}
4906
4907testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004908 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4909 params := '208820'O));
4910 f_TC_assignment_codec_amr(false, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004911 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004912}
4913
4914/* The following block tests what happens when the MSC does offer rate
4915 * configurations that are not supported by the BSC. Normally such situations
4916 * should not happen because the MSC gets informed by the BSC in advance via
4917 * the L3 COMPLETE message which rates are applicable. The MSC should not try
4918 * to offer rates that are not applicable anyway. */
4919
4920testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004921 /* Try to include 12,2k in into the active set even though the channel
4922 * is half rate only. The BSC is expected to remove the 12,0k */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004923 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4924 params := '208820'O));
4925 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004926 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004927}
4928
4929testcase TC_assignment_codec_amr_f_S01234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004930 /* See what happens when all rates are selected at once. Since then
4931 * Also S1 is selected, this setting will be prefered and we should
4932 * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004933 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4934 params := '20882208'O));
4935 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004936 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004937}
4938
4939testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004940 /* Same as above, but with S1 missing, the MSC is then expected to
4941 * select the currently supported rates, which are also 12.2k, 7,40k,
4942 * 5,90k, and 4,75k, into the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004943 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4944 params := '20882208'O));
4945 f_TC_assignment_codec_amr(true, mr_cfg, '11111101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004946 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004947}
4948
4949testcase TC_assignment_codec_amr_f_zero() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004950 /* Try to select no rates at all */
4951 f_TC_assignment_codec_amr_fail(true, '00000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004952 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004953}
4954
4955testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004956 /* Try to select only unsupported rates */
4957 f_TC_assignment_codec_amr_fail(true, '01101000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004958 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004959}
4960
4961testcase TC_assignment_codec_amr_h_S7() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004962 /* Try to select 12,2k for half rate */
4963 f_TC_assignment_codec_amr_fail(false, '10000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004964 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004965}
4966
Neels Hofmeyr21863562020-11-26 00:34:33 +00004967testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004968 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4969 codec_modes := '10010101'B,
4970 params := '20882208'O));
4971 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004972 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004973}
4974
4975testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004976 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4977 codec_modes := '00010101'B,
4978 params := '208820'O));
4979 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B,
Neels Hofmeyr21863562020-11-26 00:34:33 +00004980 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004981 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004982}
4983
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004984testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004985 /* "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 +07004986 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 3,
4987 codec_modes := '10010101'B,
4988 params := '20882208'O));
4989 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004990 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004991}
4992
4993testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004994 /* "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 +07004995 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 2,
4996 codec_modes := '00010101'B,
4997 params := '208820'O));
4998 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004999 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00005000}
5001
Philipp Maierac09bfc2019-01-08 13:41:39 +01005002private function f_disable_all_tch_f() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005003 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 borken");
5004 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 borken");
5005 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 borken");
5006 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005007}
5008
5009private function f_disable_all_tch_h() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005010 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 borken");
5011 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005012}
5013
5014private function f_enable_all_tch() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005015 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 unused");
5016 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 unused");
5017 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 unused");
5018 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 unused");
5019 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 unused");
5020 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005021}
5022
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02005023private function f_disable_all_sdcch() runs on test_CT {
5024 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
5025 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
5026 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
5027 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
5028}
5029
5030private function f_enable_all_sdcch() runs on test_CT {
5031 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
5032 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
5033 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
5034 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
5035}
5036
Philipp Maierac09bfc2019-01-08 13:41:39 +01005037/* Allow HR only */
5038private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs on MSC_ConnHdlr {
5039 g_pars := f_gen_test_hdlr_pars();
5040 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5041 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5042 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5043 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5044 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5045 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5046 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005047 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005048}
5049
5050/* Allow FR only */
5051private function f_TC_assignment_codec_xr_exhausted_req_fr(charstring id) runs on MSC_ConnHdlr {
5052 g_pars := f_gen_test_hdlr_pars();
5053 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5054 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5055 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5056 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5057 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5058 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5059 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005060 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005061}
5062
5063/* Allow HR only (expect assignment failure) */
5064private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) runs on MSC_ConnHdlr {
5065 g_pars := f_gen_test_hdlr_pars();
5066 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5067 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5068 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5069 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5070 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5071 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5072 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005073 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005074}
5075
5076/* Allow FR only (expect assignment failure) */
5077private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) runs on MSC_ConnHdlr {
5078 g_pars := f_gen_test_hdlr_pars();
5079 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5080 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5081 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5082 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5083 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5084 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5085 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005086 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005087}
5088
5089/* Allow FR and HR, but prefer FR */
5090private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5091 g_pars := f_gen_test_hdlr_pars();
5092 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5093 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5094 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5095 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5096 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5097 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5098 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5099 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005100 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005101}
5102
5103/* Allow FR and HR, but prefer HR */
5104private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5105 g_pars := f_gen_test_hdlr_pars();
5106 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5107 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5108 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5109 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5110 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5111 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5112 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5113 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005114 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005115}
5116
5117/* Allow FR and HR, but prefer FR */
5118private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5119 g_pars := f_gen_test_hdlr_pars();
5120 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5121 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5122 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5123 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5124 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5125 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5126 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5127 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005128 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005129}
5130
5131/* Allow FR and HR, but prefer HR */
5132private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5133 g_pars := f_gen_test_hdlr_pars();
5134 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5135 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5136 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5137 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5138 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5139 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5140 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5141 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005142 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005143}
5144
5145/* Request a HR channel while all FR channels are exhausted, this is expected
5146 * to work without conflicts */
5147testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
5148 var MSC_ConnHdlr vc_conn;
5149 f_init(1, true);
5150 f_sleep(1.0);
5151 f_enable_all_tch();
5152 f_disable_all_tch_f();
5153 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
5154 vc_conn.done;
5155 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005156 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005157}
5158
5159/* Request a FR channel while all FR channels are exhausted, this is expected
5160 * to fail. */
5161testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
5162 var MSC_ConnHdlr vc_conn;
5163 f_init(1, true);
5164 f_sleep(1.0);
5165 f_enable_all_tch();
5166 f_disable_all_tch_f();
5167 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
5168 vc_conn.done;
5169 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005170 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005171}
5172
5173/* Request a FR (prefered) or alternatively a HR channel while all FR channels
5174 * are exhausted, this is expected to be resolved by selecting a HR channel. */
5175testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
5176 var MSC_ConnHdlr vc_conn;
5177 f_init(1, true);
5178 f_sleep(1.0);
5179 f_enable_all_tch();
5180 f_disable_all_tch_f();
5181 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
5182 vc_conn.done;
5183 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005184 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005185}
5186
5187/* Request a HR (prefered) or alternatively a FR channel while all FR channels
5188 * are exhausted, this is expected to work without conflicts. */
5189testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
5190 var MSC_ConnHdlr vc_conn;
5191 f_init(1, true);
5192 f_sleep(1.0);
5193 f_enable_all_tch();
5194 f_disable_all_tch_f();
5195 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
5196 vc_conn.done;
5197 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005198 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005199}
5200
5201/* Request a FR channel while all HR channels are exhausted, this is expected
5202 * to work without conflicts */
5203testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
5204 var MSC_ConnHdlr vc_conn;
5205 f_init(1, true);
5206 f_sleep(1.0);
5207 f_enable_all_tch();
5208 f_disable_all_tch_h();
5209 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
5210 vc_conn.done;
5211 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005212 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005213}
5214
5215/* Request a HR channel while all HR channels are exhausted, this is expected
5216 * to fail. */
5217testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
5218 var MSC_ConnHdlr vc_conn;
5219 f_init(1, true);
5220 f_sleep(1.0);
5221 f_enable_all_tch();
5222 f_disable_all_tch_h();
5223 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
5224 vc_conn.done;
5225 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005226 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005227}
5228
5229/* Request a HR (prefered) or alternatively a FR channel while all HR channels
5230 * are exhausted, this is expected to be resolved by selecting a FR channel. */
5231testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
5232 var MSC_ConnHdlr vc_conn;
5233 f_init(1, true);
5234 f_sleep(1.0);
5235 f_enable_all_tch();
5236 f_disable_all_tch_h();
5237 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
5238 vc_conn.done;
5239 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005240 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005241}
5242
5243/* Request a FR (prefered) or alternatively a HR channel while all HR channels
5244 * are exhausted, this is expected to work without conflicts. */
5245testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
5246 var MSC_ConnHdlr vc_conn;
5247 f_init(1, true);
5248 f_sleep(1.0);
5249 f_enable_all_tch();
5250 f_disable_all_tch_h();
5251 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
5252 vc_conn.done;
5253 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005254 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005255}
5256
5257/* Allow FR and HR, but prefer HR */
5258private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5259 g_pars := f_gen_test_hdlr_pars();
5260 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5261 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5262 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5263 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5264 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5265 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5266 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5267 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005268 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005269}
5270
5271/* Allow FR and HR, but prefer FR */
5272private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5273 g_pars := f_gen_test_hdlr_pars();
5274 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5275 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5276 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5277 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5278 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5279 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5280 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5281 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005282 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005283}
5284
5285/* Request a HR (prefered) or alternatively a FR channel, it is expected that
5286 * HR, which is the prefered type, is selected. */
5287testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
5288 var MSC_ConnHdlr vc_conn;
5289 f_init(1, true);
5290 f_sleep(1.0);
5291 f_enable_all_tch();
5292 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
5293 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005294 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005295}
5296
5297/* Request a FR (prefered) or alternatively a HR channel, it is expected that
5298 * FR, which is the prefered type, is selected. */
5299testcase TC_assignment_codec_req_fr_hr() runs on test_CT {
5300 var MSC_ConnHdlr vc_conn;
5301 f_init(1, true);
5302 f_sleep(1.0);
5303 f_enable_all_tch();
5304 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_fr_hr));
5305 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005306 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005307}
5308
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005309/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
5310private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
5311 g_pars := f_gen_test_hdlr_pars();
5312 g_pars.ra := '02'O; /* RA containing reason=LU */
5313
5314 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5315 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5316 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5317 var template uint3_t tsc := ?;
5318
5319 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5320 f_create_bssmap_exp(l3_enc);
5321 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5322 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5323
5324 /* we should now have a COMPL_L3 at the MSC */
5325 timer T := 10.0;
5326 T.start;
5327 alt {
5328 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5329 [] T.timeout {
5330 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5331 }
5332 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005333
5334 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005335}
5336testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
5337 var MSC_ConnHdlr vc_conn;
5338 f_init(1, true);
5339 f_sleep(1.0);
5340 f_disable_all_sdcch();
5341 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
5342 vc_conn.done;
5343 f_enable_all_sdcch();
5344 f_shutdown_helper();
5345}
5346
5347/* Request a signalling channel with all SDCCH exhausted, it is
5348 expected that no TCH will be selected for signalling and assigment will fail
5349 because it's dictated by VTY config */
5350testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
5351 var RSL_Message rsl_unused, rsl_msg;
5352 var GsmRrMessage rr;
5353 f_init(1, false);
5354 f_sleep(1.0);
5355 f_vty_allow_tch_for_signalling(false, 0);
5356 f_disable_all_sdcch();
5357
5358 /* RA containing reason=LU */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005359 f_ipa_tx(ts_RSL_CHAN_RQD('02'O, 2342));
5360 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005361 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
5362 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
5363 setverdict(fail, "Expected reject");
5364 }
5365
5366 f_vty_allow_tch_for_signalling(true, 0);
5367 f_enable_all_sdcch();
5368 f_shutdown_helper();
5369}
5370
5371/* Request a voice channel with all SDCCH exhausted, it is
5372 * expected that TCH channel will be allocated since the VTY option is only
5373 * aimed at signalling requests */
5374private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
5375 g_pars := f_gen_test_hdlr_pars();
5376 g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
5377
5378 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5379 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5380 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5381 var template uint3_t tsc := ?;
5382
5383 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5384 f_create_bssmap_exp(l3_enc);
5385 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5386 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5387
5388 /* we should now have a COMPL_L3 at the MSC */
5389 timer T := 10.0;
5390 T.start;
5391 alt {
5392 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5393 [] T.timeout {
5394 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5395 }
5396 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005397 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005398}
5399testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
5400 var MSC_ConnHdlr vc_conn;
5401 f_init(1, true);
5402 f_sleep(1.0);
5403 f_vty_allow_tch_for_signalling(false, 0);
5404 f_disable_all_sdcch();
5405
5406 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
5407 vc_conn.done;
5408
5409 f_vty_allow_tch_for_signalling(true, 0);
5410 f_enable_all_sdcch();
5411 f_shutdown_helper();
5412}
5413
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005414/* Test Osmux setup BSC<->MSC */
5415testcase TC_assignment_osmux_cn() runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005416 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5417 var MSC_ConnHdlr vc_conn;
5418
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005419 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5420 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5421 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiyb9bf00f2022-09-14 15:35:37 +07005422 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02005423 pars.use_osmux_cn := true;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005424
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02005425 g_osmux_enabled_cn := true;
5426 f_init(1, true);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005427 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005428 f_vty_amr_start_mode_set(false, "1");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005429
5430 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5431 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005432
5433 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01005434 f_shutdown_helper();
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005435}
5436
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005437/* Test Osmux setup BTS<->BSC */
5438testcase TC_assignment_osmux_bts() runs on test_CT {
5439 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5440 var MSC_ConnHdlr vc_conn;
5441
5442 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5443 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5444 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005445 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005446 pars.use_osmux_bts := true;
5447
5448 g_osmux_enabled_bts := true;
5449 f_init(1, true);
5450 f_sleep(1.0);
5451 f_vty_amr_start_mode_set(false, "1");
5452
5453 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5454 vc_conn.done;
5455
5456 f_vty_amr_start_mode_restore(false);
5457 f_shutdown_helper();
5458}
5459
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +02005460/* Test non-AMR codecs still work fine as RTP when Osmux is enabled BTS<->BSC<->MSC */
5461testcase TC_assignment_codec_hr_osmux_on() runs on test_CT {
5462 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5463 var MSC_ConnHdlr vc_conn;
5464
5465 g_osmux_enabled_cn := true;
5466 g_osmux_enabled_bts := true;
5467 f_init(1, true);
5468 f_sleep(1.0);
5469 f_ctrs_bsc_and_bts_assignment_init(1);
5470
5471 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5472 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5473 vc_conn.done;
5474
5475 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
5476 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
5477 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
5478 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
5479 f_ctrs_bts_verify();
5480
5481 f_shutdown_helper();
5482}
5483
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005484/* Test Osmux setup BTS<->BSC<->MSC */
5485testcase TC_assignment_osmux() runs on test_CT {
5486 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5487 var MSC_ConnHdlr vc_conn;
5488
5489 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5490 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5491 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005492 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005493 pars.use_osmux_cn := true;
5494 pars.use_osmux_bts := true;
5495
5496 g_osmux_enabled_cn := true;
5497 g_osmux_enabled_bts := true;
5498 f_init(1, true);
5499 f_sleep(1.0);
5500 f_vty_amr_start_mode_set(false, "1");
5501
5502 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5503 vc_conn.done;
5504
5505 f_vty_amr_start_mode_restore(false);
5506 f_shutdown_helper();
5507}
5508
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005509/* test the procedure of the MSC requesting a Classmark Update:
5510 * a) BSSMAP Classmark Request should result in RR CLASSMARK ENQUIRY,
5511 * b) L3 RR CLASSMARK CHANGE should result in BSSMAP CLASSMARK UPDATE */
Harald Welte898113b2018-01-31 18:32:21 +01005512private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005513 g_pars := f_gen_test_hdlr_pars();
5514
Harald Weltea0630032018-03-20 21:09:55 +01005515 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005516 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005517
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005518 BSSAP.send(ts_BSSMAP_ClassmarkRequest);
5519 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
5520
Harald Welte898113b2018-01-31 18:32:21 +01005521 f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
5522 BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
5523 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005524
5525 f_perform_clear();
Harald Welte898113b2018-01-31 18:32:21 +01005526}
5527testcase TC_classmark() runs on test_CT {
5528 var MSC_ConnHdlr vc_conn;
5529 f_init(1, true);
5530 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005531 vc_conn := f_start_handler(refers(f_tc_classmark));
Harald Welte898113b2018-01-31 18:32:21 +01005532 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005533 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005534}
5535
Harald Welteeddf0e92020-06-21 19:42:15 +02005536/* Send a CommonID from the simulated MSC and verify that the information is used to
5537 * fill BSC-internal data structures (specifically, bsc_subscr associated with subscr_conn) */
5538private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
5539 g_pars := f_gen_test_hdlr_pars();
5540 f_MscConnHdlr_init_vty();
5541
5542 f_create_chan_and_exp();
5543 /* we should now have a COMPL_L3 at the MSC */
Harald Welteeddf0e92020-06-21 19:42:15 +02005544
5545 /* Send CommonID */
5546 BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
5547
5548 /* Use VTY to verify that the IMSI of the subscr_conn is set */
5549 var charstring regex := "*(IMSI: " & hex2str(g_pars.imsi) & ")*";
5550 f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
5551
5552 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005553
5554 f_perform_clear();
Harald Welteeddf0e92020-06-21 19:42:15 +02005555}
5556testcase TC_common_id() runs on test_CT {
5557 var MSC_ConnHdlr vc_conn;
5558 f_init(1, true);
5559 f_sleep(1.0);
5560 vc_conn := f_start_handler(refers(f_tc_common_id));
5561 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005562 f_shutdown_helper();
Harald Welteeddf0e92020-06-21 19:42:15 +02005563}
5564
Harald Weltee3bd6582018-01-31 22:51:25 +01005565private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005566 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005567 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005568 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005569
Harald Weltee3bd6582018-01-31 22:51:25 +01005570 /* send the single message we want to send */
5571 f_rsl_send_l3(l3);
5572}
5573
5574private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr {
5575 timer T := sec;
5576 var PDU_BSSAP bssap;
Harald Welte898113b2018-01-31 18:32:21 +01005577 T.start;
5578 alt {
Harald Weltee3bd6582018-01-31 22:51:25 +01005579 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap {
5580 setverdict(fail, "Unexpected BSSMAP ", bssap);
Daniel Willmannafce8662018-07-06 23:11:32 +02005581 mtc.stop;
Harald Welte898113b2018-01-31 18:32:21 +01005582 }
5583 [] T.timeout {
5584 setverdict(pass);
5585 }
5586 }
5587}
5588
Harald Weltee3bd6582018-01-31 22:51:25 +01005589/* unsolicited ASSIGNMENT FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5590private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
5591 f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
5592 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005593 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005594}
Harald Welte898113b2018-01-31 18:32:21 +01005595testcase TC_unsol_ass_fail() runs on test_CT {
5596 var MSC_ConnHdlr vc_conn;
5597 f_init(1, true);
5598 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005599 vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
Harald Welte898113b2018-01-31 18:32:21 +01005600 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005601 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005602}
Harald Welte552620d2017-12-16 23:21:36 +01005603
Harald Welteea99a002018-01-31 20:46:43 +01005604
5605/* unsolicited ASSIGNMENT COMPLETE (without ASSIGN) from MS shouldn't bring BSC down */
5606private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005607 f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
5608 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005609 f_perform_clear();
Harald Welteea99a002018-01-31 20:46:43 +01005610}
5611testcase TC_unsol_ass_compl() runs on test_CT {
5612 var MSC_ConnHdlr vc_conn;
5613 f_init(1, true);
5614 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005615 vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
Harald Welteea99a002018-01-31 20:46:43 +01005616 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005617 f_shutdown_helper();
Harald Welteea99a002018-01-31 20:46:43 +01005618}
5619
5620
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005621/* unsolicited HANDOVER FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5622private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005623 f_est_single_l3(ts_RRM_HandoverFailure('00'O));
5624 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005625 f_perform_clear();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005626}
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005627testcase TC_unsol_ho_fail() runs on test_CT {
5628 var MSC_ConnHdlr vc_conn;
5629 f_init(1, true);
5630 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005631 vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005632 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005633 f_shutdown_helper();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005634}
5635
5636
Harald Weltee3bd6582018-01-31 22:51:25 +01005637/* short message from MS should be ignored */
5638private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005639 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005640 f_create_chan_and_exp();
Harald Weltee3bd6582018-01-31 22:51:25 +01005641 /* we should now have a COMPL_L3 at the MSC */
Harald Weltee3bd6582018-01-31 22:51:25 +01005642
5643 /* send short message */
5644 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
5645 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005646 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005647}
5648testcase TC_err_82_short_msg() runs on test_CT {
5649 var MSC_ConnHdlr vc_conn;
5650 f_init(1, true);
5651 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005652 vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
Harald Weltee3bd6582018-01-31 22:51:25 +01005653 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005654 f_shutdown_helper();
Harald Weltee3bd6582018-01-31 22:51:25 +01005655}
5656
5657
Harald Weltee9e02e42018-01-31 23:36:25 +01005658/* 24.008 8.4 Unknown message must trigger RR STATUS */
5659private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
5660 f_est_single_l3(ts_RRM_UL_REL('00'O));
5661 timer T := 3.0
5662 alt {
5663 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
5664 setverdict(pass);
5665 }
5666 [] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
Harald Welte458fd372018-03-21 11:26:23 +01005667 [] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
Harald Weltee9e02e42018-01-31 23:36:25 +01005668 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005669 f_perform_clear();
Harald Weltee9e02e42018-01-31 23:36:25 +01005670}
5671testcase TC_err_84_unknown_msg() runs on test_CT {
5672 var MSC_ConnHdlr vc_conn;
5673 f_init(1, true);
5674 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005675 vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
Harald Weltee9e02e42018-01-31 23:36:25 +01005676 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005677 f_shutdown_helper();
Harald Weltee9e02e42018-01-31 23:36:25 +01005678}
5679
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005680/***********************************************************************
5681 * Handover
5682 ***********************************************************************/
5683
Harald Welte94e0c342018-04-07 11:33:23 +02005684/* execute a "bts <0-255> trx <0-255> timeslot <0-7> " command on given Dchan */
5685private function f_vty_ts_action(charstring suffix, integer bts_nr, integer trx_nr, integer ts_nr)
5686runs on test_CT {
5687 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5688 " timeslot "&int2str(ts_nr)&" ";
5689 f_vty_transceive(BSCVTY, cmd & suffix);
5690}
5691
Harald Welte261af4b2018-02-12 21:20:39 +01005692/* 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 +07005693private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
5694 uint8_t bts_nr, uint8_t trx_nr,
5695 in RslChannelNr chan_nr)
5696{
Harald Welte261af4b2018-02-12 21:20:39 +01005697 /* FIXME: resolve those from component-global state */
5698 var integer ts_nr := chan_nr.tn;
5699 var integer ss_nr;
5700 if (ischosen(chan_nr.u.ch0)) {
5701 ss_nr := 0;
5702 } else if (ischosen(chan_nr.u.lm)) {
5703 ss_nr := chan_nr.u.lm.sub_chan;
5704 } else if (ischosen(chan_nr.u.sdcch4)) {
5705 ss_nr := chan_nr.u.sdcch4.sub_chan;
5706 } else if (ischosen(chan_nr.u.sdcch8)) {
5707 ss_nr := chan_nr.u.sdcch8.sub_chan;
5708 } else {
5709 setverdict(fail, "Invalid ChanNr ", chan_nr);
Daniel Willmannafce8662018-07-06 23:11:32 +02005710 mtc.stop;
Harald Welte261af4b2018-02-12 21:20:39 +01005711 }
5712
5713 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5714 " timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005715 f_vty_transceive(pt, cmd & suffix);
Harald Welte261af4b2018-02-12 21:20:39 +01005716}
5717
Neels Hofmeyr91401012019-07-11 00:42:35 +02005718/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
5719 * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor
5720 * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
5721 * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
5722 * pair, not really to a specific BTS number. */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005723private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
5724 in RslChannelNr chan_nr, uint8_t new_bts_nr)
5725{
5726 f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
Harald Welte261af4b2018-02-12 21:20:39 +01005727}
5728
5729/* intra-BSC hand-over between BTS0 and BTS1 */
5730private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02005731 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5732 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte261af4b2018-02-12 21:20:39 +01005733
5734 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5735 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5736
Harald Weltea0630032018-03-20 21:09:55 +01005737 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005738 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Harald Welte261af4b2018-02-12 21:20:39 +01005739
5740 var HandoverState hs := {
5741 rr_ho_cmpl_seen := false,
5742 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005743 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005744 expect_target_tsc := c_BtsParams[1].tsc
Harald Welte261af4b2018-02-12 21:20:39 +01005745 };
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005746 /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005747 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
Harald Welte261af4b2018-02-12 21:20:39 +01005748 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5749 f_rslem_suspend(RSL1_PROC);
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005750
5751 /* From the MGW perspective, a handover is is characterized by
5752 * performing one MDCX operation with the MGW. So we expect to see
5753 * one more MDCX during handover. */
5754 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5755
Harald Welte261af4b2018-02-12 21:20:39 +01005756 alt {
5757 [] as_handover(hs);
Harald Welte261af4b2018-02-12 21:20:39 +01005758 }
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005759
Philipp Maier4dae0652018-11-12 12:03:26 +01005760 /* Since this is an internal handover we expect the BSC to inform the
5761 * MSC about the event */
5762 BSSAP.receive(tr_BSSMAP_HandoverPerformed);
5763
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005764 /* Check the amount of MGCP transactions is still consistant with the
5765 * test expectation */
5766 f_check_mgcp_expectations()
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005767
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005768 var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
5769
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005770 /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
5771 * 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 +02005772 f_verify_encr_info(chan_act);
5773
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005774 f_chan_act_verify_tsc(chan_act, c_BtsParams[1].tsc);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005775
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005776 f_perform_clear(RSL1, RSL1_PROC);
5777
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005778 f_sleep(0.5);
Harald Welte261af4b2018-02-12 21:20:39 +01005779}
5780
5781testcase TC_ho_int() runs on test_CT {
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005782 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte261af4b2018-02-12 21:20:39 +01005783 var MSC_ConnHdlr vc_conn;
5784 f_init(2, true);
5785 f_sleep(1.0);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005786
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005787 pars.expect_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005788
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005789 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005790
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005791 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
Harald Welte261af4b2018-02-12 21:20:39 +01005792 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005793
5794 /* from f_establish_fully() */
5795 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5796 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5797 /* from handover */
5798 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5799 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5800 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5801 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005802 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5803 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005804 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005805 f_shutdown_helper(ho := true);
Harald Welte261af4b2018-02-12 21:20:39 +01005806}
Harald Weltee9e02e42018-01-31 23:36:25 +01005807
Oliver Smith7eabd312021-07-12 14:18:56 +02005808function 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 +02005809 var MSC_ConnHdlr vc_conn;
5810 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5811 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
5812
5813 f_init(2, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02005814 f_vty_encryption_a5(enc_a5);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005815 f_sleep(1.0);
5816
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005817 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005818
5819 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
5820 vc_conn.done;
5821
5822 /* from f_establish_fully() */
5823 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5824 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5825 /* from handover */
5826 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5827 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5828 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5829 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005830 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5831 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005832 f_ctrs_bsc_and_bts_verify();
Oliver Smith7eabd312021-07-12 14:18:56 +02005833 f_vty_encryption_a5_reset();
Oliver Smith39f53072022-10-27 14:44:04 +02005834 f_shutdown_helper(ho := true);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005835}
5836
5837testcase TC_ho_int_a5_0() runs on test_CT {
5838 f_tc_ho_int_a5('01'O);
5839}
5840
5841testcase TC_ho_int_a5_1() runs on test_CT {
5842 f_tc_ho_int_a5('02'O);
5843}
5844
5845testcase TC_ho_int_a5_3() runs on test_CT {
5846 f_tc_ho_int_a5('08'O);
5847}
5848
5849testcase TC_ho_int_a5_4() runs on test_CT {
Oliver Smith7eabd312021-07-12 14:18:56 +02005850 f_tc_ho_int_a5('10'O, "0 1 3 4");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005851}
5852
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005853/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
5854private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
5855 g_pars := f_gen_test_hdlr_pars();
5856 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5857 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005858
5859 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5860 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5861
5862 f_establish_fully(ass_cmd, exp_compl);
5863 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
5864
5865 var HandoverState hs := {
5866 rr_ho_cmpl_seen := false,
5867 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005868 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005869 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005870 };
5871 /* issue hand-over command on VTY */
5872 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
5873 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5874 f_rslem_suspend(RSL1_PROC);
5875
5876 /* From the MGW perspective, a handover is is characterized by
5877 * performing one MDCX operation with the MGW. So we expect to see
5878 * one more MDCX during handover. */
5879 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5880
5881 var RSL_Message rsl;
5882 var PDU_ML3_NW_MS l3;
5883 var RslChannelNr new_chan_nr;
5884 var GsmArfcn arfcn;
5885 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
5886 l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
5887 if (not ischosen(l3.msgs.rrm.handoverCommand)) {
5888 setverdict(fail, "Expected handoverCommand");
5889 mtc.stop;
5890 }
5891 }
5892 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
5893 new_chan_nr, arfcn);
5894
5895 f_rslem_register(0, new_chan_nr, RSL1_PROC);
5896
5897 /* resume processing of RSL DChan messages, which was temporarily suspended
5898 * before performing a hand-over */
5899 f_rslem_resume(RSL1_PROC);
5900 RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
5901
5902 f_sleep(1.0);
5903
5904 /* Handover fails because no HANDO DET appears on the new lchan,
5905 * and the old lchan reports a Radio Link Failure. */
5906 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
5907
5908 var PDU_BSSAP rx_clear_request;
5909 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5910 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5911 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5912
5913 var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
5914
5915 var MgcpCommand mgcp;
5916 interleave {
5917 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
5918 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005919 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005920 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005921 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005922 }
5923 [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005924 [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005925 RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005926 f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005927 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005928 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5929 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5930 }
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005931 }
5932
5933 f_sleep(0.5);
5934 setverdict(pass);
5935}
5936testcase TC_ho_int_radio_link_failure() runs on test_CT {
5937 var MSC_ConnHdlr vc_conn;
5938 f_init(2, true);
5939 f_sleep(1.0);
5940
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005941 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005942
5943 vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
5944 vc_conn.done;
5945
5946 /* from f_establish_fully() */
5947 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5948 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5949 /* from handover */
5950 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5951 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
5952 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5953 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005954 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5955 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005956 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005957 f_shutdown_helper(ho := true);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005958}
5959
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005960/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005961private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005962 var MgcpCommand mgcp;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005963 var template MgcpResponse mgcp_resp;
5964 var MGCP_RecvFrom mrf;
5965 var template MgcpMessage msg_resp;
5966 var template MgcpMessage msg_dlcx := {
5967 command := tr_DLCX()
5968 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005969
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005970 if (g_pars.aoip) {
5971 MGCP.receive(tr_DLCX()) -> value mgcp {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005972 log("Got first DLCX: ", mgcp);
5973 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005974 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005975
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005976 MGCP.receive(tr_DLCX()) -> value mgcp {
5977 log("Got second DLCX: ", mgcp);
5978 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
5979 };
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005980 } else {
5981 /* For SCCPLite, BSC doesn't handle the MSC-side */
5982 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
5983 log("Got first DLCX: ", mrf.msg.command);
5984 msg_resp := {
5985 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
5986 }
5987 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
5988 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005989 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005990}
5991
Oliver Smithc9a5f532022-10-21 11:32:23 +02005992private function f_ho_out_of_this_bsc(template (omit) BSSMAP_oldToNewBSSIEs exp_oldToNewBSSIEs := omit,
5993 boolean skip_meas_rep := false) runs on MSC_ConnHdlr {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005994
Oliver Smithc9a5f532022-10-21 11:32:23 +02005995 if (not skip_meas_rep) {
5996 var NcellReports neighbor_rep := {
5997 { rxlev := 20, bcch_freq := 0, bsic := 11 }
5998 };
5999 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
6000 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
6001 l3_mr, 0));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006002
Oliver Smithc9a5f532022-10-21 11:32:23 +02006003 BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
6004 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006005
6006 f_sleep(0.5);
6007 /* The MSC negotiates Handover Request and Handover Request Ack with
6008 * the other BSS and comes back with a BSSMAP Handover Command
6009 * containing an RR Handover Command coming from the target BSS... */
6010
6011 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6012 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6013 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6014 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6015 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6016
6017 /* expect the Handover Command to go out on RR */
6018 var RSL_Message rsl_ho_cmd
6019 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6020 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6021 var RSL_IE_Body rsl_ho_cmd_l3;
6022 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6023 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6024 setverdict(fail);
6025 } else {
6026 log("Found L3 Info: ", rsl_ho_cmd_l3);
6027 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6028 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6029 setverdict(fail);
6030 } else {
6031 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6032 setverdict(pass);
6033 }
6034 }
6035
6036 /* When the other BSS has reported a completed handover, this side is
6037 * torn down. */
6038
6039 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_HANDOVER_SUCCESSFUL;
6040 var BssmapCause cause := enum2int(cause_val);
6041 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6042
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006043 f_expect_dlcx_conns();
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006044
6045 interleave {
6046 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
6047 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
6048 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006049 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
6050 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
6051 }
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006052 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006053 setverdict(pass);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006054}
6055
6056private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
6057 g_pars := f_gen_test_hdlr_pars();
6058 var PDU_BSSAP ass_req := f_gen_ass_req();
6059 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6060 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6061 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6062 f_establish_fully(ass_req, exp_compl);
6063
6064 f_ho_out_of_this_bsc();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006065}
6066testcase TC_ho_out_of_this_bsc() runs on test_CT {
6067 var MSC_ConnHdlr vc_conn;
6068
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006069 f_init_vty();
6070 f_bts_0_cfg(BSCVTY,
6071 {"neighbor-list mode automatic",
6072 "handover 1",
6073 "handover algorithm 2",
6074 "handover2 window rxlev averaging 1",
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006075 "no neighbors",
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006076 "neighbor lac 99 arfcn 123 bsic any"});
6077 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6078
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006079 f_init(1, true);
6080 f_sleep(1.0);
6081
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006082 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006083
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006084 vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
6085 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006086
6087 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6088 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6089 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6090 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6091 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6092 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
6093 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006094 f_shutdown_helper(ho := true);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006095}
6096
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006097private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6098 template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
Vadim Yanitskiy2ef6a2f2020-10-08 23:17:32 +07006099 template (present) OCT1 dlci := ?,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006100 octetstring l3 := '0123456789'O)
6101runs on MSC_ConnHdlr {
Neels Hofmeyr43654812020-09-25 01:35:35 +02006102 /* The old lchan and conn should still be active. See that arbitrary L3
6103 * is still going through. */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006104 rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
Neels Hofmeyr43654812020-09-25 01:35:35 +02006105 var template PDU_BSSAP exp_data := {
6106 discriminator := '1'B,
6107 spare := '0000000'B,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006108 dlci := dlci,
6109 lengthIndicator := lengthof(l3),
Neels Hofmeyr43654812020-09-25 01:35:35 +02006110 pdu := {
6111 dtap := l3
6112 }
6113 };
6114 BSSAP.receive(exp_data);
6115 setverdict(pass);
6116}
6117
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006118private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6119 template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006120 template (value) OCT1 dlci := '00'O,
6121 octetstring l3 := '0123456789'O)
6122runs on MSC_ConnHdlr {
6123 BSSAP.send(PDU_BSSAP:{
6124 discriminator := '1'B,
6125 spare := '0000000'B,
6126 dlci := dlci,
6127 lengthIndicator := lengthof(l3),
6128 pdu := {
6129 dtap := l3
6130 }
6131 });
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006132 rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006133 setverdict(pass);
6134}
6135
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006136/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
6137 * simply never sends a BSSMAP Handover Command. */
6138private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006139 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006140
6141 var PDU_BSSAP ass_req := f_gen_ass_req();
6142 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6143 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6144 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6145 f_establish_fully(ass_req, exp_compl);
6146
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006147 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006148 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6149
6150 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6151
6152 /* osmo-bsc should time out 10 seconds after the handover started.
6153 * Let's give it a bit extra. */
6154 f_sleep(15.0);
6155
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006156 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006157 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006158 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006159}
6160testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
6161 var MSC_ConnHdlr vc_conn;
6162
6163 f_init(1, true);
6164 f_sleep(1.0);
6165
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006166 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006167
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006168 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
6169 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006170
6171 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6172 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6173 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6174 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6175 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6176 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6177 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006178 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006179}
6180
6181/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
6182 * RR Handover Failure. */
6183private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006184 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006185
6186 var PDU_BSSAP ass_req := f_gen_ass_req();
6187 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6188 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6189 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6190 f_establish_fully(ass_req, exp_compl);
6191
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006192 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006193 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6194
6195 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6196
6197 f_sleep(0.5);
6198 /* The MSC negotiates Handover Request and Handover Request Ack with
6199 * the other BSS and comes back with a BSSMAP Handover Command
6200 * containing an RR Handover Command coming from the target BSS... */
6201
6202 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6203 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6204 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6205 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6206 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6207
6208 /* expect the Handover Command to go out on RR */
6209 var RSL_Message rsl_ho_cmd
6210 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6211 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6212 var RSL_IE_Body rsl_ho_cmd_l3;
6213 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6214 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6215 setverdict(fail);
6216 } else {
6217 log("Found L3 Info: ", rsl_ho_cmd_l3);
6218 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6219 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6220 setverdict(fail);
6221 } else {
6222 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6223 setverdict(pass);
6224 }
6225 }
6226
6227 f_sleep(0.2);
6228 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
6229
6230 /* Should tell the MSC about the failure */
6231 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6232
6233 f_sleep(1.0);
6234
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006235 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006236 f_sleep(1.0);
6237
6238 setverdict(pass);
6239 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006240 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006241}
6242testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
6243 var MSC_ConnHdlr vc_conn;
6244
6245 f_init(1, true);
6246 f_sleep(1.0);
6247
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006248 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006249
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006250 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
6251 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006252
6253 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6254 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6255 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6256 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6257 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6258 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
6259 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006260 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006261}
6262
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006263/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
6264 * (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 +02006265 * and the lchan is released. */
6266private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006267 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006268
6269 var PDU_BSSAP ass_req := f_gen_ass_req();
6270 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6271 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6272 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6273 f_establish_fully(ass_req, exp_compl);
6274
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006275 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006276 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6277
6278 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6279
6280 f_sleep(0.5);
6281 /* The MSC negotiates Handover Request and Handover Request Ack with
6282 * the other BSS and comes back with a BSSMAP Handover Command
6283 * containing an RR Handover Command coming from the target BSS... */
6284
6285 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6286 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6287 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6288 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6289 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6290
6291 /* expect the Handover Command to go out on RR */
6292 var RSL_Message rsl_ho_cmd
6293 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6294 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6295 var RSL_IE_Body rsl_ho_cmd_l3;
6296 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6297 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6298 setverdict(fail);
6299 } else {
6300 log("Found L3 Info: ", rsl_ho_cmd_l3);
6301 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6302 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6303 setverdict(fail);
6304 } else {
6305 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6306 setverdict(pass);
6307 }
6308 }
6309
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006310 /* We get neither success nor failure report from the remote BSS. Eventually T8 times out and we run into 3GPP
6311 * TS 48.008 3.1.5.3.3 "Abnormal Conditions": Clear Request should go to the MSC, and RR should be released
6312 * after Clear Command */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006313
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006314 var PDU_BSSAP rx_clear_request;
Neels Hofmeyre1797aa2019-07-09 19:34:04 +02006315 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
6316 log("Got BSSMAP Clear Request");
6317 /* Instruct BSC to clear channel */
6318 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6319 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6320
6321 var MgcpCommand mgcp;
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006322 interleave {
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01006323 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
6324 log("Got Deact SACCH");
6325 }
Harald Welte924b6ea2019-02-04 01:05:34 +01006326 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
Neels Hofmeyr211169d2018-11-07 00:37:29 +01006327 log("Got RR Release");
6328 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02006329 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006330 log("Got RF Chan Rel");
6331 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02006332 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006333 }
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006334 }
6335
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006336 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006337 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006338 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006339
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006340 setverdict(pass);
6341 f_sleep(1.0);
6342}
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006343testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006344 var MSC_ConnHdlr vc_conn;
6345
6346 f_init(1, true);
6347 f_sleep(1.0);
6348
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006349 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006350
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006351 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006352 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006353
6354 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6355 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6356 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6357 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6358 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6359 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6360 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006361 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006362}
6363
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006364private 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 +01006365 var PDU_BSSAP rx_bssap;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006366 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6367 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6368 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6369 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6370 * before we get started. */
6371 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6372 f_rslem_register(0, new_chan_nr);
6373 g_chan_nr := new_chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06006374 var uint3_t expect_target_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006375 f_sleep(1.0);
6376
6377 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6378 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006379 var default as_media := activate(as_Media());
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006380
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01006381 var PDU_BSSAP ho_req := f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
6382 cell_id_source := g_pars.cell_id_source,
6383 oldToNewBSSIEs := oldToNewBSSIEs,
6384 enc := g_pars.encr);
6385 if (g_pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr) {
6386 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, ho_req));
6387 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6388 } else {
6389 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, omit));
6390 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6391 BSSAP.send(ho_req);
6392 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006393
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006394 alt {
6395 [] BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap {
6396 if (g_pars.expect_ho_fail) {
6397 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6398 "Expected Handover Request to fail, but got Handover Request Ack")
6399 }
6400 }
6401 [] BSSAP.receive(tr_BSSMAP_HandoverFailure) -> value rx_bssap {
6402 if (not g_pars.expect_ho_fail) {
6403 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6404 "Expected Handover Request to succeed, but got Handover Failure")
6405 }
6406 // TODO: evaluate correct cause value. But osmo-bsc doesn't seem to send meaningful causes yet!
6407 // For now just accept any cause.
6408 BSSAP.receive(tr_BSSMAP_ClearRequest);
6409 setverdict(pass);
6410 return;
6411 }
6412 }
6413
Oliver Smith7a8594a2023-02-13 14:30:49 +01006414 if (g_pars.expect_ho_fail_lchan_est) {
6415 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6416 setverdict(pass);
Oliver Smitha1cbec52023-02-21 12:44:12 +01006417
6418 /* When we let MGCP MDCX run into a timeout, it's still in the
6419 * queue and additionally after BSSAP HandoverFailure, two DLCX
Oliver Smith30eb8822023-03-06 12:31:53 +01006420 * get sent (for AoIP, for SCCPlite one DLCX). */
Oliver Smitha1cbec52023-02-21 12:44:12 +01006421 if (g_pars.ignore_mgw_mdcx) {
Oliver Smith30eb8822023-03-06 12:31:53 +01006422 if (g_pars.aoip) {
6423 MGCP.receive(tr_MDCX);
6424 MGCP.receive(tr_DLCX);
6425 MGCP.receive(tr_DLCX);
6426 } else {
6427 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_MDCX}));
6428 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_DLCX}));
6429 }
Oliver Smitha1cbec52023-02-21 12:44:12 +01006430 }
Oliver Smith7a8594a2023-02-13 14:30:49 +01006431 return;
6432 }
6433
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006434 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6435
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006436 /* we're sure that the channel activation is done now, verify the parameters in it */
6437 var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
6438 f_verify_encr_info(chan_act);
6439 f_chan_act_verify_tsc(chan_act, expect_target_tsc);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006440
Neels Hofmeyr46e16e52022-02-23 17:04:00 +01006441 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.codecList)) {
6442 if (not g_pars.aoip) {
6443 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6444 "handoverRequestAck: Expected no Speech Codec List (BSS Supported), because this is not AoIP");
6445 }
6446 /* TODO: check actual codecs? */
6447 } else {
6448 if (g_pars.aoip) {
6449 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6450 "handoverRequestAck: Expected Speech Codec List (BSS Supported), but none found");
6451 }
6452 }
6453
6454 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.speechCodec)) {
6455 if (not g_pars.aoip) {
6456 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6457 "handoverRequestAck: Expected no Speech Codec (Chosen), because this is not AoIP");
6458 }
6459 /* TODO: check actual codec? */
6460 } else {
6461 if (g_pars.aoip) {
6462 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6463 "handoverRequestAck: Expected Speech Codec (Chosen), but none found");
6464 }
6465 }
6466
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006467 var octetstring ho_command_str;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006468 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6469 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6470 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6471 log("L3 Info in HO Request Ack is ", ho_command);
6472
6473 var GsmArfcn arfcn;
6474 var RslChannelNr actual_new_chan_nr;
6475 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6476 actual_new_chan_nr, arfcn);
6477
6478 if (actual_new_chan_nr != new_chan_nr) {
6479 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6480 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6481 setverdict(fail);
6482 return;
6483 }
6484 log("Handover Command chan_nr is", actual_new_chan_nr);
6485
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006486 var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
6487 if (not match(got_tsc, expect_target_tsc)) {
6488 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6489 expect_target_tsc, " got ", got_tsc);
6490 mtc.stop;
6491 } else {
6492 log("handoverCommand: verified TSC = ", got_tsc);
6493 }
6494
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006495 /* Check the Cipher Mode Setting IE (shall be present during inter-RAT handover) */
6496 if (ispresent(ho_command.msgs.rrm.handoverCommand.cipherModeSetting)) {
6497 var CipherModeSetting_TV cms := ho_command.msgs.rrm.handoverCommand.cipherModeSetting;
6498 var template (present) CipherModeSetting_TV tr_cms := {
6499 sC := '0'B, /* no ciphering by default */
6500 algorithmIdentifier := '000'B,
6501 elementIdentifier := ?
6502 };
6503 if (ispresent(g_pars.encr) and g_pars.encr.enc_alg_expect != '01'O) { /* A5/N */
6504 tr_cms.algorithmIdentifier := f_cipher_mode_bssmap_to_rr(g_pars.encr.enc_alg_expect);
6505 tr_cms.sC := '1'B;
6506 }
6507 if (not match(cms, tr_cms)) {
6508 setverdict(fail, "RR Handover Command: unexpected Cipher Mode Setting IE: ",
6509 cms, ", expected: ", tr_cms);
6510 }
6511 } else {
6512 setverdict(fail, "RR Handover Command: Cipher Mode Setting IE is not present");
6513 }
6514
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006515 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6516 * tells the MS to handover to the new lchan. Here comes the new MS on
6517 * the new lchan with a Handover RACH: */
6518
6519 /* send handover detect */
6520
6521 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6522
6523 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6524
6525 /* send handover complete over the new channel */
6526
6527 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_HandoverComplete('00'O));
6528 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
6529 enc_PDU_ML3_MS_NW(l3_tx)));
6530
6531 BSSAP.receive(tr_BSSMAP_HandoverComplete);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006532 deactivate(as_media);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006533 setverdict(pass);
6534}
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006535
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006536private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006537 var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006538 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
6539 if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
6540 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006541 }
6542 if (g_pars.exp_fast_return) {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006543 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006544 } else {
6545 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006546 }
6547 f_ho_into_this_bsc(id, oldToNewBSSIEs);
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006548 if (g_pars.expect_ho_fail) {
6549 f_perform_clear_no_lchan();
Oliver Smith7a8594a2023-02-13 14:30:49 +01006550 } else if (g_pars.expect_ho_fail_lchan_est) {
6551 BSSAP.receive(tr_BSSMAP_ClearRequest);
6552 f_perform_clear_no_lchan();
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006553 } else {
6554 f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
6555 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006556 setverdict(pass);
6557}
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006558function 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 +01006559 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006560
6561 f_init(1, true);
6562 f_sleep(1.0);
6563
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006564 f_vty_encryption_a5(vty_a5_cfg);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006565 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006566
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006567 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6568 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006569
6570 vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
6571 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006572
6573 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006574 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006575 if (pars.expect_ho_fail) {
6576 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6577 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:failed");
Oliver Smith7a8594a2023-02-13 14:30:49 +01006578 } else if (pars.expect_ho_fail_lchan_est) {
6579 f_ctrs_bsc_and_bts_add(0, "handover:error");
6580 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006581 } else {
6582 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6583 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
6584 }
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006585 f_ctrs_bsc_and_bts_verify();
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006586
6587 f_vty_encryption_a5_reset();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006588}
6589
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006590testcase TC_ho_into_this_bsc() runs on test_CT {
6591 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6592 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006593 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006594}
6595
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006596function f_tc_ho_into_this_bsc_a5(TestHdlrEncrParams encr, charstring vty_a5_cfg := VTY_A5_DEFAULT,
6597 boolean expect_fail := false) runs on test_CT {
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006598 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006599 pars.encr := encr;
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006600 pars.expect_ho_fail := expect_fail;
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006601 f_tc_ho_into_this_bsc_main(pars, vty_a5_cfg);
Oliver Smith39f53072022-10-27 14:44:04 +02006602 f_shutdown_helper(ho := true);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006603}
6604
6605testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006606 f_tc_ho_into_this_bsc_a5(f_encr_params('01'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006607}
6608
6609testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006610 f_tc_ho_into_this_bsc_a5(f_encr_params('02'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006611}
6612
6613testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006614 f_tc_ho_into_this_bsc_a5(f_encr_params('08'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006615}
6616
6617testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006618 f_tc_ho_into_this_bsc_a5(f_encr_params('10'O, kc128 := true), "3 4");
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006619}
6620
Neels Hofmeyr1951be22022-02-16 16:21:07 +01006621/* Report: in inter-BSC incoming handover, when the MSC omits the Chosen Encryption Algorithm IE in the Handover Request
6622 * message, then osmo-bsc starts an unencrypted lchan even if A5/0 is not permitted.
6623 *
6624 * This test verifies that the Encryption Information is present in the Channel Activation when the Chosen Enc Alg is
6625 * omitted.
6626 *
6627 * Related: SYS#5839
6628 */
6629testcase TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() runs on test_CT {
6630 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O, alg_chosen := omit));
6631}
6632
6633testcase TC_ho_into_this_bsc_a5_1_3() runs on test_CT {
6634 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O));
6635}
6636
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006637/* Send a permitted algo mask that does not intersect with osmo-bsc.cfg */
6638testcase TC_ho_into_this_bsc_a5_mismatch() runs on test_CT {
6639 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '18'O, alg_expect := '10'O), "0 1",
6640 expect_fail := true); // 0x18 = A5/3 and A5/4
6641}
6642
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006643testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
6644 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6645 pars.host_aoip_tla := "::6";
6646 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006647 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006648}
6649
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006650/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006651 to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006652 channel is later released (RR CHannel Release), should trigger inclusion of
6653 IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
6654 neighbors. */
6655testcase TC_srvcc_eutran_to_geran() runs on test_CT {
6656 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6657 pars.last_used_eutran_plmn := '323454'O;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006658 pars.exp_fast_return := true;
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006659 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006660
6661 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6662 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6663 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006664 f_shutdown_helper(ho := true);
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006665}
6666
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006667/* Same as TC_srvcc_eutran_to_geran, but enables ciphering on the target channel. */
6668testcase TC_srvcc_eutran_to_geran_a5_3() runs on test_CT {
6669 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6670 pars.encr := f_encr_params('08'O); /* only A5/3 */
6671 pars.last_used_eutran_plmn := '323454'O;
6672 pars.exp_fast_return := true;
6673 f_tc_ho_into_this_bsc_main(pars);
6674
6675 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6676 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6677 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006678 f_shutdown_helper(ho := true);
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006679}
6680
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006681/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
6682 on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
6683 list when the channel is released. */
6684testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
6685 f_init_vty();
6686 f_vty_allow_srvcc_fast_return(true, 0)
6687
6688 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6689 pars.last_used_eutran_plmn := '323454'O;
6690 pars.exp_fast_return := false;
6691 f_tc_ho_into_this_bsc_main(pars);
6692 f_vty_allow_srvcc_fast_return(false, 0);
6693 f_shutdown_helper();
6694}
6695
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01006696/* Same as TC_srvcc_eutran_to_geran, but using SAI as serving Cell Identifier. SYS#5838 */
6697testcase TC_srvcc_eutran_to_geran_src_sai() runs on test_CT {
6698 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6699 pars.last_used_eutran_plmn := '323454'O;
6700 pars.cell_id_source := valueof(ts_CellID_SAI('123456'O, 300, 444));
6701 f_tc_ho_into_this_bsc_main(pars);
6702
6703 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6704 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6705 f_ctrs_bsc_and_bts_verify();
6706 f_shutdown_helper();
6707}
6708
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006709private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
6710 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
6711 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
6712 f_ho_into_this_bsc(id, oldToNewBSSIEs);
6713 f_ho_out_of_this_bsc(oldToNewBSSIEs);
6714 setverdict(pass);
6715}
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006716
6717private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
6718 runs on test_CT {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006719 var MSC_ConnHdlr vc_conn;
6720 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6721
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006722 f_init_vty();
6723 f_bts_0_cfg(BSCVTY,
6724 {"neighbor-list mode automatic",
6725 "handover 1",
6726 "handover algorithm 2",
6727 "handover2 window rxlev averaging 1",
6728 "no neighbors",
6729 "neighbor lac 99 arfcn 123 bsic any"});
6730 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6731
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006732 f_init(1, true);
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006733 if (disable_fast_return) {
6734 f_vty_allow_srvcc_fast_return(true, 0);
6735 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006736 f_sleep(1.0);
6737
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006738 f_ctrs_bsc_and_bts_handover_init();
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006739
6740 pars.last_used_eutran_plmn := '323454'O;
6741 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6742 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
6743
6744 vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
6745 vc_conn.done;
6746
6747 f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
6748 f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
6749 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
6750 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
6751 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
6752 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006753
6754 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
6755 f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006756 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006757
6758 if (disable_fast_return) {
6759 f_vty_allow_srvcc_fast_return(false, 0);
6760 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006761 f_shutdown_helper();
6762}
6763
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006764/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
6765 BSS Information" IE with "Last Used E-UTRAN PLMN Id".
6766 Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
6767 IE with "Last Used E-UTRAN PLMN Id" from first step. */
6768testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
6769 f_tc_srvcc_eutran_to_geran_ho_out_main(false);
6770}
6771/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
6772 * independently of fast-reture allowed/forbidden in local BTS */
6773testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
6774 f_tc_srvcc_eutran_to_geran_ho_out_main(true);
6775}
6776
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006777private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
6778 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6779 f_rslem_register(0, new_chan_nr);
6780 g_chan_nr := new_chan_nr;
6781 f_sleep(1.0);
6782
6783 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6784 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6785 activate(as_Media());
6786
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006787 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006788 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006789 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006790
6791 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6792
6793 var PDU_BSSAP rx_bssap;
6794 var octetstring ho_command_str;
6795
6796 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6797
6798 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6799 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6800 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6801 log("L3 Info in HO Request Ack is ", ho_command);
6802
6803 var GsmArfcn arfcn;
6804 var RslChannelNr actual_new_chan_nr;
6805 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6806 actual_new_chan_nr, arfcn);
6807
6808 if (actual_new_chan_nr != new_chan_nr) {
6809 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6810 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6811 setverdict(fail);
6812 return;
6813 }
6814 log("Handover Command chan_nr is", actual_new_chan_nr);
6815
Neels Hofmeyr61ca08d2019-05-06 23:52:22 +02006816 /* For deterministic test results, give some time for the MGW endpoint to be configured */
6817 f_sleep(1.0);
6818
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006819 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6820 * tells the MS to handover to the new lchan. In this case, the MS
6821 * reports a Handover Failure to the old BSS, which forwards a BSSMAP
6822 * Handover Failure to the MSC. The procedure according to 3GPP TS
6823 * 48.008 3.1.5.3.2 "Handover Failure" is then that the MSC sends a
6824 * BSSMAP Clear Command: */
6825
6826 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6827 var BssmapCause cause := enum2int(cause_val);
6828 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6829
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006830 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006831 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006832 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006833
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006834 setverdict(pass);
6835 f_sleep(1.0);
6836
6837 setverdict(pass);
6838}
6839testcase TC_ho_in_fail_msc_clears() runs on test_CT {
6840 var MSC_ConnHdlr vc_conn;
6841 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6842
6843 f_init(1, true);
6844 f_sleep(1.0);
6845
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006846 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006847
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006848 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6849 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006850
6851 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
6852 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006853
6854 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6855 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6856 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6857 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6858 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006859 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006860}
6861
6862private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
6863 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6864 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6865 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6866 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6867 * before we get started. */
6868 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6869 f_rslem_register(0, new_chan_nr);
6870 g_chan_nr := new_chan_nr;
6871 f_sleep(1.0);
6872
6873 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6874 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6875 activate(as_Media());
6876
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006877 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006878 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006879 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006880
6881 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6882
6883 var PDU_BSSAP rx_bssap;
6884 var octetstring ho_command_str;
6885
6886 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6887
6888 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6889 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6890 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6891 log("L3 Info in HO Request Ack is ", ho_command);
6892
6893 var GsmArfcn arfcn;
6894 var RslChannelNr actual_new_chan_nr;
6895 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6896 actual_new_chan_nr, arfcn);
6897
6898 if (actual_new_chan_nr != new_chan_nr) {
6899 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6900 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6901 setverdict(fail);
6902 return;
6903 }
6904 log("Handover Command chan_nr is", actual_new_chan_nr);
6905
6906 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6907 * tells the MS to handover to the new lchan. Here comes the new MS on
6908 * the new lchan with a Handover RACH: */
6909
6910 /* send handover detect */
6911
6912 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6913
6914 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6915
6916 /* The MSC chooses to clear the connection now, maybe we got the
6917 * Handover RACH on the new cell but the MS still signaled Handover
6918 * Failure to the old BSS? */
6919
6920 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6921 var BssmapCause cause := enum2int(cause_val);
6922 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6923
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006924 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006925 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006926 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006927
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006928 f_sleep(1.0);
6929}
6930testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
6931 var MSC_ConnHdlr vc_conn;
6932 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6933
6934 f_init(1, true);
6935 f_sleep(1.0);
6936
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006937 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006938
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006939 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6940 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006941
6942 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
6943 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006944
6945 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6946 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6947 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6948 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6949 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006950 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006951}
6952
6953/* The new BSS's lchan times out before the MSC decides that handover failed. */
6954private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
6955 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6956 f_rslem_register(0, new_chan_nr);
6957 g_chan_nr := new_chan_nr;
6958 f_sleep(1.0);
6959
6960 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6961 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01006962 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006963
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006964 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006965 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006966 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006967
6968 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6969
6970 var PDU_BSSAP rx_bssap;
6971 var octetstring ho_command_str;
6972
6973 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6974
6975 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6976 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6977 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6978 log("L3 Info in HO Request Ack is ", ho_command);
6979
6980 var GsmArfcn arfcn;
6981 var RslChannelNr actual_new_chan_nr;
6982 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6983 actual_new_chan_nr, arfcn);
6984
6985 if (actual_new_chan_nr != new_chan_nr) {
6986 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6987 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6988 setverdict(fail);
6989 return;
6990 }
6991 log("Handover Command chan_nr is", actual_new_chan_nr);
6992
6993 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6994 * tells the MS to handover to the new lchan. But the MS never shows up
6995 * on the new lchan. */
6996
6997 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6998
6999 /* Did osmo-bsc also send a Clear Request? */
7000 timer T := 0.5;
7001 T.start;
7002 alt {
7003 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
7004 [] T.timeout { }
7005 }
7006
7007 /* MSC plays along with a Clear Command (no matter whether osmo-bsc
7008 * asked for it, this is a Handover Failure after all). */
7009
7010 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
7011 var BssmapCause cause := enum2int(cause_val);
7012 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7013
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007014 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007015 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007016 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007017
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007018 f_sleep(1.0);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007019}
7020testcase TC_ho_in_fail_no_detect() runs on test_CT {
7021 var MSC_ConnHdlr vc_conn;
7022 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7023
Oliver Smithd49f46d2023-03-08 12:23:13 +01007024 pars.fail_on_dlcx := false;
7025
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007026 f_init(1, true);
7027 f_sleep(1.0);
7028
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007029 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007030
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007031 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7032 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007033
7034 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect), pars);
7035 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007036
7037 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7038 f_ctrs_bsc_and_bts_add(0, "handover:error");
7039 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7040 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7041 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007042 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007043}
7044
7045/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
7046private function f_tc_ho_in_fail_no_detect2(charstring id) runs on MSC_ConnHdlr {
7047 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
7048 f_rslem_register(0, new_chan_nr);
7049 g_chan_nr := new_chan_nr;
7050 f_sleep(1.0);
7051
7052 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
7053 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01007054 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007055
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007056 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007057 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02007058 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007059
7060 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
7061
7062 var PDU_BSSAP rx_bssap;
7063 var octetstring ho_command_str;
7064
7065 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
7066
7067 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
7068 log("Received L3 Info in HO Request Ack: ", ho_command_str);
7069 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
7070 log("L3 Info in HO Request Ack is ", ho_command);
7071
7072 var GsmArfcn arfcn;
7073 var RslChannelNr actual_new_chan_nr;
7074 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
7075 actual_new_chan_nr, arfcn);
7076
7077 if (actual_new_chan_nr != new_chan_nr) {
7078 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
7079 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
7080 setverdict(fail);
7081 return;
7082 }
7083 log("Handover Command chan_nr is", actual_new_chan_nr);
7084
7085 /* Now the MSC forwards the RR Handover Command to the other BSC, which
7086 * tells the MS to handover to the new lchan. But the MS never shows up
7087 * on the new lchan. */
7088
7089 BSSAP.receive(tr_BSSMAP_HandoverFailure);
7090
7091 /* MSC plays dumb and sends no Clear Command */
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007092 var PDU_BSSAP rx_clear_request;
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02007093
7094 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request {
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007095 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
7096 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7097 };
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007098 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007099 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007100 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007101
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007102 f_sleep(1.0);
7103}
7104testcase TC_ho_in_fail_no_detect2() runs on test_CT {
7105 var MSC_ConnHdlr vc_conn;
7106 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7107
Oliver Smith735b47c2023-02-15 16:03:54 +01007108 pars.fail_on_dlcx := false;
7109
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007110 f_init(1, true);
7111 f_sleep(1.0);
7112
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007113 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007114
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007115 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7116 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007117
7118 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
7119 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007120
7121 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7122 f_ctrs_bsc_and_bts_add(0, "handover:error");
7123 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7124 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7125 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007126 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007127}
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01007128
Oliver Smith7a8594a2023-02-13 14:30:49 +01007129testcase TC_ho_in_fail_mgw_mdcx_timeout() runs on test_CT {
7130 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7131
7132 pars.ignore_mgw_mdcx := true;
7133 pars.expect_ho_fail_lchan_est := true;
7134
7135 f_tc_ho_into_this_bsc_main(pars);
7136 f_shutdown_helper(ho := true);
7137}
7138
Oliver Smith4eed06f2023-02-15 15:43:19 +01007139testcase TC_ho_in_fail_ipa_crcx_timeout() runs on test_CT {
7140 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7141
7142 pars.ignore_ipa_media := true;
7143 pars.expect_ho_fail_lchan_est := true;
7144 pars.fail_on_dlcx := false;
7145
7146 f_tc_ho_into_this_bsc_main(pars);
7147 f_shutdown_helper(ho := true);
7148}
7149
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007150/* An incoming inter-BSC HO can either issue the Handover Request message attached to the initial SCCP N-Connect (as in
7151 * the other tests we have so far), or the first CR can be "empty" with the BSSAP request following later. Test the
7152 * empty N-Connect case. */
7153testcase TC_ho_into_this_bsc_sccp_cr_without_bssap() runs on test_CT {
7154 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7155 pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr := false;
7156 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02007157 f_shutdown_helper(ho := true);
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007158}
7159
Neels Hofmeyr91401012019-07-11 00:42:35 +02007160type record of charstring Commands;
7161
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007162private function f_bts_0_cfg(TELNETasp_PT pt, Commands cmds := {})
Neels Hofmeyr91401012019-07-11 00:42:35 +02007163{
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007164 f_vty_enter_cfg_bts(pt, 0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007165 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007166 f_vty_transceive(pt, cmds[i]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007167 }
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007168 f_vty_transceive(pt, "end");
Neels Hofmeyr91401012019-07-11 00:42:35 +02007169}
7170
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01007171private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
7172{
7173 f_vty_enter_cfg_cs7_inst(pt, 0);
7174 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
7175 f_vty_transceive(pt, cmds[i]);
7176 }
7177 f_vty_transceive(pt, "end");
7178}
7179
Neels Hofmeyr91401012019-07-11 00:42:35 +02007180private function f_probe_for_handover(charstring log_label,
7181 charstring log_descr,
7182 charstring handover_vty_cmd,
7183 boolean expect_handover,
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007184 boolean is_inter_bsc_handover := false,
7185 template uint3_t expect_target_tsc := ?)
Neels Hofmeyr91401012019-07-11 00:42:35 +02007186runs on MSC_ConnHdlr
7187{
Neels Hofmeyrb3fc8982020-05-11 00:16:42 +02007188 /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
7189 * lchans to be established on bts 1 or bts 2. */
7190 f_rslem_suspend(RSL1_PROC);
7191 f_rslem_suspend(RSL2_PROC);
7192
Neels Hofmeyr91401012019-07-11 00:42:35 +02007193 var RSL_Message rsl;
7194
7195 var charstring log_msg := " (expecting handover)"
7196 if (not expect_handover) {
7197 log_msg := " (expecting NO handover)";
7198 }
7199 log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg);
7200 f_vty_transceive(BSCVTY, handover_vty_cmd);
7201
Neels Hofmeyr91401012019-07-11 00:42:35 +02007202 timer T := 2.0;
7203 T.start;
7204
7205 alt {
7206 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
7207 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
7208 log("Rx L3 from net: ", l3);
7209 if (ischosen(l3.msgs.rrm.handoverCommand)) {
7210 var RslChannelNr new_chan_nr;
7211 var GsmArfcn arfcn;
7212 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
7213 new_chan_nr, arfcn);
7214 log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
7215 log(l3.msgs.rrm.handoverCommand);
7216
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007217 /* Verify correct TSC in handoverCommand */
7218 var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
7219 if (not match(got_tsc, expect_target_tsc)) {
7220 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
7221 expect_target_tsc, " got ", got_tsc);
7222 mtc.stop;
7223 } else {
7224 log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
7225 expect_target_tsc, ")");
7226 }
7227
Neels Hofmeyr91401012019-07-11 00:42:35 +02007228 /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
7229 * matter on which BTS it really is, we're not going to follow through an entire handover
7230 * anyway. */
7231 f_rslem_register(0, new_chan_nr, RSL1_PROC);
7232 f_rslem_resume(RSL1_PROC);
7233 f_rslem_register(0, new_chan_nr, RSL2_PROC);
7234 f_rslem_resume(RSL2_PROC);
7235
7236 if (expect_handover and not is_inter_bsc_handover) {
7237 setverdict(pass);
7238 log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected.");
7239 } else {
7240 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. "
7241 & log_label & ": " & log_descr);
7242 }
7243
7244 log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
7245 /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with
7246 * Handover Failure. */
7247 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
7248
7249 /* target BTS is told to release lchan again; don't care which BTS nor what messages. */
7250 f_sleep(0.5);
7251 RSL1.clear;
7252 RSL2.clear;
7253 log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)");
7254 break;
7255 } else {
7256 repeat;
7257 }
7258 }
7259 [] BSSAP.receive(tr_BSSMAP_HandoverRequired) {
7260 if (expect_handover and is_inter_bsc_handover) {
7261 setverdict(pass);
7262 log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected.");
7263 } else {
7264 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. "
7265 & log_label & ": " & log_descr);
7266 }
7267
7268 log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)");
7269
7270 /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to
7271 * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required,
7272 * setting a short timeout and waiting is the only way. */
7273 log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out...");
7274 f_sleep(1.5);
7275 log("f_probe_for_handover(" & log_label & "): ...done");
7276
7277 break;
7278 }
7279 [] T.timeout {
7280 if (expect_handover) {
7281 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. "
7282 & log_label & ": " & log_descr);
7283 } else {
7284 setverdict(pass);
7285 log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected.");
7286 }
7287 log("f_probe_for_handover(" & log_label & "): done (got no Handover)");
7288 break;
7289 }
7290 }
7291
7292 f_rslem_resume(RSL1_PROC);
7293 f_rslem_resume(RSL2_PROC);
7294 f_sleep(3.0);
7295 RSL.clear;
7296
7297 log("f_probe_for_handover(" & log_label & "): done clearing");
7298}
7299
7300/* Test the effect of various neighbor configuration scenarios:
7301 *
7302 * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0.
7303 * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO.
7304 */
7305private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
7306 g_pars := f_gen_test_hdlr_pars();
7307 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
7308 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007309
7310 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
7311 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
7312
7313 /* Establish lchan at bts 0 */
7314 f_establish_fully(ass_cmd, exp_compl);
7315
7316 /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */
7317 f_vty_enter_cfg_network(BSCVTY);
7318 f_vty_transceive(BSCVTY, "timer T7 1");
7319 f_vty_transceive(BSCVTY, "end");
7320}
7321
7322private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
7323 f_tc_ho_neighbor_config_start();
7324
7325 /*
7326 * bts 0 ARFCN 871 BSIC 10
7327 * bts 1 ARFCN 871 BSIC 11
7328 * bts 2 ARFCN 871 BSIC 12
7329 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7330 */
7331
7332 log("f_tc_ho_neighbor_config: 1. No 'neighbor' config");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007333 f_bts_0_cfg(BSCVTY, {"no neighbors"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007334 f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
7335 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007336 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007337
7338 f_probe_for_handover("1.b", "HO to unknown cell does not start",
7339 "handover any to arfcn 13 bsic 39",
7340 false);
7341
7342 f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error",
7343 "handover any to arfcn 871 bsic 12",
7344 false);
7345
7346 f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
7347 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007348 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007349
7350 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007351}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007352testcase TC_ho_neighbor_config_1() runs on test_CT {
7353 var MSC_ConnHdlr vc_conn;
7354 f_init(3, true, guard_timeout := 60.0);
7355 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007356 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007357 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
7358 vc_conn.done;
7359
7360 /* f_tc_ho_neighbor_config_start() */
7361 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7362 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7363
7364 /* 1.a */
7365 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7366 * handover quickly by sending a Handover Failure message. */
7367 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7368 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7369 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7370 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007371 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7372 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007373
7374 /* 1.b */
7375 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7376 f_ctrs_bsc_and_bts_add(0, "handover:error");
7377
7378 /* 1.c */
7379 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7380 f_ctrs_bsc_and_bts_add(0, "handover:error");
7381
7382 /* 1.d */
7383 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7384 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7385 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7386 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007387 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7388 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007389
7390 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007391 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007392}
7393
Neels Hofmeyr91401012019-07-11 00:42:35 +02007394private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
7395 f_tc_ho_neighbor_config_start();
7396
7397 /*
7398 * bts 0 ARFCN 871 BSIC 10
7399 * bts 1 ARFCN 871 BSIC 11
7400 * bts 2 ARFCN 871 BSIC 12
7401 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7402 */
7403
7404 log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007405 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007406 f_sleep(0.5);
7407
7408 f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
7409 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007410 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007411
7412 f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
7413 "handover any to arfcn 871 bsic 12",
7414 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007415 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007416}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007417testcase TC_ho_neighbor_config_2() runs on test_CT {
7418 var MSC_ConnHdlr vc_conn;
7419 f_init(3, true, guard_timeout := 50.0);
7420 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007421 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007422 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
7423 vc_conn.done;
7424
7425 /* f_tc_ho_neighbor_config_start() */
7426 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7427 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7428
7429 /* 2.a */
7430 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7431 * handover quickly by sending a Handover Failure message. */
7432 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7433 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7434 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7435 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007436 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7437 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007438
7439 /* 2.b */
7440 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7441 f_ctrs_bsc_and_bts_add(0, "handover:error");
7442
7443 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007444 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007445}
7446
Neels Hofmeyr91401012019-07-11 00:42:35 +02007447private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
7448 f_tc_ho_neighbor_config_start();
7449
7450 /*
7451 * bts 0 ARFCN 871 BSIC 10
7452 * bts 1 ARFCN 871 BSIC 11
7453 * bts 2 ARFCN 871 BSIC 12
7454 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7455 */
7456
7457 log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007458 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007459 f_sleep(0.5);
7460
7461 f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor",
7462 "handover any to arfcn 871 bsic 11",
7463 false);
7464 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",
7465 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007466 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007467 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007468}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007469testcase TC_ho_neighbor_config_3() runs on test_CT {
7470 var MSC_ConnHdlr vc_conn;
7471 f_init(3, true, guard_timeout := 50.0);
7472 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007473 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007474 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
7475 vc_conn.done;
7476
7477 /* f_tc_ho_neighbor_config_start() */
7478 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7479 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7480
7481 /* 3.a */
7482 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7483 f_ctrs_bsc_and_bts_add(0, "handover:error");
7484
7485 /* 3.b */
7486 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7487 * handover quickly by sending a Handover Failure message. */
7488 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7489 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7490 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7491 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007492 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7493 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007494
7495 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007496 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007497}
7498
Neels Hofmeyr91401012019-07-11 00:42:35 +02007499private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
7500 f_tc_ho_neighbor_config_start();
7501
7502 /*
7503 * bts 0 ARFCN 871 BSIC 10
7504 * bts 1 ARFCN 871 BSIC 11
7505 * bts 2 ARFCN 871 BSIC 12
7506 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7507 */
7508
7509 log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007510 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007511 f_sleep(0.5);
7512
7513 f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor",
7514 "handover any to arfcn 871 bsic 11",
7515 false);
7516 f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor",
7517 "handover any to arfcn 871 bsic 12",
7518 false);
7519 f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
7520 "handover any to arfcn 123 bsic 45",
7521 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007522 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007523}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007524testcase TC_ho_neighbor_config_4() runs on test_CT {
7525 var MSC_ConnHdlr vc_conn;
7526 f_init(3, true, guard_timeout := 50.0);
7527 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007528 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007529 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
7530 vc_conn.done;
7531
7532 /* f_tc_ho_neighbor_config_start() */
7533 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7534 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7535
7536 /* 4.a */
7537 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7538 f_ctrs_bsc_and_bts_add(0, "handover:error");
7539
7540 /* 4.b */
7541 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7542 f_ctrs_bsc_and_bts_add(0, "handover:error");
7543
7544 /* 4.c */
7545 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7546 * handover quickly by timing out after the Handover Required message */
7547 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7548 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7549 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7550 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7551
7552 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007553 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007554}
7555
Neels Hofmeyr91401012019-07-11 00:42:35 +02007556private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
7557 f_tc_ho_neighbor_config_start();
7558
7559 /*
7560 * bts 0 ARFCN 871 BSIC 10
7561 * bts 1 ARFCN 871 BSIC 11
7562 * bts 2 ARFCN 871 BSIC 12
7563 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7564 */
7565
7566 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 +02007567 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007568 f_sleep(0.5);
7569
7570 f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
7571 "handover any to arfcn 871 bsic 12",
7572 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007573 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007574}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007575testcase TC_ho_neighbor_config_5() runs on test_CT {
7576 var MSC_ConnHdlr vc_conn;
7577 f_init(3, true);
7578 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007579 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007580 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
7581 vc_conn.done;
7582
7583 /* f_tc_ho_neighbor_config_start() */
7584 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7585 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7586
7587 /* 5 */
7588 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7589 * handover quickly by timing out after the Handover Required message */
7590 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7591 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7592 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7593 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7594
7595 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007596 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007597}
7598
Neels Hofmeyr91401012019-07-11 00:42:35 +02007599private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
7600 f_tc_ho_neighbor_config_start();
7601
7602 /*
7603 * bts 0 ARFCN 871 BSIC 10
7604 * bts 1 ARFCN 871 BSIC 11
7605 * bts 2 ARFCN 871 BSIC 12
7606 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7607 */
7608
7609 log("f_tc_ho_neighbor_config: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:"
7610 & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007611 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007612 f_sleep(0.5);
7613
7614 f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
7615 "handover any to arfcn 871 bsic 12",
7616 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007617 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007618}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007619testcase TC_ho_neighbor_config_6() runs on test_CT {
7620 var MSC_ConnHdlr vc_conn;
7621 f_init(3, true);
7622 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007623 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007624 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
7625 vc_conn.done;
7626
7627 /* f_tc_ho_neighbor_config_start() */
7628 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7629 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7630
7631 /* 6.a */
7632 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7633 * handover quickly by timing out after the Handover Required message */
7634 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7635 f_ctrs_bsc_and_bts_add(0, "handover:error");
7636
7637 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007638 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007639}
7640
Neels Hofmeyr91401012019-07-11 00:42:35 +02007641private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
7642 f_tc_ho_neighbor_config_start();
7643
7644 /*
7645 * bts 0 ARFCN 871 BSIC 10
7646 * bts 1 ARFCN 871 BSIC 11
7647 * bts 2 ARFCN 871 BSIC 12
7648 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7649 */
7650
7651 log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:"
7652 & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007653 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007654 f_sleep(0.5);
7655
7656 f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
7657 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007658 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007659 f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
7660 "handover any to arfcn 123 bsic 45",
7661 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007662 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007663}
Neels Hofmeyr91401012019-07-11 00:42:35 +02007664testcase TC_ho_neighbor_config_7() runs on test_CT {
7665 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf2b88032020-06-16 00:35:04 +02007666 f_init(3, true, guard_timeout := 50.0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007667 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007668 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007669 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
7670 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007671
7672 /* f_tc_ho_neighbor_config_start() */
7673 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7674 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7675
7676 /* 7.a */
7677 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7678 * handover quickly by sending a Handover Failure message. */
7679 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7680 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7681 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7682 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007683 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7684 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007685
7686 /* 7.b */
7687 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7688 * handover quickly by timing out after the Handover Required message */
7689 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7690 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7691 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7692 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7693
7694 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007695 f_shutdown_helper(ho := true);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007696}
7697
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007698/* OS#3041: Open and close N connections in a normal fashion, and expect no
7699 * BSSMAP Reset just because of that. */
7700testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
7701 var default d;
7702 var integer i;
7703 var DchanTuple dt;
7704
7705 f_init();
7706
7707 /* Wait for initial BSSMAP Reset to pass */
7708 f_sleep(4.0);
7709
7710 d := activate(no_bssmap_reset());
7711
7712 /* Setup up a number of connections and RLSD them again from the MSC
7713 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7714 * Let's do it some more times for good measure. */
Harald Weltec3260d92018-06-11 17:48:16 +02007715 for (i := 0; i < 4; i := i+1) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007716 /* Since we're doing a lot of runs, give each one a fresh
7717 * T_guard from the top. */
7718 T_guard.start;
7719
7720 /* Setup a BSSAP connection and clear it right away. This is
7721 * the MSC telling the BSC about a planned release, it's not an
7722 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007723 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007724
7725 /* MSC disconnects (RLSD). */
7726 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
7727 }
7728
7729 /* In the buggy behavior, a timeout of 2 seconds happens between above
7730 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7731 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7732 f_sleep(4.0);
7733
7734 deactivate(d);
7735 f_shutdown_helper();
7736}
Harald Welte552620d2017-12-16 23:21:36 +01007737
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007738/* OS#3041: Open and close N connections in a normal fashion, and expect no
7739 * BSSMAP Reset just because of that. Invoke the release by a BSSMAP Clear from
7740 * the MSC. */
7741testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
7742 var default d;
7743 var integer i;
7744 var DchanTuple dt;
7745 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007746 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
7747 var BssmapCause cause := enum2int(cause_val);
7748
7749 f_init();
7750
7751 /* Wait for initial BSSMAP Reset to pass */
7752 f_sleep(4.0);
7753
7754 d := activate(no_bssmap_reset());
7755
7756 /* Setup up a number of connections and RLSD them again from the MSC
7757 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7758 * Let's do it some more times for good measure. */
7759 for (i := 0; i < 8; i := i+1) {
7760 /* Since we're doing a lot of runs, give each one a fresh
7761 * T_guard from the top. */
7762 T_guard.start;
7763
7764 /* Setup a BSSAP connection and clear it right away. This is
7765 * the MSC telling the BSC about a planned release, it's not an
7766 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007767 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007768
7769 /* Instruct BSC to clear channel */
7770 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7771
7772 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007773 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007774 }
7775
7776 /* In the buggy behavior, a timeout of 2 seconds happens between above
7777 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7778 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7779 f_sleep(4.0);
7780
7781 deactivate(d);
7782 f_shutdown_helper();
7783}
7784
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007785/* OS#3041: Open and close N connections in a normal fashion, and expect no
7786 * BSSMAP Reset just because of that. Close connections from the MS side with a
7787 * Release Ind on RSL. */
7788testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
7789 var default d;
7790 var integer i;
7791 var DchanTuple dt;
7792 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007793 var integer j;
7794
7795 f_init();
7796
7797 /* Wait for initial BSSMAP Reset to pass */
7798 f_sleep(4.0);
7799
7800 d := activate(no_bssmap_reset());
7801
7802 /* Setup up a number of connections and RLSD them again from the MSC
7803 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7804 * Let's do it some more times for good measure. */
7805 for (i := 0; i < 8; i := i+1) {
7806 /* Since we're doing a lot of runs, give each one a fresh
7807 * T_guard from the top. */
7808 T_guard.start;
7809
7810 /* Setup a BSSAP connection and clear it right away. This is
7811 * the MSC telling the BSC about a planned release, it's not an
7812 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007813 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007814
7815 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007816 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007817
7818 /* expect Clear Request on MSC side */
7819 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
7820
7821 /* Instruct BSC to clear channel */
7822 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
7823 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7824
7825 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007826 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007827 }
7828
7829 /* In the buggy behavior, a timeout of 2 seconds happens between above
7830 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7831 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7832 f_sleep(4.0);
7833
7834 deactivate(d);
7835 f_shutdown_helper();
7836}
7837
Harald Welte94e0c342018-04-07 11:33:23 +02007838/***********************************************************************
7839 * IPA style dynamic PDCH
7840 ***********************************************************************/
7841
7842private function f_dyn_ipa_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7843 template (omit) RSL_Cause nack := omit)
7844runs on test_CT {
7845 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7846 var RSL_Message rsl_unused;
7847 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7848 f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
7849 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007850 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007851 if (istemplatekind(nack, "omit")) {
7852 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007853 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007854 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007855 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007856 }
7857}
7858
7859private function f_dyn_ipa_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7860 template (omit) RSL_Cause nack := omit)
7861runs on test_CT {
7862 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7863 var RSL_Message rsl_unused;
7864 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7865 f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
7866 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007867 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_DEACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007868 if (istemplatekind(nack, "omit")) {
7869 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007870 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007871 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007872 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007873 }
7874}
7875
7876private function f_ts_dyn_mode_get(integer bts_nr, integer trx_nr, integer ts_nr)
7877runs on test_CT return charstring {
7878 var charstring cmd, resp;
7879 cmd := "show timeslot "&int2str(bts_nr)&" "&int2str(trx_nr)&" "&int2str(ts_nr);
Stefan Sperlingcff13562018-11-13 15:24:06 +01007880 return f_vty_transceive_match_regexp_retry(BSCVTY, cmd, "*\((*)\)*", 0, 4, 1.0);
Harald Welte94e0c342018-04-07 11:33:23 +02007881}
7882
7883private function f_ts_dyn_mode_assert(integer bts_nr, integer trx_nr, integer ts_nr,
7884 template charstring exp)
7885runs on test_CT {
7886 var charstring mode := f_ts_dyn_mode_get(bts_nr, trx_nr, ts_nr);
7887 if (not match(mode, exp)) {
7888 setverdict(fail, "Unexpected TS Mode: ", mode);
Daniel Willmannafce8662018-07-06 23:11:32 +02007889 mtc.stop;
Harald Welte94e0c342018-04-07 11:33:23 +02007890 }
7891}
7892
7893private function f_ts_set_chcomb(integer bts_nr, integer trx_nr, integer ts_nr, charstring chcomb)
7894runs on test_CT {
7895 f_vty_enter_cfg_ts(BSCVTY, bts_nr, trx_nr, ts_nr);
7896 f_vty_transceive(BSCVTY, "phys_chan_config " & chcomb);
7897 f_vty_transceive(BSCVTY, "end");
7898}
7899
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007900
7901private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
7902 var integer i;
7903 for (i := 0; i < 8; i := i + 1) {
7904 f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
7905 }
7906}
7907
Harald Welte94e0c342018-04-07 11:33:23 +02007908private const charstring TCHF_MODE := "TCH/F mode";
7909private const charstring TCHH_MODE := "TCH/H mode";
7910private const charstring PDCH_MODE := "PDCH mode";
7911private const charstring NONE_MODE := "NONE mode";
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007912private const charstring SDCCH8_MODE := "SDCCH8 mode";
Harald Welte94e0c342018-04-07 11:33:23 +02007913
7914/* Test IPA PDCH activation / deactivation triggered by VTY */
7915testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
7916 var RSL_Message rsl_unused;
7917
7918 /* change Timeslot 6 before f_init() starts RSL */
7919 f_init_vty();
7920 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7921 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7922
7923 f_init(1, false);
7924 f_sleep(1.0);
7925
7926 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7927
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007928 log("TCH/F_PDCH pchan starts out in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007929 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7930 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007931 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7932 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007933 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007934 log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007935 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7936
7937 /* De-activate it via VTY */
7938 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7939 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007940 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007941 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7942
7943 /* re-activate it via VTY */
7944 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn);
7945 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007946 log("TCH/F_PDCH pchan, PDCH ACT via VTY, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007947 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7948
7949 /* and finally de-activate it again */
7950 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7951 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007952 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007953 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7954
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007955 /* clean up config */
7956 f_ts_set_chcomb(0, 0, 6, "PDCH");
7957
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007958 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007959}
7960
7961/* Test IPA PDCH activation NACK */
7962testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
7963 var RSL_Message rsl_unused;
7964
7965 /* change Timeslot 6 before f_init() starts RSL */
7966 f_init_vty();
7967 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7968 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7969
7970 f_init(1, false);
7971 f_sleep(1.0);
7972
7973 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7974
7975 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7976 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007977 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7978 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007979 f_sleep(1.0);
7980 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7981
7982 /* De-activate it via VTY */
7983 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7984 f_sleep(1.0);
7985 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7986
7987 /* re-activate it via VTY, but fail that; check BSC still assumes TCH/F mode */
7988 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn, RSL_ERR_EQUIPMENT_FAIL);
7989 f_sleep(1.0);
7990 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7991
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007992 /* clean up config */
7993 f_ts_set_chcomb(0, 0, 6, "PDCH");
7994
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007995 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007996}
7997
7998
7999/***********************************************************************
8000 * Osmocom style dynamic PDCH
8001 ***********************************************************************/
8002
8003private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
8004 template (omit) RSL_Cause nack := omit)
8005runs on test_CT {
8006 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
8007 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02008008 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02008009 /* FIXME: no VTY command to activate Osmocom PDCH !! */
8010 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008011 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT(chan_nr, ?));
Harald Welte94e0c342018-04-07 11:33:23 +02008012 if (istemplatekind(nack, "omit")) {
8013 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008014 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02008015 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008016 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02008017 }
8018}
8019
8020private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
8021 template (omit) RSL_Cause nack := omit)
8022runs on test_CT {
8023 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
8024 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02008025 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02008026 /* FIXME: no VTY command to activate Osmocom PDCH !! */
8027 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008028 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008029 if (istemplatekind(nack, "omit")) {
8030 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008031 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008032 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008033 //f_ipa_tx(ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02008034 }
8035}
8036
8037/* Test Osmocom dyn PDCH activation / deactivation triggered by VTY */
8038testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
8039 var RSL_Message rsl_unused;
8040
8041 /* change Timeslot 6 before f_init() starts RSL */
8042 f_init_vty();
8043 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8044 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8045
8046 f_init(1, false);
8047 f_sleep(1.0);
8048
8049 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8050
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008051 log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02008052 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8053 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008054 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008055
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008056 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02008057 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008058 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 +02008059 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
8060
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008061 /* clean up config */
8062 f_ts_set_chcomb(0, 0, 6, "PDCH");
8063
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008064 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008065}
8066
8067/* Test Osmocom dyn PDCH activation NACK behavior */
8068testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
8069 var RSL_Message rsl_unused;
8070
8071 /* change Timeslot 6 before f_init() starts RSL */
8072 f_init_vty();
8073 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8074 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8075
8076 f_init(1, false);
8077 f_sleep(1.0);
8078
8079 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8080
8081 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8082 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008083 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008084
8085 /* NACK this activation and expect the "show timeslot" mode still to be NONE */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008086 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte94e0c342018-04-07 11:33:23 +02008087 f_sleep(1.0);
8088 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8089
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008090 /* clean up config */
8091 f_ts_set_chcomb(0, 0, 6, "PDCH");
8092
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008093 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008094}
8095
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008096/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
8097testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
8098 var RSL_Message rsl_unused, rsl_msg;
8099 var DchanTuple dt;
8100 var BSSAP_N_CONNECT_ind rx_c_ind;
8101
8102 /* change Timeslot 6 before f_init() starts RSL */
8103 f_init_vty();
8104 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8105 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8106
8107 f_init(1, false);
8108 f_sleep(1.0);
8109
8110 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8111
8112 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8113 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8114 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008115 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008116
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008117 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008118 f_sleep(1.0);
8119 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8120 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8121
8122 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8123 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008124 var DchanTuples sdcch_cleanup := {};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008125 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008126 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008127 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008128 sdcch_cleanup := sdcch_cleanup & { dt };
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008129 }
8130
8131 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008132 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8133 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8134 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008135
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008136 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008137 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008138 dt.idx := {0, 0};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008139
8140 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008141 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8142 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008143 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
8144
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008145 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 +02008146 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8147 dt.sccp_conn_id := rx_c_ind.connectionId;
8148 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8149
8150 /* Instruct BSC to clear channel */
8151 var BssmapCause cause := 0;
8152 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008153 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008154
8155 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008156 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8157 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008158 f_sleep(1.0);
8159 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8160
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008161 /* Clean up SDCCH lchans */
8162 for (i := 0; i < lengthof(sdcch_cleanup); i := i + 1) {
8163 f_perform_clear_test_ct(sdcch_cleanup[i]);
8164 }
8165
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008166 /* clean up config */
8167 f_ts_set_chcomb(0, 0, 6, "PDCH");
8168
8169 f_shutdown_helper();
8170}
8171
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008172/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
8173testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
8174 var ASP_RSL_Unitdata rsl_ud;
8175 var integer i;
8176 var integer chreq_total, chreq_nochan;
8177
8178 f_init_vty();
8179 for (i := 1; i < 8; i := i + 1) {
8180 if (i == 2) {
8181 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8182 } else {
8183 f_ts_set_chcomb(0, 0, i, "PDCH");
8184 }
8185 }
8186 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8187
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008188 f_init(1, guard_timeout := 60.0);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008189
8190 /* The dyn TS want to activate PDCH mode, ACK that. */
8191 var RslChannelNr chan_nr;
8192 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008193 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
8194 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008195
8196 f_sleep(1.0);
8197
8198 /* Exhaust all dedicated SDCCH lchans.
8199 /* GSM 44.018 Table 9.1.8.2:
8200 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
8201 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008202 var DchanTuples chan_cleanup := {};
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008203 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008204 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 +02008205 }
8206
8207 /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008208 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 +02008209 /* Also occupy the seven other SDCCH of the dyn TS */
8210 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008211 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 +01008212 }
8213
8214 /* Clean up SDCCH lchans */
8215 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8216 f_perform_clear_test_ct(chan_cleanup[i]);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008217 }
8218
8219 /* clean up config */
8220 f_ts_reset_chcomb(0);
8221
8222 f_shutdown_helper();
8223}
8224
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008225/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
8226 SDCCH8 would end up in having no free TCH, then BSC should decide to activate
8227 it as TCH directly instead. SYS#5309. */
8228testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
8229 var RSL_Message rsl_unused, rsl_msg;
8230 var DchanTuple dt;
8231 var BSSAP_N_CONNECT_ind rx_c_ind;
8232 var integer i;
8233
8234 /* change Timeslot 6 before f_init() starts RSL */
8235 f_init_vty();
8236 for (i := 1; i < 8; i := i + 1) {
8237 if (i == 6) {
8238 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8239 } else {
8240 f_ts_set_chcomb(0, 0, i, "PDCH");
8241 }
8242 }
8243 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8244
8245 f_init(1, false);
8246 f_sleep(1.0);
8247
8248 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8249
8250 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8251 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8252 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008253 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008254
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008255 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008256 f_sleep(1.0);
8257 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8258 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8259
8260 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8261 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008262 var DchanTuples chan_cleanup := {};
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02008263 var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008264 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008265 dt := f_est_dchan(ra, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008266 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008267 }
8268
8269 /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008270 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
8271 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8272 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008273
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008274 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008275 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008276 dt.idx := {0, 0};
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008277
8278 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008279 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8280 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008281 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
8282
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008283 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 +02008284 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8285 dt.sccp_conn_id := rx_c_ind.connectionId;
8286 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8287
8288 /* Instruct BSC to clear channel */
8289 var BssmapCause cause := 0;
8290 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008291 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008292
8293 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008294 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8295 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008296 f_sleep(1.0);
8297 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8298
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008299 /* Clean up SDCCH lchans */
8300 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8301 f_perform_clear_test_ct(chan_cleanup[i]);
8302 }
8303
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008304 /* clean up config */
8305 f_ts_reset_chcomb(0);
8306 /* TODO: clean up other channels? */
8307
8308 f_shutdown_helper();
8309}
8310
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008311/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
8312testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
8313 var RSL_Message rsl_unused, rsl_msg;
8314 var DchanTuple dt;
8315 var BSSAP_N_CONNECT_ind rx_c_ind;
8316 var GsmRrMessage rr;
8317
8318 /* change Timeslot 6 before f_init() starts RSL */
8319 f_init_vty();
8320 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8321 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8322
8323 f_init(1, false);
8324 f_sleep(1.0);
8325
8326 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8327
8328 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8329 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8330 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008331 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008332
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008333 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008334 f_sleep(1.0);
8335 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8336 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8337
8338 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8339 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008340 var DchanTuples chan_cleanup := {};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008341 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008342 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008343 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008344 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008345 }
8346
8347 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008348 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8349 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8350 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008351
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008352 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008353 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008354 dt.idx := {0, 0};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008355
8356 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008357 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
8358 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008359 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
8360 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
8361 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
8362 }
8363
8364 /* FIXME? Currently the TS stays in state BORKEN: */
8365
8366 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008367 /* rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8368 * f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008369 * f_sleep(1.0);
8370 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
8371 */
8372
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008373 /* Clean up SDCCH lchans */
8374 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8375 f_perform_clear_test_ct(chan_cleanup[i]);
8376 }
8377
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008378 /* clean up config */
8379 f_ts_set_chcomb(0, 0, 6, "PDCH");
8380
8381 f_shutdown_helper();
8382}
8383
Stefan Sperling0796a822018-10-05 13:01:39 +02008384testcase TC_chopped_ipa_ping() runs on test_CT {
Stefan Sperling554123f2018-10-09 14:12:30 +02008385 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port, mp_bsc_ctrl_port};
Stefan Sperling0796a822018-10-05 13:01:39 +02008386 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8387 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8388 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008389 f_shutdown_helper();
Stefan Sperling0796a822018-10-05 13:01:39 +02008390}
8391
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008392testcase TC_chopped_ipa_payload() runs on test_CT {
8393 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port
8394 /* TODO: mp_bsc_ctrl_port does not work yet */};
8395 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8396 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8397 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008398 f_shutdown_helper();
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008399}
8400
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008401/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
8402 the BTS does autonomous MS power control loop */
8403testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
8404 var MSC_ConnHdlr vc_conn;
8405 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8406 //pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
8407 pars.exp_ms_power_params := true;
8408
8409 f_init(1, true);
8410 f_sleep(1.0);
8411 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
8412 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008413 f_shutdown_helper();
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008414}
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008415
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008416/* Verify activation and deactivation of the BCCH carrier power reduction mode */
8417testcase TC_c0_power_red_mode() runs on test_CT {
8418 f_init(1);
8419
8420 for (var integer red := 6; red >= 0; red := red - 2) {
8421 /* Configure BCCH carrier power reduction mode via the VTY */
8422 f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
8423
8424 /* Expect Osmocom specific BS Power Control message on the RSL */
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03008425 var template (present) RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008426 chan_nr := t_RslChanNr_BCCH(0),
8427 bs_power := tr_RSL_IE_BS_Power(red / 2));
8428 tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008429 var RSL_Message unused := f_exp_ipa_rx(tr_rsl_pdu);
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008430
8431 /* Additionally verify the applied value over the CTRL interface */
8432 var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
8433 if (cred != int2str(red)) {
8434 setverdict(fail, "Unexpected BCCH carrier power reduction value ",
8435 cred, " (expected ", red, ")");
8436 }
8437 }
8438
8439 f_shutdown_helper();
8440}
8441
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008442/***********************************************************************
8443 * MSC Pooling
8444 ***********************************************************************/
8445
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008446template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
Harald Weltebf397612021-01-14 20:39:46 +01008447 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 +02008448
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008449private 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 +02008450runs on MSC_ConnHdlr {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008451 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008452 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008453 f_logp(BSCVTY, "Got RSL RR Release");
8454 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008455 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008456 f_logp(BSCVTY, "Got RSL Deact SACCH");
8457 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008458 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008459 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008460 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8461 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008462 break;
8463 }
8464 }
8465}
8466
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008467private altstep as_mgcp_ack_all_dlcx() runs on MSC_ConnHdlr {
8468 var MgcpCommand mgcp_cmd;
8469 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
8470 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
8471 repeat;
8472 }
8473}
8474
8475private altstep as_rsl_ack_all_rel_req() runs on MSC_ConnHdlr {
8476 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
8477 [] RSL.receive(tr_RSL_REL_REQ(g_chan_nr, ?)) {
8478 RSL.send(ts_RSL_REL_CONF(g_chan_nr, main_dcch));
8479 repeat;
8480 }
8481}
8482
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008483friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
8484 template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02008485runs on MSC_ConnHdlr {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008486 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8487 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008488 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008489 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8490 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008491 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008492 f_logp(BSCVTY, "Got RSL RR Release");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008493 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008494 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008495 f_logp(BSCVTY, "Got RSL Deact SACCH");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008496 }
8497 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008498 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008499 /* Also drop the SCCP connection */
8500 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8501 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008502 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008503 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008504 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8505 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008506 }
8507 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008508 deactivate(ack_dlcx);
8509 deactivate(ack_rel_req);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008510}
8511
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01008512friend function f_perform_clear_no_rr_rel(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC)
8513runs on MSC_ConnHdlr {
8514 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8515 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
8516 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8517 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8518 interleave {
8519 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
8520 f_logp(BSCVTY, "Got RSL Deact SACCH");
8521 }
8522 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
8523 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8524 /* Also drop the SCCP connection */
8525 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8526 }
8527 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
8528 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
8529 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8530 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
8531 }
8532 }
8533 deactivate(ack_dlcx);
8534 deactivate(ack_rel_req);
8535}
8536
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01008537friend function f_perform_clear_no_lchan()
8538runs on MSC_ConnHdlr {
8539 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8540 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8541 BSSAP.receive(tr_BSSMAP_ClearComplete);
8542 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8543 /* Also drop the SCCP connection */
8544 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8545}
8546
Vadim Yanitskiy65d879d2022-06-23 18:15:39 +07008547friend function f_perform_clear_test_ct(DchanTuple dt)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008548 runs on test_CT
8549{
8550 /* Instruct BSC to clear channel */
8551 var BssmapCause cause := 0;
8552 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008553 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008554}
8555
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008556private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
8557 template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008558runs on MSC_ConnHdlr {
8559 timer T := 10.0;
8560 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
8561
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008562 f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008563 f_create_bssmap_exp(l3_enc);
8564
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008565 /* RSL_Emulation.f_chan_est() on rsl_pt:
8566 * This is basically code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008567 * RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
8568 */
8569 var RSL_Message rx_rsl;
8570 var GsmRrMessage rr;
8571
8572 /* request a channel to be established */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008573 rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008574 /* expect immediate assignment.
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008575 * Code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008576 * rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
8577 */
8578 timer Tt := 10.0;
8579
8580 /* request a channel to be established */
8581 Tt.start;
8582 alt {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008583 [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008584 Tt.stop;
8585 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008586 [] rsl_pt.receive {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008587 setverdict(fail, "Unexpected RSL message on DCHAN");
8588 mtc.stop;
8589 }
8590 [] Tt.timeout {
8591 setverdict(fail, "Timeout waiting for RSL on DCHAN");
8592 mtc.stop;
8593 }
8594 }
8595 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
8596 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008597 rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008598
8599
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008600 if (expect_bssmap_l3) {
8601 f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
8602 var template PDU_BSSAP exp_l3_compl;
8603 exp_l3_compl := tr_BSSMAP_ComplL3()
8604 if (g_pars.aoip == false) {
8605 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
8606 } else {
8607 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
8608 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008609
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008610 var PDU_BSSAP bssap;
8611 T.start;
8612 alt {
8613 [] BSSAP.receive(exp_l3_compl) -> value bssap {
8614 f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
8615 log("rx exp_l3_compl = ", bssap);
8616 }
8617 [] BSSAP.receive(tr_BSSMAP_ComplL3) {
8618 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
8619 }
8620 [] T.timeout {
8621 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
8622 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008623 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008624
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008625 /* start ciphering, if requested */
8626 if (ispresent(g_pars.encr)) {
8627 f_logp(BSCVTY, "start ciphering");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008628 f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008629 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008630 }
8631
8632 if (do_clear) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008633 f_perform_clear(rsl_pt, rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008634 }
8635 setverdict(pass);
8636 f_sleep(1.0);
8637}
8638
8639private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
8640 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8641 if (g_pars.mscpool.rsl_idx == 0) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008642 f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008643 } else if (g_pars.mscpool.rsl_idx == 1) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008644 f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008645 } else if (g_pars.mscpool.rsl_idx == 2) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008646 f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008647 }
8648}
8649
8650/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
8651private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
8652 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008653 f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
8654 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 +02008655 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)) );
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008656 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 +02008657}
8658testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
8659
8660 f_init(1, true);
8661 f_sleep(1.0);
8662 var MSC_ConnHdlr vc_conn;
8663 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008664
8665 f_ctrs_msc_init();
8666
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008667 vc_conn := f_start_handler(refers(f_tc_mscpool_L3Compl_on_1_msc), pars);
8668 vc_conn.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008669
8670 f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008671 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008672}
8673
8674/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
8675/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8676 * just as well using only RSL. */
8677testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
8678
8679 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8680 f_sleep(1.0);
8681
8682 /* Control which MSC gets chosen next by the round-robin, otherwise
8683 * would be randomly affected by which other tests ran before this. */
8684 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8685
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008686 f_ctrs_msc_init();
8687
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008688 var MSC_ConnHdlr vc_conn1;
8689 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8690 pars1.mscpool.rsl_idx := 0;
8691 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8692 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8693 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008694 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008695
8696 var MSC_ConnHdlr vc_conn2;
8697 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8698 pars2.mscpool.rsl_idx := 1;
8699 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8700 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8701 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008702 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008703
8704 /* Test round-robin wrap to the first MSC */
8705 var MSC_ConnHdlr vc_conn3;
8706 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8707 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008708 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008709 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8710 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008711 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008712 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008713}
8714
8715/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 0
8716 * (configured in osmo-bsc.cfg). */
8717/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8718 * just as well using only RSL. */
8719testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
8720
8721 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8722 f_sleep(1.0);
8723
8724 /* Control which MSC gets chosen next by the round-robin, otherwise
8725 * would be randomly affected by which other tests ran before this. */
8726 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8727
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008728 f_ctrs_msc_init();
8729
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008730 var MSC_ConnHdlr vc_conn1;
8731 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8732 pars1.mscpool.rsl_idx := 0;
8733 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8734 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8735 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008736 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008737
8738 var MSC_ConnHdlr vc_conn2;
8739 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8740 pars2.mscpool.rsl_idx := 1;
8741 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8742 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8743 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008744 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008745
8746 /* Test round-robin wrap to the first MSC */
8747 var MSC_ConnHdlr vc_conn3;
8748 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8749 pars3.mscpool.rsl_idx := 2;
8750 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8751 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8752 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008753 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008754 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008755}
8756
8757/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
8758 * (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
8759 * NULL-NRI setting is stronger than that. */
8760/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8761 * just as well using only RSL. */
8762testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
8763
8764 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8765 f_sleep(1.0);
8766
8767 /* Control which MSC gets chosen next by the round-robin, otherwise
8768 * would be randomly affected by which other tests ran before this. */
8769 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8770
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008771 f_ctrs_msc_init();
8772
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008773 var MSC_ConnHdlr vc_conn1;
8774 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8775 pars1.mscpool.rsl_idx := 0;
8776 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8777 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8778 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008779 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008780
8781 var MSC_ConnHdlr vc_conn2;
8782 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8783 pars2.mscpool.rsl_idx := 1;
8784 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8785 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8786 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008787 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008788
8789 /* Test round-robin wrap to the first MSC */
8790 var MSC_ConnHdlr vc_conn3;
8791 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8792 pars3.mscpool.rsl_idx := 2;
8793 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8794 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8795 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008796 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008797 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008798}
8799
8800/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
8801 * assigned to any MSC (configured in osmo-bsc.cfg). */
8802/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8803 * just as well using only RSL. */
8804testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test_CT {
8805
8806 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8807 f_sleep(1.0);
8808
8809 /* Control which MSC gets chosen next by the round-robin, otherwise
8810 * would be randomly affected by which other tests ran before this. */
8811 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8812
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008813 f_ctrs_msc_init();
8814
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008815 var MSC_ConnHdlr vc_conn1;
8816 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8817 pars1.mscpool.rsl_idx := 0;
8818 /* An NRI that is not assigned to any MSC */
8819 pars1.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(1023))));
8820 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8821 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008822 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008823
8824 var MSC_ConnHdlr vc_conn2;
8825 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8826 pars2.mscpool.rsl_idx := 1;
8827 /* An NRI that is not assigned to any MSC */
8828 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(768)), '00F110'O));
8829 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8830 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008831 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008832
8833 /* Test round-robin wrap to the first MSC */
8834 var MSC_ConnHdlr vc_conn3;
8835 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8836 pars3.mscpool.rsl_idx := 2;
8837 /* An NRI that is not assigned to any MSC */
8838 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, valueof(ts_MI_TMSI_NRI_LV(819))));
8839 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8840 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008841 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008842 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008843}
8844
8845/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
8846 * assigned to an MSC that is currently not connected (configured in osmo-bsc.cfg). */
8847/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8848 * just as well using only RSL. */
8849testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
8850
8851 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8852 f_sleep(1.0);
8853
8854 /* Control which MSC gets chosen next by the round-robin, otherwise
8855 * would be randomly affected by which other tests ran before this. */
8856 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8857
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008858 f_ctrs_msc_init();
8859
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008860 var MSC_ConnHdlr vc_conn1;
8861 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8862 pars1.mscpool.rsl_idx := 0;
8863 /* An NRI that is assigned to an unconnected MSC */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008864 pars1.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(512)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008865 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8866 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008867 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8868 f_ctrs_msc_add(0, "mscpool:subscr:new");
8869 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008870
8871 var MSC_ConnHdlr vc_conn2;
8872 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8873 pars2.mscpool.rsl_idx := 1;
8874 /* An NRI that is assigned to an unconnected MSC */
8875 pars2.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(767))));
8876 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8877 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008878 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8879 f_ctrs_msc_add(1, "mscpool:subscr:new");
8880 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008881
8882 /* Test round-robin wrap to the first MSC */
8883 var MSC_ConnHdlr vc_conn3;
8884 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8885 pars3.mscpool.rsl_idx := 2;
8886 /* An NRI that is assigned to an unconnected MSC */
8887 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(750)), '00F110'O));
8888 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8889 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008890 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8891 f_ctrs_msc_add(0, "mscpool:subscr:new");
8892 f_ctrs_msc_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008893 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008894}
8895
8896/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
8897 * osmo-bsc.cfg). */
8898/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8899 * just as well using only RSL. */
8900testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
8901
8902 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8903 f_sleep(1.0);
8904
8905 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
8906 * this is not using round-robin. */
8907 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8908
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008909 f_ctrs_msc_init();
8910
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008911 var MSC_ConnHdlr vc_conn1;
8912 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8913 pars1.mscpool.rsl_idx := 0;
8914 /* An NRI of the second MSC's range (256-511) */
8915 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(256))));
8916 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8917 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008918 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008919
8920 var MSC_ConnHdlr vc_conn2;
8921 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8922 pars2.mscpool.rsl_idx := 1;
8923 /* An NRI of the second MSC's range (256-511) */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008924 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(260)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008925 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8926 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008927 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008928
8929 var MSC_ConnHdlr vc_conn3;
8930 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8931 pars3.mscpool.rsl_idx := 2;
8932 /* An NRI of the second MSC's range (256-511) */
8933 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(511)), '00F110'O));
8934 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8935 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008936 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008937 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008938}
8939
8940/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
8941 * while a round-robin remains unaffected by that. */
8942/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8943 * just as well using only RSL. */
8944testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
8945
8946 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8947 f_sleep(1.0);
8948
8949 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
8950 * this is not using round-robin. */
8951 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8952
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008953 f_ctrs_msc_init();
8954
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008955 var MSC_ConnHdlr vc_conn1;
8956 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 2);
8957 pars1.mscpool.rsl_idx := 0;
8958 /* An NRI of the third MSC's range (512-767) */
8959 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(512))));
8960 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8961 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008962 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008963
8964 var MSC_ConnHdlr vc_conn2;
8965 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8966 pars2.mscpool.rsl_idx := 1;
8967 /* An NRI of the third MSC's range (512-767) */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008968 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(678)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008969 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8970 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008971 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008972
8973 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
8974 var MSC_ConnHdlr vc_conn3;
8975 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8976 pars3.mscpool.rsl_idx := 2;
8977 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000013'H)), '00F110'O));
8978 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8979 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008980 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008981 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008982}
8983
8984/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
8985/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8986 * just as well using only RSL. */
8987testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
8988
8989 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8990 f_sleep(1.0);
8991
8992 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
8993 * instead, and hits msc 0. */
8994 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8995
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008996 f_ctrs_msc_init();
8997
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008998 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-bsc.cfg */
8999 var MSC_ConnHdlr vc_conn1;
9000 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9001 pars1.mscpool.rsl_idx := 0;
9002 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(260)), '99F999'O));
9003 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9004 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009005 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009006
9007 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
9008 var MSC_ConnHdlr vc_conn2;
9009 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9010 pars2.mscpool.rsl_idx := 1;
9011 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(555)), '00F110'O));
9012 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9013 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009014 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009015 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009016}
9017
9018/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
9019 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9020private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
9021 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9022 //cid_list := { cIl_allInBSS := ''O };
9023 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9024 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9025 var BSSAP_N_UNITDATA_req paging;
9026 var hexstring imsi := '001010000000123'H;
9027
9028 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9029
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009030 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009031 valueof(ts_BSSMAP_Paging(imsi, cid_list, omit, bssmap_chneed))));
9032 BSSAP.send(paging);
9033
9034 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9035 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9036 * channel number is picked here. */
9037 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9038 f_rslem_register(0, new_chan_nr);
9039 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(imsi)));
9040 f_rslem_unregister(0, new_chan_nr);
9041
9042 /* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
9043 * causes this Paging Response to go to the first MSC (bssap_idx := 0). */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009044 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV(imsi)) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009045 f_sleep(1.0);
9046}
9047testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
9048 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9049 f_sleep(1.0);
9050
9051 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9052 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9053 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
9054
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009055 f_ctrs_msc_init();
9056
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009057 var MSC_ConnHdlr vc_conn1;
9058 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9059 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009060 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9061 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009062 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
9063 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009064 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009065 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009066}
9067
9068/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
9069 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9070private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
9071 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9072 //cid_list := { cIl_allInBSS := ''O };
9073 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9074 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9075 var integer nri_v := 300; /* <-- second MSC's NRI */
Harald Weltebf397612021-01-14 20:39:46 +01009076 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009077 var BSSAP_N_UNITDATA_req paging;
9078
9079 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9080
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009081 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009082 valueof(ts_BSSMAP_Paging('001010000000011'H, cid_list, tmsi, bssmap_chneed))));
9083 BSSAP.send(paging);
9084
9085 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9086 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9087 * channel number is picked here. */
9088 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9089 f_rslem_register(0, new_chan_nr);
9090 RSL.receive(tr_RSL_PAGING_CMD(t_MI_TMSI(tmsi)));
9091 f_rslem_unregister(0, new_chan_nr);
9092
9093 /* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
9094 * third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
9095 * the first MSC (bssap_idx := 0). */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009096 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_TMSI_NRI_LV(nri_v)) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009097 f_sleep(1.0);
9098}
9099testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
9100 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9101 f_sleep(1.0);
9102
9103 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9104 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9105 f_vty_transceive(BSCVTY, "mscpool roundrobin next 2");
9106
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009107 f_ctrs_msc_init();
9108
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009109 var MSC_ConnHdlr vc_conn1;
9110 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9111 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009112 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9113 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009114 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
9115 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009116 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009117 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009118}
9119
9120/* For round-robin, skip an MSC that has 'no allow-attach' set. */
9121/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
9122 * just as well using only RSL. */
9123testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
9124
9125 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9126 f_sleep(1.0);
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009127 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9128 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009129
9130 /* Control which MSC gets chosen next by the round-robin, otherwise
9131 * would be randomly affected by which other tests ran before this. */
9132 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9133
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009134 f_ctrs_msc_init();
9135
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009136 var MSC_ConnHdlr vc_conn1;
9137 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9138 pars1.mscpool.rsl_idx := 0;
9139 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9140 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9141 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009142 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009143
9144 var MSC_ConnHdlr vc_conn2;
9145 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9146 pars2.mscpool.rsl_idx := 1;
9147 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9148 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9149 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009150 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009151
9152 var MSC_ConnHdlr vc_conn3;
9153 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
9154 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009155 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009156 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9157 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009158 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009159 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009160}
9161
9162/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
9163 * TMSI NRI. */
9164testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
9165
9166 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9167 f_sleep(1.0);
9168
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009169 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9170 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
9171
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009172 /* Control which MSC gets chosen next by the round-robin, otherwise
9173 * would be randomly affected by which other tests ran before this. */
9174 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9175
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009176 f_ctrs_msc_init();
9177
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009178 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
9179 var MSC_ConnHdlr vc_conn1;
9180 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
9181 pars1.mscpool.rsl_idx := 0;
9182 /* An NRI of the second MSC's range (256-511) */
9183 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_TMSI_NRI_LV(260))));
9184 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9185 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009186 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009187
9188 var MSC_ConnHdlr vc_conn2;
9189 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9190 pars2.mscpool.rsl_idx := 1;
9191 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9192 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9193 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009194 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009195
9196 var MSC_ConnHdlr vc_conn3;
9197 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 2);
9198 pars3.mscpool.rsl_idx := 2;
9199 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000003'H))));
9200 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9201 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009202 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009203 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009204}
9205
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009206/* When an MSC point-code gets an SCCP N-PCSTATE saying it is unreachable, immediately mark the MSC as unusable. */
9207testcase TC_mscpool_sccp_n_pcstate_detaches_msc() runs on test_CT {
9208
9209 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
9210 f_sleep(1.0);
9211
9212 /* Control which MSC gets chosen next by the round-robin, otherwise
9213 * would be randomly affected by which other tests ran before this. */
9214 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9215
9216 f_ctrs_msc_init();
9217
9218 var MSC_ConnHdlr vc_conn1;
9219 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9220 pars1.mscpool.rsl_idx := 0;
9221 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9222 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9223 vc_conn1.done;
9224 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9225
9226 var MSC_ConnHdlr vc_conn2;
9227 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
9228 pars2.mscpool.rsl_idx := 1;
9229 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9230 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9231 vc_conn2.done;
9232 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9233
9234 f_logp(BSCVTY, "disconnecting msc0");
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009235 f_bssap_idx_disconnect(0);
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009236
9237 /* Now round-robin would wrap to the first MSC, but since the first MSC is disconnected, it wraps around to msc
9238 * 2 again. */
9239 var MSC_ConnHdlr vc_conn3;
9240 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
9241 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009242 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009243 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9244 vc_conn3.done;
9245 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9246 f_shutdown_helper();
9247}
9248
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009249/* When an MSC point-code gets an SCCP N-PCSTATE saying it is now reachable, immediately trigger RESET and bring up the
9250 * MSC. */
9251testcase TC_mscpool_sccp_n_pcstate_attaches_msc() runs on test_CT {
9252
9253 f_init(nr_bts := 3, handler_mode := true, nr_msc := 1);
9254 f_sleep(1.0);
9255
9256 /* Control which MSC gets chosen next by the round-robin, otherwise
9257 * would be randomly affected by which other tests ran before this. */
9258 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9259
9260 f_ctrs_msc_init();
9261
9262 /* There is only one MSC, round robin stays on msc0 */
9263 var MSC_ConnHdlr vc_conn1;
9264 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9265 pars1.mscpool.rsl_idx := 0;
9266 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('0010100230000001'H)), '00F110'O));
9267 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9268 vc_conn1.done;
9269 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9270
9271 var MSC_ConnHdlr vc_conn2;
9272 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9273 pars2.mscpool.rsl_idx := 1;
9274 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010023000002'H))));
9275 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9276 vc_conn2.done;
9277 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9278
9279 f_logp(BSCVTY, "connecting msc1");
9280 f_vty_msc_allow_attach(BSCVTY, { true, true });
9281 f_bssap_idx_init(1);
9282 f_sleep(1.0);
9283
9284 /* This time round-robin wraps to the second MSC, because it is now online. */
9285 var MSC_ConnHdlr vc_conn4;
9286 var TestHdlrParams pars4 := f_gen_test_hdlr_pars(bssap_idx := 1);
9287 pars4.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009288 pars4.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010023000003'H)));
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009289 vc_conn4 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars4);
9290 vc_conn4.done;
9291 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9292
9293 f_shutdown_helper();
9294}
9295
Philipp Maier783681c2020-07-16 16:47:06 +02009296/* Allow/Deny emergency calls globally via VTY */
9297private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
9298 f_vty_enter_cfg_msc(BSCVTY, 0);
9299 if (allow) {
9300 f_vty_transceive(BSCVTY, "allow-emergency allow");
9301 } else {
9302 f_vty_transceive(BSCVTY, "allow-emergency deny");
9303 }
9304 f_vty_transceive(BSCVTY, "exit");
9305 f_vty_transceive(BSCVTY, "exit");
9306}
9307
9308/* Allow/Deny emergency calls per BTS via VTY */
9309private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
9310 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9311 if (allow) {
9312 f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
9313 } else {
9314 f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
9315 }
9316 f_vty_transceive(BSCVTY, "exit");
9317 f_vty_transceive(BSCVTY, "exit");
Neels Hofmeyrb6ed80c2020-10-12 22:52:39 +00009318 f_vty_transceive(BSCVTY, "exit");
Philipp Maier783681c2020-07-16 16:47:06 +02009319}
9320
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02009321/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
9322private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
9323 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9324 if (allow) {
9325 f_vty_transceive(BSCVTY, "srvcc fast-return allow");
9326 } else {
9327 f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
9328 }
9329 f_vty_transceive(BSCVTY, "exit");
9330 f_vty_transceive(BSCVTY, "exit");
9331 f_vty_transceive(BSCVTY, "exit");
9332}
9333
Pau Espin Pedrol14475352021-07-22 15:48:16 +02009334/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
9335private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
9336 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9337 if (allow) {
9338 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
9339 } else {
9340 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
9341 }
9342 f_vty_transceive(BSCVTY, "exit");
9343 f_vty_transceive(BSCVTY, "exit");
9344 f_vty_transceive(BSCVTY, "exit");
9345}
9346
Pau Espin Pedrol35609792023-01-03 16:56:59 +01009347/* Begin assignment procedure and send an EMERGENCY SETUP (RR) */
Philipp Maier783681c2020-07-16 16:47:06 +02009348private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
9349 var PDU_ML3_MS_NW emerg_setup;
9350 var octetstring emerg_setup_enc;
9351 var RSL_Message emerg_setup_data_ind;
9352
9353 f_establish_fully(omit, omit);
9354
9355 emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
9356 emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
9357 emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
9358
9359 RSL.send(emerg_setup_data_ind);
9360}
9361
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009362/* expect EmergencySetup on BSSAP after calling f_assignment_emerg_setup() */
9363private function f_assignment_emerg_setup_exp_bssap()
9364runs on MSC_ConnHdlr {
Philipp Maier783681c2020-07-16 16:47:06 +02009365 var PDU_BSSAP emerg_setup_data_ind_bssap;
9366 var PDU_ML3_MS_NW emerg_setup;
9367 timer T := 3.0;
9368
Philipp Maier783681c2020-07-16 16:47:06 +02009369 T.start;
9370 alt {
9371 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
9372 emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
9373 if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
9374 setverdict(fail, "no emergency setup");
9375 }
9376 }
9377 [] BSSAP.receive {
9378 setverdict(fail, "unexpected BSSAP message!");
9379 }
9380 [] T.timeout {
9381 setverdict(fail, "timout waiting for EMERGENCY SETUP!");
9382 }
9383 }
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009384}
9385
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009386private function f_assignment_emerg_setup_voice()
9387runs on MSC_ConnHdlr {
9388 /* Go on with voice call assignment */
9389 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
9390 var PDU_BSSAP ass_cmd := f_gen_ass_req();
9391
9392 /* Below speechOrDataIndicator and codecList are copied from an emergency call captured during tests.
9393 * They seem a bit weird (AMR-WB, and the order differ between speechId_DataIndicator and the codecList), but
9394 * seems a good idea to see how osmo-bsc reacts to this. */
9395 ass_cmd.pdu.bssmap.assignmentRequest.channelType := {
9396 elementIdentifier := '0B'O, /* overwritten */
9397 lengthIndicator := 0, /* overwritten */
9398 speechOrDataIndicator := '0001'B, /* speech */
9399 spare1_4 := '0000'B,
9400 channelRateAndType := ChRate_TCHForH_Fpref,
9401 speechId_DataIndicator := 'c2918105'O
9402 };
9403 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({
9404 ts_CodecHR, ts_CodecAMR_WB, ts_CodecEFR, ts_CodecFR}));
9405
9406 f_rslem_dchan_queue_enable();
9407
9408 var ExpectCriteria mgcpcrit := {
9409 connid := omit,
9410 endpoint := omit,
9411 transid := omit
9412 };
9413 f_create_mgcp_expect(mgcpcrit);
9414
9415 BSSAP.send(ass_cmd);
9416
9417 var AssignmentState st := valueof(ts_AssignmentStateInit);
Oliver Smithce2dd692023-04-17 10:25:50 +02009418 st.rtp_stream := true;
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009419 st.is_assignment := false;
9420 alt {
9421 [] as_modify(st);
9422 [] as_Media();
9423 [st.modify_done] BSSAP.receive(exp_compl) {
9424 setverdict(pass);
9425 }
9426 }
9427
9428 /* Voice call carries on ... */
9429 f_sleep(2.0);
9430}
9431
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009432/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
9433 * CALLS are permitted by the BSC config. */
9434private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
9435
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009436 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
9437 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
9438 * another lchan. */
9439 g_pars.ra := f_rnd_ra_emerg();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009440 f_assignment_emerg_setup();
9441 f_assignment_emerg_setup_exp_bssap();
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009442 f_assignment_emerg_setup_voice();
Philipp Maier783681c2020-07-16 16:47:06 +02009443
9444 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009445 f_perform_clear();
Philipp Maier783681c2020-07-16 16:47:06 +02009446}
9447
9448/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
9449 * forbidden by the BSC config. */
9450private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
9451 var PDU_BSSAP emerg_setup_data_ind_bssap;
9452 timer T := 3.0;
9453
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009454 f_assignment_emerg_setup();
Philipp Maier783681c2020-07-16 16:47:06 +02009455
9456 T.start;
9457 alt {
9458 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
9459 setverdict(pass);
9460 }
9461 [] RSL.receive {
9462 setverdict(fail, "unexpected RSL message!");
9463 }
9464 [] T.timeout {
9465 setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
9466 }
9467 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009468 BSSAP.receive(tr_BSSMAP_ClearRequest);
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01009469 f_perform_clear_no_rr_rel();
Philipp Maier783681c2020-07-16 16:47:06 +02009470}
9471
9472/* EMERGENCY CALL situation #1, allowed globally and by BTS */
9473testcase TC_assignment_emerg_setup_allow() runs on test_CT {
9474 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9475 var MSC_ConnHdlr vc_conn;
9476
9477 f_init(1, true);
9478 f_sleep(1.0);
9479
9480 f_vty_allow_emerg_msc(true);
9481 f_vty_allow_emerg_bts(true, 0);
9482 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9483 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009484 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009485}
9486
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +01009487/* Test MO emergency call using MobileIdentity=IMEI (possible for emergency
9488 * calls from phones without SIM card).
9489 * 3GPP TS 24.008 section 10.5.1.4, OS#5849 */
9490testcase TC_assignment_emerg_setup_allow_imei() runs on test_CT {
9491 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9492 var MSC_ConnHdlr vc_conn;
9493
9494 /* Remove IMSI set by f_gen_test_hdlr_pars(), then IMEI will be used to place the call */
9495 pars.imsi := omit;
9496
9497 f_init(1, true);
9498 f_sleep(1.0);
9499
9500 f_vty_allow_emerg_msc(true);
9501 f_vty_allow_emerg_bts(true, 0);
9502 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9503 vc_conn.done;
9504 f_shutdown_helper();
9505}
9506
Philipp Maier783681c2020-07-16 16:47:06 +02009507/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
9508testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
9509 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9510 var MSC_ConnHdlr vc_conn;
9511
9512 f_init(1, true);
9513 f_sleep(1.0);
9514
9515 f_vty_allow_emerg_msc(false);
9516 f_vty_allow_emerg_bts(true, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009517 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx): */
9518 pars.ra := f_rnd_ra_emerg();
Philipp Maier783681c2020-07-16 16:47:06 +02009519 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9520 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009521 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009522}
9523
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009524/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS.
9525 * The RACH req (and hence CHAN RQD) indicate other than emergency call.
9526 * Hence BSC only learns about it being an emergency call later during call setup.
9527 * If interested in the ra="emergency call" + deny bts policy case,
9528 * see TC_chan_rqd_emerg_deny.
9529 */
Philipp Maier783681c2020-07-16 16:47:06 +02009530testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
9531 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9532 var MSC_ConnHdlr vc_conn;
9533
9534 /* Note: This simulates a spec violation by the MS, correct MS
9535 * implementations would not try to establish an emergency call because
9536 * the system information tells in advance that emergency calls are
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009537 * not allowed */
Philipp Maier783681c2020-07-16 16:47:06 +02009538
9539 f_init(1, true);
9540 f_sleep(1.0);
9541
9542 f_vty_allow_emerg_msc(true);
9543 f_vty_allow_emerg_bts(false, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009544 /* Note: Here we implicitly leave default g_pars.ra which is different than "emergency call" */
Philipp Maier783681c2020-07-16 16:47:06 +02009545 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9546 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009547 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009548}
9549
Philipp Maier82812002020-08-13 18:48:27 +02009550/* Test what happens when an emergency call arrives while all TCH channels are
9551 * busy, the BSC is expected to terminate one call in favor of the incoming
9552 * emergency call */
9553testcase TC_emerg_premption() runs on test_CT {
9554 var ASP_RSL_Unitdata rsl_ud;
9555 var integer i;
9556 var integer chreq_total, chreq_nochan;
9557 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009558 var octetstring l3_payload := gen_l3_valid_payload();
Philipp Maier82812002020-08-13 18:48:27 +02009559
9560 f_init(1);
9561 f_sleep(1.0);
9562
9563 f_vty_allow_emerg_msc(true);
9564 f_vty_allow_emerg_bts(true, 0);
9565
9566 /* Fill up all channels on the BTS */
9567 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
9568 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
9569 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 +02009570 f_chreq_act_ack('33'O, i);
Philipp Maier82812002020-08-13 18:48:27 +02009571 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009572 IPA_RSL[0][0].clear;
Philipp Maier82812002020-08-13 18:48:27 +02009573 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
9574 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
9575
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009576 /* Send EST IND for the first TCH, so we get to test the RR release cause */
9577 var RslChannelNr first_tch := valueof(t_RslChanNr_Bm(1));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009578 f_ipa_tx(ts_RSL_EST_IND(first_tch, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009579
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009580 /* Accept BSSAP conn, so we get to test the Clear Request cause */
9581 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009582 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009583 var integer sccp_conn_id := rx_c_ind.connectionId;
9584 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
9585
Philipp Maier82812002020-08-13 18:48:27 +02009586 /* Send Channel request for emegergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009587 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier82812002020-08-13 18:48:27 +02009588
9589 /* Expect the BSC to release one (the first) TCH/F on the BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009590 f_expect_chan_rel(first_tch, expect_rr_chan_rel := true, expect_rll_rel_req := false,
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009591 expect_rr_cause := GSM48_RR_CAUSE_PREMPTIVE_REL);
Philipp Maier82812002020-08-13 18:48:27 +02009592
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009593 /* Also expect a BSSMAP Clear Request with PREEMPTION */
9594 var BSSAP_N_DATA_ind rx_clear_req;
9595 const myBSSMAP_Cause preemption := GSM0808_CAUSE_PREEMPTION;
9596 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_clear_req;
9597 log("XXX ", rx_clear_req);
9598 if (rx_clear_req.userData.pdu.bssmap.clearRequest.cause.causeValue != int2bit(enum2int(preemption), 7)) {
9599 setverdict(fail, "BSSMAP Clear Request: expected cause PREEMPTION");
9600 }
9601
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009602 /* Expect the BSC to send activate/assign the channel for the emergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009603 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009604 if (first_tch != rx_rsl.ies[0].body.chan_nr) {
9605 setverdict(fail, "different TCH lchan activated than expected");
9606 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009607 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(first_tch, 33));
9608 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Philipp Maier104f4c02020-09-11 18:12:18 +02009609
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009610 /* complete the BSSMAP Clear to satisfy the conn leak check */
9611 BSSAP.send(ts_BSSAP_DATA_req(sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(preemption))));
9612 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearComplete)) {
9613 BSSAP.send(ts_BSSAP_DISC_req(sccp_conn_id, 0));
9614 }
9615
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009616 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009617}
9618
9619/* Hopping parameters per a timeslot */
Vadim Yanitskiybc6654a2020-09-13 01:27:40 +07009620private type record length(0..64) of GsmArfcn ArfcnList;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009621private type record FHParamsTs {
9622 boolean enabled,
9623 uint6_t hsn,
9624 uint6_t maio,
9625 ArfcnList ma
9626};
9627
9628/* Hopping parameters per a transceiver */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009629private type record FHParamsTrx {
Philipp Maier798d8952021-10-19 14:43:19 +02009630 GsmBandArfcn arfcn,
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009631 FHParamsTs ts[8]
9632};
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009633
9634/* Randomly generate the hopping parameters for the given timeslot numbers */
9635private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
9636runs on test_CT return FHParamsTrx {
9637 var FHParamsTrx fhp;
9638
Philipp Maier798d8952021-10-19 14:43:19 +02009639 /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
9640 * fall in the GSM900 band. */
9641 fhp.arfcn.arfcn := f_rnd_int(3);
9642 fhp.arfcn.pcs := false;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009643
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009644 for (var integer tn := 0; tn < 8; tn := tn + 1) {
9645 if (not match(tn, tr_tn)) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009646 fhp.ts[tn].enabled := false;
9647 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009648 continue;
9649 }
9650
9651 /* Random HSN / MAIO values: 0..63 */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009652 fhp.ts[tn].hsn := f_rnd_int(64);
9653 fhp.ts[tn].maio := f_rnd_int(64);
9654 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009655
9656 /* Random Mobile Allocation (hopping channels) */
9657 var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
9658 var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
9659 for (var integer i := 1; i <= ma_len; i := i + 1) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009660 fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009661 }
9662
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009663 fhp.ts[tn].enabled := true;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009664 }
9665
9666 log("f_TC_fh_params_gen(): ", fhp);
9667 return fhp;
9668}
9669
9670/* Make sure that the given Channel Description IE matches the hopping configuration */
9671private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
9672{
9673 var template (present) ChannelDescription tr_cd;
9674 var template (present) MaioHsn tr_maio_hsn;
9675 var uint3_t tn := cd.chan_nr.tn;
9676
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009677 if (fhp.ts[tn].enabled) {
9678 tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009679 tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
9680 } else {
Philipp Maier798d8952021-10-19 14:43:19 +02009681 tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009682 }
9683
9684 if (not match(cd, tr_cd)) {
9685 setverdict(fail, "Channel Description IE does not match: ",
9686 cd, " vs expected ", tr_cd);
9687 }
9688}
9689
9690/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
9691private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
9692 in MobileAllocationLV ma)
9693{
9694 var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
9695
9696 if (not match(ma, tr_ma)) {
9697 setverdict(fail, "Mobile Allocation IE does not match (tn := ",
9698 tn, "): ", ma, " vs expected: ", tr_ma);
9699 } else {
9700 setverdict(pass);
9701 }
9702}
9703
9704private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
9705 in MobileAllocationLV ma)
9706return template MobileAllocationLV {
9707 /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009708 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009709 return { len := 0, ma := ''B };
9710 }
9711
9712 var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
9713 var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
9714 var bitstring ma_mask := ''B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009715
9716 /* Compose the full bit-mask (all channels, up to 1024 entries) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009717 for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
9718 for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
9719 if (full_mask[fhp.ts[i].ma[j]] == '1'B)
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009720 { continue; }
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009721 full_mask[fhp.ts[i].ma[j]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009722 }
9723 }
9724
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009725 /* Take ARFCN of the TRX itself into account */
Philipp Maier798d8952021-10-19 14:43:19 +02009726 full_mask[fhp.arfcn.arfcn] := '1'B;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009727
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009728 /* Compose a bit-mask for the given timeslot number */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009729 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9730 slot_mask[fhp.ts[tn].ma[i]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009731 }
9732
9733 /* Finally, compose the Mobile Allocation bit-mask */
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009734 for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009735 if (full_mask[i] != '1'B)
9736 { continue; }
9737
9738 /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
9739 if (slot_mask[i] == '1'B) {
9740 ma_mask := ma_mask & '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009741 } else {
9742 ma_mask := ma_mask & '0'B;
9743 }
9744 }
9745
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009746 /* ARFCN 0 (if present) goes to the last position of the bit-mask */
9747 if (full_mask[0] == '1'B) {
9748 /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
9749 if (slot_mask[0] == '1'B) {
9750 ma_mask := ma_mask & '1'B;
9751 } else {
9752 ma_mask := ma_mask & '0'B;
9753 }
9754 }
9755
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009756 /* Ensure that ma_mask is octet-aligned */
Vadim Yanitskiy2aa02522020-09-06 14:05:23 +07009757 var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009758 ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
9759
9760 return { len := ma_mask_len, ma := ma_mask };
9761}
9762
Philipp Maier798d8952021-10-19 14:43:19 +02009763/* Configure the appropriate band for a given arfcn, exc */
9764private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
9765{
9766 var charstring band;
9767 var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
9768
9769 select (arfcn_) {
9770 case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
9771 case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
9772 case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
9773 case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
9774 case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
9775 case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
9776 case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
9777 case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
9778 case else { return; }
9779 }
9780
9781 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9782 f_vty_transceive(BSCVTY, "band " & band);
9783 f_vty_transceive(BSCVTY, "end");
9784}
9785
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009786/* Configure the hopping parameters in accordance with the given record */
9787private function f_TC_fh_params_set(in FHParamsTrx fhp,
9788 uint8_t bts_nr := 0,
9789 uint8_t trx_nr := 0)
9790runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009791
9792 f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
9793
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009794 /* Enter the configuration node for the given BTS/TRX numbers */
9795 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9796
Philipp Maier798d8952021-10-19 14:43:19 +02009797 f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009798
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009799 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009800 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9801
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009802 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009803 f_vty_transceive(BSCVTY, "hopping enabled 0");
9804 f_vty_transceive(BSCVTY, "exit"); /* go back */
9805 continue;
9806 }
9807
9808 /* Configure HSN / MAIO values */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009809 f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
9810 f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009811
9812 /* Configure the Mobile Allocation (hopping channels) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009813 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9814 f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009815 }
9816
9817 f_vty_transceive(BSCVTY, "hopping enabled 1");
9818 f_vty_transceive(BSCVTY, "exit"); /* go back */
9819 }
9820
9821 f_vty_transceive(BSCVTY, "end");
9822}
9823
9824/* Disable frequency hopping on all timeslots */
9825private function f_TC_fh_params_unset(in FHParamsTrx fhp,
9826 uint8_t bts_nr := 0,
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009827 uint8_t trx_nr := 0,
Philipp Maier798d8952021-10-19 14:43:19 +02009828 GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009829runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009830
9831 f_TC_set_band_by_arfcn(bts_nr, arfcn);
9832
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009833 /* Enter the configuration node for the given BTS/TRX numbers */
9834 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9835
Philipp Maier798d8952021-10-19 14:43:19 +02009836 f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009837
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009838 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009839 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9840
9841 /* Delete all ARFCNs from the Mobile Allocation (if any) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009842 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9843 f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009844 }
9845
9846 f_vty_transceive(BSCVTY, "hopping enabled 0");
9847 f_vty_transceive(BSCVTY, "exit"); /* go back */
9848 }
9849
9850 f_vty_transceive(BSCVTY, "end");
9851 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9852}
9853
9854/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
9855 * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
9856testcase TC_fh_params_chan_activ() runs on test_CT {
9857 var FHParamsTrx fhp := f_TC_fh_params_gen();
9858 var RSL_Message rsl_msg;
9859 var RSL_IE_Body ie;
9860
9861 f_init_vty();
9862
9863 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9864 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9865
9866 f_init(1);
9867
9868 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9869 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009870 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9871 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009872
9873 /* Make sure that Channel Identification IE is present */
9874 if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
9875 setverdict(fail, "RSL Channel Identification IE is absent");
9876 continue;
9877 }
9878
9879 /* Make sure that hopping parameters (HSN/MAIO) match */
9880 f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
9881
9882 /* "Mobile Allocation shall be included but empty" - let's check this */
9883 if (ie.chan_ident.ma.v.len != 0) {
9884 setverdict(fail, "Mobile Allocation IE is not empty: ",
9885 ie.chan_ident.ma, ", despite it shall be");
9886 continue;
9887 }
9888 }
9889
9890 /* Disable frequency hopping */
9891 f_TC_fh_params_unset(fhp);
9892
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009893 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009894}
9895
9896/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
9897testcase TC_fh_params_imm_ass() runs on test_CT {
9898 var FHParamsTrx fhp := f_TC_fh_params_gen();
9899 var RSL_Message rsl_msg;
9900 var RSL_IE_Body ie;
9901
9902 f_init_vty();
9903
9904 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9905 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9906
9907 f_init(1);
9908
9909 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9910 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009911 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9912 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009913
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009914 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9915 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009916
9917 /* Make sure that Full Immediate Assign Info IE is present */
9918 if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
9919 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
9920 continue;
9921 }
9922
9923 /* Decode the actual Immediate Assignment message */
9924 var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
9925 if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
9926 setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
9927 continue;
9928 }
9929
9930 /* Make sure that hopping parameters (HSN/MAIO) match */
9931 f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
9932
9933 /* Make sure that the Mobile Allocation IE matches */
9934 f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
9935 rr_msg.payload.imm_ass.mobile_allocation);
9936 }
9937
9938 /* Disable frequency hopping */
9939 f_TC_fh_params_unset(fhp);
Philipp Maier82812002020-08-13 18:48:27 +02009940
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009941 f_shutdown_helper();
Philipp Maier82812002020-08-13 18:48:27 +02009942}
9943
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009944/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
9945testcase TC_fh_params_assignment_cmd() runs on test_CT {
9946 var FHParamsTrx fhp := f_TC_fh_params_gen();
9947 var RSL_Message rsl_msg;
9948 var RSL_IE_Body ie;
9949
9950 f_init_vty();
9951
9952 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9953 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9954
9955 f_init(1);
9956
9957 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02009958 vc_MGCP[0].stop;
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009959
9960 var template PDU_BSSAP ass_cmd := f_gen_ass_req();
9961 ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
9962
9963 /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
9964 * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
9965 for (var integer i := 0; i < 3; i := i + 1) {
9966 /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009967 var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009968
9969 /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
9970 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009971 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009972
9973 /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009974 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9975 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009976
9977 /* Make sure that L3 Information IE is present */
9978 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9979 setverdict(fail, "RSL L3 Information IE is absent");
9980 continue;
9981 }
9982
9983 /* Decode the L3 message and make sure it is (RR) Assignment Command */
9984 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9985 if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
9986 setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
9987 continue;
9988 }
9989
9990 /* Make sure that hopping parameters (HSN/MAIO) match */
9991 var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
9992 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9993
9994 /* Make sure that Cell Channel Description IE is present if FH is enabled */
9995 if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
Vadim Yanitskiy38d069d2020-09-02 17:18:57 +07009996 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009997 continue;
9998 }
9999
10000 /* Make sure that the Mobile Allocation IE matches (if present) */
10001 var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
10002 if (chan_desc.h and ma_present) {
10003 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10004 l3_msg.payload.ass_cmd.mobile_allocation.v);
10005 } else if (chan_desc.h and not ma_present) {
10006 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10007 continue;
10008 } else if (not chan_desc.h and ma_present) {
10009 setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
10010 continue;
10011 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010012
10013 f_perform_clear_test_ct(dt);
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010014 }
10015
10016 /* Give the IUT some time to release all channels */
10017 f_sleep(3.0);
10018
10019 /* Disable frequency hopping */
10020 f_TC_fh_params_unset(fhp);
10021
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010022 f_shutdown_helper();
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010023}
10024
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010025/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
10026private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
10027runs on test_CT {
10028 var RSL_Message rsl_msg;
10029 var RSL_IE_Body ie;
10030 var DchanTuple dt;
10031
10032 /* Establish a dedicated channel, so we can trigger handover */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010010033 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyc18ff472021-11-18 20:15:37 +030010034 f_sleep(0.5);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010035
10036 /* Trigger handover from BTS0 to BTS1 */
10037 f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
10038 f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
10039
10040 /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010041 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx := {1, 0});
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010042
10043 /* ACKnowledge channel activation and expect (RR) Handover Command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010044 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33), idx := {1, 0});
10045 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010046
10047 /* Make sure that L3 Information IE is present */
10048 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
10049 setverdict(fail, "RSL L3 Information IE is absent");
10050 return;
10051 }
10052
10053 /* Decode the L3 message and make sure it is (RR) Handover Command */
10054 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
10055 if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
10056 setverdict(fail, "Failed to match Handover Command: ", l3_msg);
10057 return;
10058 }
10059
10060 /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
10061 var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
10062 if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
10063 setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
10064 return;
10065 }
10066
10067 /* Make sure that hopping parameters (HSN/MAIO) match */
10068 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10069
10070 /* Make sure that Cell Channel Description IE is present */
10071 if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
10072 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
10073 return;
10074 }
10075
10076 /* Make sure that the Mobile Allocation (after time) IE is present and matches */
10077 var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
10078 if (ma_present) {
10079 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10080 l3_msg.payload.ho_cmd.mobile_allocation.v);
10081 } else {
10082 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10083 return;
10084 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010085
10086 f_perform_clear_test_ct(dt);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010087}
10088testcase TC_fh_params_handover_cmd() runs on test_CT {
10089 var FHParamsTrx fhp := f_TC_fh_params_gen();
10090
10091 f_init_vty();
10092
10093 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
10094 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
10095
10096 f_vty_transceive(BSCVTY, "timeslot 0");
10097 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10098 f_vty_transceive(BSCVTY, "exit"); /* go back */
10099
10100 f_vty_transceive(BSCVTY, "timeslot 1");
10101 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
10102 f_vty_transceive(BSCVTY, "end"); /* we're done */
10103
10104 f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
10105 f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
10106
10107 f_init(2);
10108
10109 f_TC_fh_params_handover_cmd(fhp);
10110
10111 /* Disable frequency hopping on BTS1 */
10112 f_TC_fh_params_unset(fhp, 1);
10113
10114 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
10115 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
10116
10117 f_vty_transceive(BSCVTY, "timeslot 0");
10118 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
10119 f_vty_transceive(BSCVTY, "exit"); /* go back */
10120
10121 f_vty_transceive(BSCVTY, "timeslot 1");
10122 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10123 f_vty_transceive(BSCVTY, "end"); /* we're done */
10124
10125 f_shutdown_helper();
10126}
10127
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010128/* Verify the hopping parameters in System Information Type 4 */
10129testcase TC_fh_params_si4_cbch() runs on test_CT {
10130 var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
10131 var ASP_RSL_Unitdata rx_rsl_ud;
10132 timer T := 5.0;
10133
10134 f_init_vty();
10135
10136 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
10137 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10138
10139 f_vty_transceive(BSCVTY, "timeslot 0");
10140 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10141 f_vty_transceive(BSCVTY, "exit"); /* go back */
10142
10143 f_vty_transceive(BSCVTY, "timeslot 1");
10144 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
10145 f_vty_transceive(BSCVTY, "end"); /* we're done */
10146
10147 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
10148 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10149
10150 f_init(1);
10151
10152 T.start;
10153 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010154 [] 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 +070010155 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
10156 var SystemInformation si := dec_SystemInformation(ie.other.payload);
10157
10158 /* Make sure that what we decoded is System Information Type 4 */
10159 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
10160 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
10161 repeat;
10162 }
10163
10164 /* Make sure that CBCH Channel Description IE is present */
10165 if (not ispresent(si.payload.si4.cbch_chan_desc)) {
10166 setverdict(fail, "CBCH Channel Description IE is absent");
10167 break;
10168 }
10169
10170 /* Finally, check the hopping parameters (HSN, MAIO) */
10171 var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
10172 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10173
10174 /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
10175 * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
10176 if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
10177 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10178 break;
10179 } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
10180 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10181 si.payload.si4.cbch_mobile_alloc.v);
10182 }
10183 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010184 [] IPA_RSL[0][0].receive { repeat; }
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010185 [] T.timeout {
10186 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
10187 }
10188 }
10189
10190 /* Disable frequency hopping */
10191 f_TC_fh_params_unset(fhp);
10192
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010193 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010194 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10195
10196 f_vty_transceive(BSCVTY, "timeslot 0");
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010197 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010198 f_vty_transceive(BSCVTY, "exit"); /* go back */
10199
10200 f_vty_transceive(BSCVTY, "timeslot 1");
10201 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10202 f_vty_transceive(BSCVTY, "end"); /* we're done */
10203
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010204 f_shutdown_helper();
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010205}
10206
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010207template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
10208 := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
10209
10210private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
10211 template (present) BSSLAP_PDU expect_bsslap)
10212{
10213 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
10214 if (not match(bsslap, expect_bsslap)) {
10215 log("EXPECTING BSSLAP: ", expect_bsslap);
10216 log("GOT BSSLAP: ", bsslap);
10217 setverdict(fail, "BSSLAP is not as expected");
10218 mtc.stop;
10219 }
10220 setverdict(pass);
10221}
10222
10223/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
10224const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
10225
10226private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
10227 var PDU_BSSAP_LE rx_bsslap;
10228 BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
10229 f_match_bsslap(rx_bsslap, expect_rx_bsslap);
10230}
10231
10232/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10233 * Request on Lb interface. Either with or without the SMLC doing a BSSLAP TA Request. */
10234private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
10235 f_sleep(1.0);
10236
10237 f_establish_fully(omit, omit);
10238 f_bssap_le_register_imsi(g_pars.imsi, omit);
10239
10240 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10241 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10242
10243 var PDU_BSSAP_LE plr;
10244 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10245
10246 if (not do_ta_request) {
10247 /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
10248 var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
10249 if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
10250 log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
10251 log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
10252 setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
10253 mtc.stop;
10254 }
10255 var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
10256 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
10257 if (not match(bsslap, expect_ta_layer3)) {
10258 log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
10259 log("GOT BSSLAP: ", bsslap);
10260 setverdict(fail, "BSSLAP is not as expected");
10261 mtc.stop;
10262 }
10263 /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
10264 * has no need to request the TA from the BSC and directly responds. */
10265 } else {
10266 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10267 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10268 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10269 }
10270
10271 /* SMLC got the TA from the BSC, now responds with geo information data. */
10272 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10273 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10274 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10275
10276 /* The LCS was using an active A-interface conn. It should still remain active after this. */
10277 f_mo_l3_transceive();
10278
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010279 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010280
10281 f_sleep(2.0);
10282 setverdict(pass);
10283}
10284
10285/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10286 * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
10287private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
10288 f_lcs_loc_req_for_active_ms(false);
10289}
10290testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
10291 var MSC_ConnHdlr vc_conn;
10292 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10293
10294 f_init(1, true);
10295 f_sleep(1.0);
10296 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
10297 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010298 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010299}
10300
10301/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10302 * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
10303private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
10304 f_lcs_loc_req_for_active_ms(true);
10305}
10306testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
10307 var MSC_ConnHdlr vc_conn;
10308 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10309
10310 f_init(1, true);
10311 f_sleep(1.0);
10312 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
10313 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010314 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010315}
10316
10317/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
10318 * conn without an active lchan. */
10319private function f_clear_A_conn() runs on MSC_ConnHdlr
10320{
10321 var BssmapCause cause := 0;
10322 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10323 BSSAP.receive(tr_BSSMAP_ClearComplete);
10324 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10325
10326 timer no_more_bssap := 5.0;
10327 no_more_bssap.start;
10328 alt {
10329 [] no_more_bssap.timeout { break; }
10330 [] BSSAP.receive(tr_BSSAP_BSSMAP) {
10331 setverdict(fail, "Expected no more BSSAP after Clear Complete");
10332 mtc.stop;
10333 }
10334 }
10335 setverdict(pass);
10336}
10337
10338/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
10339 * for LCS, for cases where there is only an A conn without an active lchan. */
10340private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
10341{
10342 f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
10343
10344 /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
10345 * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
10346 * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
10347 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10348 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10349 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10350
10351 /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
10352 f_clear_A_conn();
10353 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10354 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10355}
10356
10357/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10358 * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
10359 */
10360private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
10361 f_sleep(1.0);
10362
10363 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10364 f_bssap_le_register_imsi(g_pars.imsi, omit);
10365
10366 /* Register to receive the Paging Command */
10367 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10368 g_chan_nr := new_chan_nr;
10369 f_rslem_register(0, g_chan_nr);
10370
10371 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10372 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10373 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10374 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10375
10376 var PDU_BSSAP_LE plr;
10377 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10378
10379 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10380 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10381
10382 /* OsmoBSC needs to Page */
10383 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
10384 f_logp(BSCVTY, "got Paging Command");
10385
10386 /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
10387 * the MSC, and releases the lchan directly. */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +020010388 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 +020010389 f_expect_lchan_rel(RSL, RSL_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010390
10391 /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
10392
10393 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10394
10395 /* SMLC got the TA from the BSC, now responds with geo information data. */
10396 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10397 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10398
10399 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10400
10401 /* The lchan is gone, the A-interface conn was created for the LCS only.
10402 * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
10403 f_verify_active_A_conn_and_clear();
10404
10405 f_sleep(2.0);
10406 setverdict(pass);
10407}
10408testcase TC_lcs_loc_req_for_idle_ms() runs on test_CT {
10409 var MSC_ConnHdlr vc_conn;
10410 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10411
10412 f_init(1, true);
10413 f_sleep(1.0);
10414
10415 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10416 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10417
10418 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
10419 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010420 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010421}
10422
10423/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
10424 */
10425private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
10426 f_sleep(1.0);
10427
10428 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10429 f_bssap_le_register_imsi(g_pars.imsi, omit);
10430
10431 /* provoke an abort by omitting both IMSI and IMEI */
10432 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10433 valueof(ts_BSSMAP_Perform_Location_Request(omit,
10434 ts_CellId_CGI('262'H, '42'H, 23, 42)))));
10435 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10436
10437 /* BSC tells MSC about failure */
10438 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10439 locationEstimate := omit, positioningData := omit,
10440 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
10441
10442 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10443 f_verify_active_A_conn_and_clear();
10444
10445 f_sleep(2.0);
10446 setverdict(pass);
10447}
10448testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
10449 var MSC_ConnHdlr vc_conn;
10450 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10451
10452 f_init(1, true);
10453 f_sleep(1.0);
10454
10455 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10456 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10457
10458 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
10459 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010460 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010461}
10462
10463/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10464 * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
10465private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
10466 f_sleep(1.0);
10467
10468 f_establish_fully(omit, omit);
10469 f_bssap_le_register_imsi(g_pars.imsi, omit);
10470
10471 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10472 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10473
10474 var PDU_BSSAP_LE plr;
10475 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10476
10477 if (do_ta) {
10478 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10479 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10480 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10481 }
10482
10483 /* SMLC fails to respond, BSC runs into timeout */
10484 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
10485 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10486
10487 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10488 locationEstimate := omit, positioningData := omit,
10489 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
10490
10491 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10492 f_verify_active_A_conn_and_clear();
10493
10494 f_sleep(2.0);
10495 setverdict(pass);
10496}
10497
10498/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10499 * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
10500private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
10501 f_lcs_loc_req_for_active_ms_le_timeout(false);
10502}
10503
10504testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
10505 var MSC_ConnHdlr vc_conn;
10506 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10507
10508 f_init(1, true);
10509 f_sleep(1.0);
10510 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
10511 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010512 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010513}
10514
10515/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10516 * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
10517private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
10518 f_lcs_loc_req_for_active_ms_le_timeout(true);
10519}
10520
10521testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
10522 var MSC_ConnHdlr vc_conn;
10523 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10524
10525 f_init(1, true);
10526 f_sleep(1.0);
10527 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
10528 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010529 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010530}
10531
10532/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
10533private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
10534 f_sleep(1.0);
10535
10536 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10537 f_bssap_le_register_imsi(g_pars.imsi, omit);
10538
10539 /* Register to receive the Paging Command */
10540 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10541 g_chan_nr := new_chan_nr;
10542 f_rslem_register(0, g_chan_nr);
10543
10544 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10545 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10546 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10547 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10548
10549 var PDU_BSSAP_LE plr;
10550 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10551
10552 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10553 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10554
10555 /* OsmoBSC needs to Page */
10556 var PDU_BSSAP_LE rx_bsslap;
10557 alt {
10558 [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
10559 f_logp(BSCVTY, "got Paging Command");
10560 repeat;
10561 }
10562 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10563 /* MS does not respond to Paging, TA Req runs into timeout. */
10564 f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
10565 }
10566 }
10567
10568 /* SMLC responds with failure */
10569 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10570 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10571
10572 /* BSC tells MSC about failure */
10573 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10574 locationEstimate := omit, positioningData := omit,
10575 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
10576
10577 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10578 f_verify_active_A_conn_and_clear();
10579
10580 f_sleep(2.0);
10581 setverdict(pass);
10582}
10583testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
10584 var MSC_ConnHdlr vc_conn;
10585 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10586
10587 f_init(1, true);
10588 f_sleep(1.0);
10589
10590 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10591 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10592
10593 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
10594 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010595 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010596}
10597
10598/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
10599 * over. */
10600private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10601 f_sleep(1.0);
10602
10603 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10604 f_bssap_le_register_imsi(g_pars.imsi, omit);
10605
10606 /* Register to receive the Paging Command */
10607 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10608 g_chan_nr := new_chan_nr;
10609 f_rslem_register(0, g_chan_nr);
10610
10611 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10612 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10613 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10614 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10615
10616 var PDU_BSSAP_LE plr;
10617 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10618
10619 /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
10620 * and establish Layer 3. It should use the existing A-interface conn. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010621 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 +020010622 do_clear := false, expect_bssmap_l3 := true);
10623
10624 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10625 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10626
10627 /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
10628 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10629
10630 /* SMLC got the TA from the BSC, now responds with geo information data. */
10631 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10632 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10633 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10634
10635 /* The lchan should still exist, it was from a CM Service Request. */
10636 f_mo_l3_transceive();
10637
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010638 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010639
10640 f_sleep(2.0);
10641 setverdict(pass);
10642}
10643testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
10644 var MSC_ConnHdlr vc_conn;
10645 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10646
10647 f_init(1, true);
10648 f_sleep(1.0);
10649
10650 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10651 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10652
10653 vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
10654 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010655 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010656}
10657
10658/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
10659 * the new lchan after handover. */
10660private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10661 f_sleep(1.0);
10662
10663 f_establish_fully(omit, omit);
10664 f_bssap_le_register_imsi(g_pars.imsi, omit);
10665
10666 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10667 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10668
10669 var PDU_BSSAP_LE plr;
10670 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10671
10672 /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
10673 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
10674
10675 var HandoverState hs := {
10676 rr_ho_cmpl_seen := false,
10677 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +020010678 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010679 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010680 };
10681 /* issue hand-over command on VTY */
10682 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
10683 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
10684 f_rslem_suspend(RSL1_PROC);
10685
10686 /* From the MGW perspective, a handover is is characterized by
10687 * performing one MDCX operation with the MGW. So we expect to see
10688 * one more MDCX during handover. */
10689 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
10690
10691 alt {
10692 [] as_handover(hs);
10693 }
10694
10695 var PDU_BSSAP_LE rx_bsslap;
10696
10697 interleave {
10698 /* Expect the BSC to inform the MSC about the handover */
10699 [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
10700
10701 /* Expect the BSC to inform the SMLC about the handover */
10702 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10703 f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
10704 }
10705 }
10706
10707 /* SMLC now responds with geo information data. */
10708 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10709 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10710 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10711
10712 /* lchan still active */
10713 f_mo_l3_transceive(RSL1);
10714
10715 /* MSC decides it is done now. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010716 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010717
10718 f_sleep(2.0);
10719 setverdict(pass);
10720}
10721testcase TC_ho_during_lcs_loc_req() runs on test_CT {
10722 var MSC_ConnHdlr vc_conn;
10723 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10724
10725 f_init(2, true);
10726 f_sleep(1.0);
10727 vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
10728 vc_conn.done;
Oliver Smith39f53072022-10-27 14:44:04 +020010729 f_shutdown_helper(ho := true);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010730}
10731
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010732private function f_tc_emerg_call_and_lcs_loc_req(charstring id) runs on MSC_ConnHdlr
10733{
10734 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
10735 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
10736 * another lchan. */
Pau Espin Pedrol1809bce2023-01-03 16:54:41 +010010737 g_pars.ra := f_rnd_ra_emerg();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010738 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010739 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010740
10741 /* Here would usually be a CC Call Proceeding from the MSC, but what does the BSC care about DTAP. */
10742
10743 /* Do a Location Request in-between the CC call setup */
10744 f_bssap_le_register_imsi(g_pars.imsi, omit);
10745 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10746 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10747 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10748 /* SMLC got the TA from the BSC, now responds with geo information data. */
10749 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10750 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10751 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10752
Pau Espin Pedrol14076d32023-01-03 17:07:59 +010010753 f_assignment_emerg_setup_voice();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010754
10755 setverdict(pass);
10756 f_perform_clear();
10757}
10758
10759testcase TC_emerg_call_and_lcs_loc_req() runs on test_CT {
10760 var MSC_ConnHdlr vc_conn;
10761 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10762
10763 f_init(1, true);
10764 f_sleep(1.0);
10765 f_vty_allow_emerg_msc(true);
10766 f_vty_allow_emerg_bts(true, 0);
10767 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req), pars);
10768 vc_conn.done;
10769 f_shutdown_helper();
10770}
10771
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010772private altstep no_bssmap_clear_req() runs on MSC_ConnHdlr {
10773 [] BSSAP.receive(tr_BSSMAP_ClearRequest) {
10774 setverdict(fail, "unexpected BSSMAP Clear Request");
10775 mtc.stop;
10776 }
10777}
10778
10779private type enumerated RslRel {
10780 RSLREL_REL_IND,
10781 RSLREL_CONN_FAIL
10782};
10783
10784private function f_emerg_call_and_lcs_loc_req_early_lchan_release(RslRel rsl_rel) runs on MSC_ConnHdlr
10785{
10786 g_pars.ra := f_rnd_ra_emerg();
10787 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010788 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010789
10790 /* Start a Location Request to locate the emergency */
10791 f_bssap_le_register_imsi(g_pars.imsi, omit);
10792 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10793 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10794 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10795
10796 /* 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
10797 * do a Clear Command when the Location Response arrives. */
10798 activate(no_bssmap_clear_req());
10799
10800 /* the lchan gets interrupted while the Location Request has no response */
10801 select (rsl_rel) {
10802 case (RSLREL_REL_IND) {
10803 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
10804 f_expect_lchan_rel(RSL, RSL_PROC);
10805 }
10806 case (RSLREL_CONN_FAIL) {
10807 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
10808 }
10809 case else {
10810 setverdict(fail, "Unknown RslRel type");
10811 mtc.stop;
10812 }
10813 }
10814
10815 /* Still expect the Location Response to find its way to the MSC. */
10816 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10817 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10818 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10819
10820 setverdict(pass);
10821
10822 select (rsl_rel) {
10823 case (RSLREL_REL_IND) {
10824 f_perform_clear_no_lchan();
10825 }
10826 case (RSLREL_CONN_FAIL) {
10827 f_perform_clear();
10828 }
10829 }
10830}
10831
10832private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind(charstring id) runs on MSC_ConnHdlr
10833{
10834 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_REL_IND);
10835}
10836
10837testcase TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() runs on test_CT {
10838 var MSC_ConnHdlr vc_conn;
10839 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10840
10841 f_init(1, true);
10842 f_sleep(1.0);
10843 f_vty_allow_emerg_msc(true);
10844 f_vty_allow_emerg_bts(true, 0);
10845 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind), pars);
10846 vc_conn.done;
10847 f_shutdown_helper();
10848}
10849
10850private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail(charstring id) runs on MSC_ConnHdlr
10851{
10852 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_CONN_FAIL);
10853}
10854
10855testcase TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() runs on test_CT {
10856 var MSC_ConnHdlr vc_conn;
10857 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10858
10859 f_init(1, true);
10860 f_sleep(1.0);
10861 f_vty_allow_emerg_msc(true);
10862 f_vty_allow_emerg_bts(true, 0);
10863 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail), pars);
10864 vc_conn.done;
10865 f_shutdown_helper();
10866}
10867
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010868/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
10869private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
10870 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10871
10872 /* Also disable attach for the single connected MSC */
10873 f_vty_msc_allow_attach(BSCVTY, { false });
10874
10875 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) ));
10876 f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
10877
10878 /* No MSC is found, expecting a proper release on RSL */
10879 interleave {
10880 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
10881 f_logp(BSCVTY, "Got RSL RR Release");
10882 }
10883 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10884 f_logp(BSCVTY, "Got RSL Deact SACCH");
10885 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010886 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010887 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
10888 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010889 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010890 }
10891 }
10892 setverdict(pass);
10893}
10894testcase TC_no_msc() runs on test_CT {
10895
10896 f_init(1, true);
10897 f_sleep(1.0);
10898 var MSC_ConnHdlr vc_conn;
10899 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10900
10901 f_ctrs_bsc_init(counternames_bsc_mscpool);
10902
10903 vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
10904 vc_conn.done;
10905
10906 f_ctrs_bsc_add("mscpool:subscr:no_msc");
10907 f_ctrs_bsc_verify();
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010908 f_shutdown_helper();
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010909}
10910
Harald Welte0ea2d5e2018-04-07 21:40:29 +020010911/* Dyn PDCH todo:
10912 * activate OSMO as TCH/F
10913 * activate OSMO as TCH/H
10914 * does the BSC-located PCU socket get the updated INFO?
10915 * what if no PCU is connected at the time?
10916 * is the info correct on delayed PCU (re)connect?
10917 */
Harald Welte94e0c342018-04-07 11:33:23 +020010918
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010919private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +020010920 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020010921 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010922
10923 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
10924 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10925 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
10926 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
10927 g_pars.ass_codec_list.codecElements[0];
10928 if (isvalue(g_pars.expect_mr_s0_s7)) {
10929 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
10930 g_pars.expect_mr_s0_s7;
10931 }
10932 }
10933 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
10934 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
10935 log("expecting ASS COMPL like this: ", exp_compl);
10936
10937 f_establish_fully(ass_cmd, exp_compl);
10938
Neels Hofmeyr8746b0d2021-06-01 17:25:39 +020010939 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 +000010940
10941 var RSL_Message rsl;
10942
10943 timer T := 5.0;
10944 T.start;
10945 alt {
10946 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
10947 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
10948 log("Rx L3 from net: ", l3);
10949 if (ischosen(l3.msgs.rrm.channelModeModify)) {
10950 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10951 mtc.stop;
10952 }
10953 }
10954 [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
10955 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10956 mtc.stop;
10957 }
10958 [] T.timeout {
10959 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
10960 setverdict(pass);
10961 }
10962 }
10963 T.stop;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010964
10965 f_perform_clear();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010966}
10967
10968/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
10969 * osmo-bsc. */
10970testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
10971 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10972 var MSC_ConnHdlr vc_conn;
10973
10974 f_init(1, true);
10975 f_sleep(1.0);
10976
10977 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10978 vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
10979 vc_conn.done;
10980 f_shutdown_helper();
10981}
10982
10983/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
10984 */
10985testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
10986 f_init_vty();
10987
10988 f_init(1, false);
10989 f_sleep(1.0);
10990
10991 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
10992
10993 var ASP_RSL_Unitdata rx_rsl_ud;
10994 timer T := 5.0;
10995
10996 T.start;
10997 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010998 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010999 if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
11000 T.stop;
11001 setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
11002 mtc.stop;
11003 }
11004 repeat;
11005 }
11006 [] T.timeout {
11007 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
11008 setverdict(pass);
11009 }
11010 }
11011}
11012
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011013private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
11014 /* First fully set up a speech lchan */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011015 f_assignment_codec(id, do_perform_clear := false);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011016
11017 /* Trigger re-assignment to another lchan */
11018 var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
11019
11020 /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
11021 * one MDCX on MGCP. */
11022 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
11023
11024 /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
11025 * as the old lchan used. */
11026 g_media.bts.ipa_crcx_seen := false;
11027 g_media.bts.ipa_mdcx_seen := false;
11028
11029 /* Send different BTS side RTP port number for the new lchan */
11030 g_media.bts.bts.port_nr := 4223;
11031
11032 f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
11033
11034 /* Trigger re-assignment. */
11035 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
11036
11037 timer T := 5.0;
11038 T.start;
11039 alt {
11040 [] as_assignment(assignment_st);
11041 [] as_Media();
11042 [] T.timeout {
11043 break;
11044 }
11045 }
11046
11047 if (not assignment_st.assignment_done) {
11048 setverdict(fail, "Assignment did not complete");
11049 mtc.stop;
11050 }
11051
11052 f_check_mgcp_expectations()
11053 setverdict(pass);
11054
11055 f_sleep(2.0);
11056 log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
11057
11058 /* Instruct BSC to clear channel */
11059 var BssmapCause cause := 0;
11060 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
11061 interleave {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011062 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
11063 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020011064 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011065 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020011066 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011067 }
11068 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
11069 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11070 }
11071 }
Neels Hofmeyr40a45d12021-09-23 22:57:12 +020011072 f_expect_dlcx_conns();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011073
11074 f_sleep(0.5);
11075}
11076
11077testcase TC_reassignment_fr() runs on test_CT {
11078 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11079 var MSC_ConnHdlr vc_conn;
11080
11081 f_init(1, true);
11082 f_sleep(1.0);
11083
Neels Hofmeyrac432fa2021-11-02 16:45:56 +010011084 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011085
11086 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11087 vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
11088 vc_conn.done;
11089
11090 /* from f_establish_fully() */
11091 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
11092 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
11093 /* from re-assignment */
11094 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
11095 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
11096 f_ctrs_bsc_and_bts_verify();
11097 f_shutdown_helper();
11098}
11099
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011100const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
11101const charstring REEST_CLEAR := "REEST_CLEAR";
11102const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
11103
11104/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
11105 * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
11106 * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
11107 * the MSC as the CM Re-Establishment is handled.
11108 *
11109 * MS bts0 bts1 bsc msc test-component
11110 * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
11111 * | | _1 wait a bit, to settle down
11112 * |<-x x--| | _1 "lose connection"
11113 * | | REEST_LOST_CONNECTION
11114 * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
11115 * | | REEST_CLEAR
11116 * | |<-0---| _1 Clear Command on first A-conn
11117 * | |--0-->| _1 Clear Complete
11118 * | |<----------------->| | _1 Release first channel
11119 * | | REEST_CLEAR_DONE
11120 * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
11121 * |<-----------------|<-------|<-1---| _2 Clear Command, Release
11122 *
11123 */
11124private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
11125 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
11126 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11127
11128 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11129 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11130
11131 f_establish_fully(ass_cmd, exp_compl);
11132
11133 /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
11134 * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
11135 * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
11136 f_sleep(2.0);
11137 COORD.send(REEST_LOST_CONNECTION);
11138
11139 alt {
11140 [] COORD.receive(REEST_CLEAR);
11141 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
11142 setverdict(fail, "Unexpected channel release");
11143 mtc.stop;
11144 }
11145 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
11146 setverdict(fail, "Unexpected channel release");
11147 mtc.stop;
11148 }
11149 }
11150 f_perform_clear()
Neels Hofmeyr969abd02021-09-23 22:24:08 +020011151 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011152 COORD.send(REEST_CLEAR_DONE);
11153}
11154
11155private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
11156 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
11157
11158 /* The MS lost the connection on the first channel, now establishes another one */
11159 COORD.receive(REEST_LOST_CONNECTION);
11160
11161 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
11162 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
11163 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
11164
11165 f_create_bssmap_exp(l3_enc);
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011166 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 +020011167 BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
11168
11169 /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
11170 COORD.send(REEST_CLEAR);
11171 COORD.receive(REEST_CLEAR_DONE);
11172
11173 f_sleep(2.0);
11174
11175 /* Answer the CM Re-Establishment with an Assignment Command. */
11176 var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
11177 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11178 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11179 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11180
11181 var AssignmentState st := valueof(ts_AssignmentStateInit);
Oliver Smithce2dd692023-04-17 10:25:50 +020011182 st.rtp_stream := true;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011183 st.is_assignment := true;
11184
11185 var ExpectCriteria mgcpcrit := {
11186 connid := omit,
11187 endpoint := omit,
11188 transid := omit
11189 };
11190 f_create_mgcp_expect(mgcpcrit);
11191
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011192 f_rslem_dchan_queue_enable(RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011193
11194 BSSAP.send(ass_cmd);
11195
11196 var PDU_BSSAP bssap;
11197
11198 alt {
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011199 [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
11200 [] as_Media_ipacc(RSL1, RSL2);
11201 [] as_Media_mgw();
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011202 [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
11203 break;
11204 }
11205 }
11206
11207 f_sleep(3.0);
11208
11209 f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011210 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011211}
11212
11213testcase TC_cm_reestablishment() runs on test_CT {
11214 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
11215 var MSC_ConnHdlr vc_conn1;
11216
11217 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
11218 var MSC_ConnHdlr vc_conn2;
11219 pars2.imsi := pars1.imsi;
11220 pars2.media_nr := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011221 pars2.expect_tsc := c_BtsParams[1].tsc;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011222
11223 f_init(2, true, guard_timeout := 40.0);
11224 f_sleep(1.0);
11225
11226 vc_conn1 := f_start_handler_create(pars1);
11227 vc_conn2 := f_start_handler_create(pars2);
11228 connect(vc_conn1:COORD, vc_conn2:COORD);
11229 f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
11230 f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
11231 vc_conn1.done;
11232 vc_conn2.done;
11233
11234 f_shutdown_helper();
11235}
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011236
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011237function f_exp_ipa_rx_nonfatal(template (present) RSL_Message t_rx,
11238 boolean ignore_other_rx := true,
11239 BtsTrxIdx idx := {0, 0},
11240 float Tval := 2.0)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011241runs on test_CT return template (omit) RSL_Message {
11242 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011243 timer T := Tval;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011244
11245 T.start;
11246 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011247 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011248 T.stop;
11249 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011250 [ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
11251 [not ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011252 log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
11253 T.stop;
11254 return omit;
11255 }
11256 [] T.timeout {
11257 return omit;
11258 }
11259 }
11260 return rx_rsl_ud.rsl;
11261}
11262
11263private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
11264 f_vty_enter_cfg_bts(pt, bts_nr);
11265 f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
11266 f_vty_transceive(pt, "exit");
11267 f_vty_transceive(pt, "exit");
11268 f_vty_transceive(pt, "exit");
11269}
11270
11271private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +030011272 template (present) RslChannelNr chan_nr := ?,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011273 template (present) uint12_t arfcn := ?,
11274 template (present) uint3_t tsc := ?)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011275{
11276 var RSL_IE_Body full_imm_ass_info;
11277 if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
11278 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
11279 mtc.stop;
11280 }
11281
11282 var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
11283 var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
11284 fn := fn,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011285 ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011286 page_mode := ?);
11287 if (not match(rr_imm_ass, expect_imm_ass)) {
11288 log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
11289 setverdict(fail, "Failed to match Immediate Assignment");
11290 mtc.stop;
11291 }
11292}
11293
11294testcase TC_imm_ass_post_chan_ack() runs on test_CT {
11295 var RSL_Message chan_act;
11296 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011297 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011298
11299 f_init(1, false);
11300 f_sleep(1.0);
11301
11302 /* (should be the default anyway, just to make things clear) */
11303 f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
11304
11305 /* RA containing reason=LU */
11306 var GsmFrameNumber fn := 2342;
11307 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011308 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011309
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011310 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011311
11312 /* First send the Chan Act ACK */
11313 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011314 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011315 var RSL_IE_Body chan_ident_ie;
11316 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11317 setverdict(fail, "RSL Channel Identification IE is absent");
11318 mtc.stop;
11319 }
11320
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011321 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011322
11323 /* Then expect the Immediate Assignment, after we ACKed the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011324 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011325
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011326 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11327 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011328
11329 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011330 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011331
11332 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011333 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011334 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011335 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11336
11337 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011338 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011339 f_shutdown_helper();
11340}
11341
11342testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
11343 var RSL_Message chan_act;
11344 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011345 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011346
11347 f_init(1, false);
11348 f_sleep(1.0);
11349
11350 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11351
11352 /* RA containing reason=LU */
11353 var GsmFrameNumber fn := 2342;
11354 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011355 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011356
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011357 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011358 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011359 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011360 var RSL_IE_Body chan_ident_ie;
11361 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11362 setverdict(fail, "RSL Channel Identification IE is absent");
11363 mtc.stop;
11364 }
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011365
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011366 /* (set bts 0 cfg back to default) */
11367 f_vty_set_imm_ass(BSCVTY);
11368
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011369 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011370 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011371 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11372 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011373
11374 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011375 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011376
11377 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011378 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011379
11380 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011381 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011382 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011383 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11384
11385 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011386 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011387 f_shutdown_helper();
11388}
11389
Neels Hofmeyr23158742021-09-07 19:08:07 +020011390testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
11391 var RSL_Message chan_act;
11392 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011393 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr23158742021-09-07 19:08:07 +020011394
11395 f_init(1, false);
11396 f_sleep(1.0);
11397
11398 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11399
11400 /* RA containing reason=LU */
11401 var GsmFrameNumber fn := 2342;
11402 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011403 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011404
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011405 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011406 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011407 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr23158742021-09-07 19:08:07 +020011408 var RSL_IE_Body chan_ident_ie;
11409 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11410 setverdict(fail, "RSL Channel Identification IE is absent");
11411 mtc.stop;
11412 }
11413
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011414 /* (set bts 0 cfg back to default) */
11415 f_vty_set_imm_ass(BSCVTY);
11416
Neels Hofmeyr23158742021-09-07 19:08:07 +020011417 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011418 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011419 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11420 chan_ident_ie.chan_ident.ch_desc.v.tsc);
11421
11422 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011423 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011424
11425 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011426 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011427
11428 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011429 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011430 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr23158742021-09-07 19:08:07 +020011431 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11432
11433 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011434 f_perform_clear_test_ct(dt);
Neels Hofmeyr23158742021-09-07 19:08:07 +020011435 f_shutdown_helper();
11436}
11437
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011438testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
11439 /* change Timeslot 6 before f_init() starts RSL */
11440 f_init_vty();
11441 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11442 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11443
11444 f_init(1, false);
11445 f_sleep(1.0);
11446
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011447 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011448 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11449 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011450 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11451 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011452
11453 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11454 f_ts_set_chcomb(0, 0, 6, "PDCH");
11455
11456 /* block all static timeslots so that the dyn TS will be used */
11457 f_disable_all_tch_f();
11458 f_disable_all_tch_h();
11459 f_disable_all_sdcch();
11460
11461 var RSL_Message chan_act;
11462 var RSL_Message imm_ass;
11463
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011464 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11465
11466 /* RA containing reason=LU */
11467 var GsmFrameNumber fn := 2342;
11468 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011469 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011470
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011471 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011472 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
11473 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011474
11475 /* Now activation as SDCCH8 */
11476 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011477 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011478
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011479 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011480 var RSL_IE_Body chan_ident_ie;
11481 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11482 setverdict(fail, "RSL Channel Identification IE is absent");
11483 mtc.stop;
11484 }
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011485
11486 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011487 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011488 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11489 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011490
11491 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011492 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011493
11494 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011495 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011496
11497 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011498 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011499 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011500 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11501
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011502 /* (set bts 0 cfg back to default) */
11503 f_vty_set_imm_ass(BSCVTY);
11504
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011505 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011506 f_perform_clear_test_ct(dt);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011507 f_shutdown_helper();
11508}
11509
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011510testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
11511 /* change Timeslot 6 before f_init() starts RSL */
11512 f_init_vty();
11513 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11514 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11515
11516 f_init(1, false);
11517 f_sleep(1.0);
11518
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011519 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011520 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11521 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011522 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11523 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011524
11525 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11526 f_ts_set_chcomb(0, 0, 6, "PDCH");
11527
11528 /* block all static timeslots so that the dyn TS will be used */
11529 f_disable_all_tch_f();
11530 f_disable_all_tch_h();
11531 f_disable_all_sdcch();
11532
11533 var RSL_Message chan_act;
11534 var RSL_Message imm_ass;
11535
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011536 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11537
11538 /* RA containing reason=LU */
11539 var GsmFrameNumber fn := 2342;
11540 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011541 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011542
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011543 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011544 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011545
11546 /* And already the Immediate Assignment even before the PDCH Deact ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011547 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011548
11549 /* continue the Osmo style PDCH Deact (usual chan rel) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011550 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011551
11552 /* Now activation as SDCCH8 */
11553 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011554 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011555
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011556 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011557 var RSL_IE_Body chan_ident_ie;
11558 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11559 setverdict(fail, "RSL Channel Identification IE is absent");
11560 mtc.stop;
11561 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011562 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011563
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011564 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11565 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011566
11567 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011568 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011569
11570 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011571 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011572 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011573 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11574
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011575 /* (set bts 0 cfg back to default) */
11576 f_vty_set_imm_ass(BSCVTY);
11577
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011578 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011579 f_perform_clear_test_ct(dt);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011580 f_shutdown_helper();
11581}
11582
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011583/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
11584testcase TC_ctrl_trx_rf_locked() runs on test_CT {
11585 var MSC_ConnHdlr vc_conn;
11586
11587 f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
11588 f_sleep(1.0);
11589
11590 /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
11591 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11592 "0,0,operational,unlocked,on,rsl-up;" &
11593 "1,0,operational,unlocked,on,rsl-up;" &
11594 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011595 "2,1,operational,unlocked,on,rsl-down;" &
11596 "2,2,operational,unlocked,on,rsl-down;" &
11597 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011598 "3,0,inoperational,locked,on,rsl-down;");
11599
11600 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock BTS 1 TRX 0");
11601 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11602 /* give it a moment to settle the FSM status */
11603 f_sleep(1.0);
11604
11605 /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
11606 * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
11607 * of "off"? But that's for a future patch if at all. */
11608 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11609 "0,0,operational,unlocked,on,rsl-up;" &
11610 "1,0,operational,locked,on,rsl-up;" &
11611 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011612 "2,1,operational,unlocked,on,rsl-down;" &
11613 "2,2,operational,unlocked,on,rsl-down;" &
11614 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011615 "3,0,inoperational,locked,on,rsl-down;");
11616
11617 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
11618 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11619 f_sleep(1.0);
11620 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11621 "0,0,operational,unlocked,on,rsl-up;" &
11622 "1,0,operational,locked,on,rsl-up;" &
11623 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011624 "2,1,operational,unlocked,on,rsl-down;" &
11625 "2,2,operational,unlocked,on,rsl-down;" &
11626 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011627 "3,0,inoperational,locked,on,rsl-down;");
11628
11629 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
11630 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
11631 f_sleep(1.0);
11632 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11633 "0,0,operational,unlocked,on,rsl-up;" &
11634 "1,0,operational,unlocked,on,rsl-up;" &
11635 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011636 "2,1,operational,unlocked,on,rsl-down;" &
11637 "2,2,operational,unlocked,on,rsl-down;" &
11638 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011639 "3,0,inoperational,locked,on,rsl-down;");
11640
11641 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
11642 f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
11643 f_sleep(1.0);
11644 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11645 "0,0,operational,unlocked,on,rsl-up;" &
11646 "1,0,operational,unlocked,on,rsl-up;" &
11647 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011648 "2,1,operational,unlocked,on,rsl-down;" &
11649 "2,2,operational,unlocked,on,rsl-down;" &
11650 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011651 "3,0,inoperational,locked,on,rsl-down;");
11652
11653 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
11654 f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
11655 f_sleep(1.0);
11656 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11657 "0,0,operational,unlocked,on,rsl-up;" &
11658 "1,0,operational,unlocked,on,rsl-up;" &
11659 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011660 "2,1,operational,unlocked,on,rsl-down;" &
11661 "2,2,operational,unlocked,on,rsl-down;" &
11662 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011663 "3,0,inoperational,locked,on,rsl-down;");
11664
11665 f_shutdown_helper();
11666}
11667
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011668const CounterNameVals counternames_cm_serv_rej := {
11669 { "cm_serv_rej", 0 },
11670 { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
11671 { "cm_serv_rej:illegal_ms", 0 },
11672 { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
11673 { "cm_serv_rej:imei_not_accepted", 0 },
11674 { "cm_serv_rej:illegal_me", 0 },
11675 { "cm_serv_rej:plmn_not_allowed", 0 },
11676 { "cm_serv_rej:loc_not_allowed", 0 },
11677 { "cm_serv_rej:roaming_not_allowed", 0 },
11678 { "cm_serv_rej:network_failure", 0 },
11679 { "cm_serv_rej:synch_failure", 0 },
11680 { "cm_serv_rej:congestion", 0 },
11681 { "cm_serv_rej:srv_opt_not_supported", 0 },
11682 { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
11683 { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
11684 { "cm_serv_rej:call_can_not_be_identified", 0 },
11685 { "cm_serv_rej:incorrect_message", 0 },
11686 { "cm_serv_rej:invalid_mandantory_inf", 0 },
11687 { "cm_serv_rej:msg_type_not_implemented", 0 },
11688 { "cm_serv_rej:msg_type_not_compatible", 0 },
11689 { "cm_serv_rej:inf_eleme_not_implemented", 0 },
11690 { "cm_serv_rej:condtional_ie_error", 0 },
11691 { "cm_serv_rej:msg_not_compatible", 0 },
11692 { "cm_serv_rej:protocol_error", 0 },
11693 { "cm_serv_rej:retry_in_new_cell", 0 }
11694};
11695
11696private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
11697{
11698 f_create_chan_and_exp();
Vadim Yanitskiya7fc5a62021-12-04 20:10:08 +030011699 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011700 BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011701 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_CM_SERV_REJ));
11702 f_perform_clear();
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011703 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011704}
11705testcase TC_cm_serv_rej() runs on test_CT {
11706 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11707 var MSC_ConnHdlr vc_conn;
11708
11709 f_init(1, true);
11710 f_sleep(1.0);
11711
11712 f_ctrs_bts_init(1, counternames_cm_serv_rej);
11713
11714 vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
11715 vc_conn.done;
11716
11717 f_ctrs_bts_add(0, "cm_serv_rej", 1);
11718 f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
11719 f_ctrs_bts_verify();
11720
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011721 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011722 f_shutdown_helper();
11723}
11724
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011725/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
11726 * Activ Ack (SYS#5627). */
11727private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
11728 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Vadim Yanitskiyf0310e32021-10-26 00:30:59 +030011729
11730 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11731 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011732
11733 var BSSMAP_FIELD_CodecType codecType;
11734 codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
11735
11736 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
11737
11738 /* First establish a signalling lchan */
11739 f_create_chan_and_exp();
11740 f_rslem_dchan_queue_enable();
11741
11742 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011743
11744 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
Oliver Smith735b47c2023-02-15 16:03:54 +010011745 activate(as_Media_mgw());
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011746
11747 var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
11748 f_rslem_register(0, chan_nr);
11749
11750 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
11751 BSSAP.send(ass_cmd);
11752
11753
11754 /* Wait for the Channel Activ for the TCH channel */
11755 var ASP_RSL_Unitdata rx_rsl_ud;
11756 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
11757
11758 /* make the original SDCCH disappear */
11759 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
11760
11761 /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
11762 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
11763
11764 interleave {
11765 [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
11766 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
11767 }
11768
11769 BSSAP.send(ts_BSSMAP_ClearCommand(0));
11770 BSSAP.receive(tr_BSSMAP_ClearComplete);
11771 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11772
11773 var MgcpCommand mgcp;
Vadim Yanitskiy6be4cf42022-06-04 21:25:47 +060011774 var MGCP_RecvFrom mrf;
11775 var template MgcpMessage msg_dlcx := { command := tr_DLCX };
11776 alt {
11777 [g_pars.aoip] MGCP.receive(tr_DLCX) -> value mgcp {
11778 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
11779 }
11780 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
11781 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
11782 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
11783 }));
11784 }
11785 }
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011786
11787 f_sleep(0.5);
11788}
11789testcase TC_lost_sdcch_during_assignment() runs on test_CT {
11790 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11791 var MSC_ConnHdlr vc_conn;
11792
Oliver Smith735b47c2023-02-15 16:03:54 +010011793 pars.fail_on_dlcx := false;
11794
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011795 f_init(1, true);
11796 f_sleep(1.0);
11797
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011798 vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
11799 vc_conn.done;
11800
11801 f_shutdown_helper();
11802}
11803
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011804const CounterNameVals counternames_bsc_bts_all_available_allocated := {
11805 { "all_allocated:sdcch", 0 },
11806 { "all_allocated:static_sdcch", 0 },
11807 { "all_allocated:tch", 0 },
11808 { "all_allocated:static_tch", 0 }
11809}
11810
11811private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
11812{
11813 /* Make sure counters settle first */
11814 f_sleep(1.0);
11815
11816 /* Take a baseline of counters */
11817 f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
11818
11819 /* Elapse some time so that we see changes in counters, hopefully where expected */
11820 f_sleep(2.0);
11821
11822 /* Get new counters */
11823 var charstring_list all_changed := {};
11824 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
11825 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
11826
11827 /* Compare with expectations */
11828 var charstring_list all_expect_changed := {};
11829 for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
11830 all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
11831 }
11832 f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
11833}
11834
11835testcase TC_ratectr_all_available_allocated() runs on test_CT {
11836 var ASP_RSL_Unitdata rsl_ud;
11837 var integer i;
11838 var integer chreq_total, chreq_nochan;
11839
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011840 f_init(1, guard_timeout := 60.0);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011841 f_sleep(1.0);
11842
11843 /* Exhaust all dedicated SDCCH lchans.
11844 /* GSM 44.018 Table 9.1.8.2:
11845 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11846 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011847 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011848 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011849 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 +020011850 }
11851
11852 /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
11853 * level.
11854 * All SDCCH are now occupied. */
11855 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11856
11857 /* Also fill up all remaining (TCH) channels */
11858 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011859 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 +020011860 }
11861
11862 /* All TCH are now also occupied */
11863 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11864 "all_allocated:tch", "all_allocated:static_tch"});
11865
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011866 /* Clean up SDCCH lchans */
11867 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11868 f_perform_clear_test_ct(chan_cleanup[i]);
11869 }
11870
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011871 f_shutdown_helper();
11872}
11873
11874testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
11875 var ASP_RSL_Unitdata rsl_ud;
11876 var integer i;
11877 var integer chreq_total, chreq_nochan;
11878
11879 f_init_vty();
11880 f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
11881 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11882 /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
11883
11884 f_init(1, guard_timeout := 60.0);
11885 f_sleep(1.0);
11886
11887 /* The dyn TS wants to activate PDCH mode, ACK that. */
11888 var RslChannelNr chan_nr;
11889 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011890 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11891 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011892
11893 /* Exhaust all dedicated SDCCH lchans.
11894 /* GSM 44.018 Table 9.1.8.2:
11895 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11896 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011897 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011898 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011899 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 +020011900 }
11901
11902 /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
11903 * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
11904 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
11905
11906 /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
11907 * Will release them later, so remember all the DchanTuples. */
11908 var DchanTuples dyn_sddch := {};
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011909 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 +020011910
11911 /* Also occupy the seven other SDCCH of the dyn TS */
11912 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011913 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 +020011914 }
11915
11916 /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
11917 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11918
11919 /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
11920 for (i := 0; i < 5; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011921 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 +020011922 }
11923
11924 /* All TCH lchans are now also occupied, both static and dynamic */
11925 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11926 "all_allocated:tch", "all_allocated:static_tch"});
11927
11928 /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
11929 * incrementing. */
11930 var BssmapCause cause := 0;
11931 var DchanTuple dt := dyn_sddch[0];
11932 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011933 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011934
11935 /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
11936 * count as occupied, so those still both increment. */
11937 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
11938 "all_allocated:tch", "all_allocated:static_tch"});
11939
11940 /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
11941 for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
11942 dt := dyn_sddch[i];
11943 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011944 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011945 }
11946
11947 /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
11948 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011949 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11950 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011951
11952 /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
11953 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
11954
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011955 /* Clean up SDCCH lchans */
11956 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11957 f_perform_clear_test_ct(chan_cleanup[i]);
11958 }
11959
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011960 /* clean up config */
11961 f_ts_reset_chcomb(0);
11962
11963 f_shutdown_helper();
11964}
11965
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011966private function f_TC_chan_alloc_algo(DchanTuple dt, BtsTrxIdx idx)
11967runs on test_CT {
11968 /* MSC sends an Assignment Request */
11969 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11970 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11971 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11972 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
11973
11974 /* Expect the BSC to allocate a TCH channel on the given BTS/TRX */
11975 var RSL_Message rsl_chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
11976 /* Send CHAN ACT NACK, so that the requested TCH channel becomes BORKEN */
11977 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(rsl_chan_act.ies[0].body.chan_nr, RSL_ERR_EQUIPMENT_FAIL), idx);
11978 /* Expect to receive an Assignment Failure */
11979 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail));
11980}
11981
11982testcase TC_chan_alloc_algo_ascending() runs on test_CT {
11983 /* We need to access BTS2, which has 4 TRXs */
11984 f_init(nr_bts := 3);
11985
11986 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020011987 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011988
11989 f_vty_enter_cfg_bts(BSCVTY, 2);
11990 f_vty_transceive(BSCVTY, "channel allocator ascending");
11991 f_vty_transceive(BSCVTY, "end");
11992
11993 /* Expect the BSC to allocate 4 x TCH/F channels on BTS2/TRX0 */
11994 for (var integer i := 0; i < 4; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011995 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011996 f_TC_chan_alloc_algo(dt, {2, 0});
11997 f_perform_clear_test_ct(dt);
11998 }
11999
12000 /* At this point all 4 x TCH/F channels are BORKEN, but they will be
12001 * resurrected upon the A-bis/OML link re-establishment. */
12002 f_shutdown_helper();
12003}
12004
12005testcase TC_chan_alloc_algo_descending() runs on test_CT {
12006 /* We need to access BTS2, which has 4 TRXs */
12007 f_init(nr_bts := 3);
12008
12009 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012010 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012011
12012 f_vty_enter_cfg_bts(BSCVTY, 2);
12013 f_vty_transceive(BSCVTY, "channel allocator descending");
12014 f_vty_transceive(BSCVTY, "end");
12015
12016 /* Expect the BSC to allocate 5 x TCH/F channels on BTS2/TRX3 */
12017 for (var integer i := 0; i < 5; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012018 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012019 f_TC_chan_alloc_algo(dt, {2, 3});
12020 f_perform_clear_test_ct(dt);
12021 }
12022
12023 /* At this point all 5 x TCH/F channels are BORKEN, but they will be
12024 * resurrected upon the A-bis/OML link re-establishment. */
12025 f_shutdown_helper();
12026}
12027
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012028testcase TC_chan_alloc_algo_ass_dynamic() runs on test_CT {
12029 const BtsTrxIdx TRX0 := {2, 0};
12030 const BtsTrxIdx TRX3 := {2, 3};
12031
12032 /* We need to access BTS2, which has 4 TRXs */
12033 f_init(nr_bts := 3);
12034
12035 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012036 vc_MGCP[0].stop;
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012037
12038 f_vty_enter_cfg_bts(BSCVTY, 2);
12039 f_vty_transceive(BSCVTY, "channel allocator mode assignment dynamic");
12040 f_vty_transceive(BSCVTY, "channel allocator dynamic-param ul-rxlev thresh 50 avg-num 2");
12041 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 0");
12042 f_vty_transceive(BSCVTY, "end");
12043
12044 var DchanTuple dt;
12045
12046 f_logp(BSCVTY, "Case a) Unknown Uplink RxLev, fall-back to ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012047 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012048 f_TC_chan_alloc_algo(dt, TRX0);
12049 f_perform_clear_test_ct(dt);
12050
12051 f_logp(BSCVTY, "Case b) Not enough RxLev samples, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012052 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012053 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12054 ts_RSL_IE_UplinkMeas(30, 0),
12055 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012056 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012057 f_TC_chan_alloc_algo(dt, TRX0);
12058 f_perform_clear_test_ct(dt);
12059
12060 f_logp(BSCVTY, "Case c) Uplink RxLev below the threshold, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012061 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012062 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12063 ts_RSL_IE_UplinkMeas(45, 0),
12064 ts_RSL_IE_BS_Power(0)), TRX0);
12065 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12066 ts_RSL_IE_UplinkMeas(48, 0),
12067 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012068 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012069 f_TC_chan_alloc_algo(dt, TRX0);
12070 f_perform_clear_test_ct(dt);
12071
12072 f_logp(BSCVTY, "Case d) Uplink RxLev above the threshold, use descending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012073 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012074 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12075 ts_RSL_IE_UplinkMeas(50, 0),
12076 ts_RSL_IE_BS_Power(0)), TRX0);
12077 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12078 ts_RSL_IE_UplinkMeas(58, 0),
12079 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012080 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012081 f_TC_chan_alloc_algo(dt, TRX3);
12082 f_perform_clear_test_ct(dt);
12083
12084 f_vty_enter_cfg_bts(BSCVTY, 2);
12085 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 90");
12086 f_vty_transceive(BSCVTY, "end");
12087
12088 f_logp(BSCVTY, "Case e) Uplink RxLev above the threshold, but C0 load is not");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012089 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012090 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12091 ts_RSL_IE_UplinkMeas(50, 0),
12092 ts_RSL_IE_BS_Power(0)), TRX0);
12093 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12094 ts_RSL_IE_UplinkMeas(58, 0),
12095 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012096 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012097 f_TC_chan_alloc_algo(dt, TRX0);
12098 f_perform_clear_test_ct(dt);
12099
12100 f_vty_enter_cfg_bts(BSCVTY, 2);
12101 f_vty_transceive(BSCVTY, "channel allocator ascending");
12102 f_vty_transceive(BSCVTY, "end");
12103
12104 /* At this point some TCH/F channels are BORKEN, but they will be
12105 * resurrected upon the A-bis/OML link re-establishment. */
12106 f_shutdown_helper();
12107}
12108
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012109private function f_vty_mgw_enable(integer mgw_nr := 1) runs on test_CT {
12110 var rof_charstring cmds := {
12111 "remote-ip " & mp_test_ip,
12112 "remote-port " & int2str(2427 + mgw_nr)
12113 };
12114 f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
12115 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " reconnect")
12116}
12117private function f_vty_mgw_disable(integer mgw_nr := 1) runs on test_CT {
12118 f_vty_config3(BSCVTY, {"network"}, { "no mgw " &int2str(mgw_nr) });
12119}
12120private function f_vty_mgw_block(integer mgw_nr := 1, boolean blocked := true) runs on test_CT {
12121 var charstring arg;
12122 if (blocked) {
12123 arg := "block";
12124 } else {
12125 arg := "unblock";
12126 }
12127 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " " & arg);
12128}
12129private const charstring COORD_CMD_ESTABLISHED := "COORD_CMD_ESTABLISHED";
12130private function f_TC_mgwpool_call_seq_1(charstring id) runs on MSC_ConnHdlr {
12131 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12132 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12133 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12134 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12135
12136 f_establish_fully(ass_cmd, exp_compl);
12137 COORD.send(COORD_CMD_ESTABLISHED);
12138
12139 COORD.receive(COORD_CMD_ESTABLISHED);
12140 f_perform_clear()
12141 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12142}
12143private function f_TC_mgwpool_call_seq_2(charstring id) runs on MSC_ConnHdlr {
12144 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12145 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12146 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12147 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12148
12149
12150 COORD.receive(COORD_CMD_ESTABLISHED);
12151 f_establish_fully(ass_cmd, exp_compl);
12152 COORD.send(COORD_CMD_ESTABLISHED);
12153
12154 f_perform_clear()
12155 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12156}
12157/* Test load is spread around 2 available MGWs */
12158testcase TC_mgwpool_all_used() runs on test_CT {
12159 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12160 var MSC_ConnHdlr vc_conn1;
12161 pars1.mgwpool_idx := 0;
12162
12163 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12164 var MSC_ConnHdlr vc_conn2;
12165 pars2.mgwpool_idx := 1;
12166
12167 f_init(1, true, nr_mgw := 2);
12168 f_sleep(1.0);
12169
12170 f_vty_mgw_enable(1);
12171
12172 vc_conn1 := f_start_handler_create(pars1);
12173 vc_conn2 := f_start_handler_create(pars2);
12174 connect(vc_conn1:COORD, vc_conn2:COORD);
12175 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12176 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12177 vc_conn1.done;
12178 vc_conn2.done;
12179
12180 f_vty_mgw_disable(1);
12181
12182 f_shutdown_helper();
12183}
12184
12185/* Test blocked MGW in the pool are not selected */
12186testcase TC_mgwpool_blocked_not_used() runs on test_CT {
12187 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12188 var MSC_ConnHdlr vc_conn1;
12189 pars1.mgwpool_idx := 0;
12190
12191 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12192 var MSC_ConnHdlr vc_conn2;
12193 pars2.mgwpool_idx := 0; /* expect it in the first one, since the second will be blocked */
12194 pars2.media_nr := 2;
12195
12196 f_init(1, true, nr_mgw := 2);
12197 f_sleep(1.0);
12198
12199 f_vty_mgw_enable(1);
12200 f_vty_mgw_block(1, true);
12201
12202 vc_conn1 := f_start_handler_create(pars1);
12203 vc_conn2 := f_start_handler_create(pars2);
12204 connect(vc_conn1:COORD, vc_conn2:COORD);
12205 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12206 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12207 vc_conn1.done;
12208 vc_conn2.done;
12209
12210 f_vty_mgw_disable(1);
12211
12212 f_shutdown_helper();
12213}
12214
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012215/* Test BTS pinning to an MGW is applied */
12216testcase TC_mgwpool_pin_bts() runs on test_CT {
12217 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12218 var MSC_ConnHdlr vc_conn1;
12219 pars1.mgwpool_idx := 0;
12220
12221 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12222 var MSC_ConnHdlr vc_conn2;
12223 pars2.mgwpool_idx := 0; /* expect it in the first one, since the BTS is pinned to the first MGW */
12224 pars2.media_nr := 2;
12225
12226 f_init(1, true, nr_mgw := 2);
12227 f_sleep(1.0);
12228
12229 f_vty_mgw_enable(1);
12230 f_vty_cfg_bts(BSCVTY, 0, { "mgw pool-target 0" });
12231
12232 vc_conn1 := f_start_handler_create(pars1);
12233 vc_conn2 := f_start_handler_create(pars2);
12234 connect(vc_conn1:COORD, vc_conn2:COORD);
12235 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12236 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12237 vc_conn1.done;
12238 vc_conn2.done;
12239
12240 f_vty_cfg_bts(BSCVTY, 0, { "no mgw pool-target" } );
Vadim Yanitskiy389d7e02022-10-25 17:44:05 +070012241 f_vty_mgw_disable(1);
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012242
12243 f_shutdown_helper();
12244}
12245
Oliver Smithc9a5f532022-10-21 11:32:23 +020012246private function f_tc_ho_meas_rep_multi_band(charstring id) runs on MSC_ConnHdlr {
12247 g_pars := f_gen_test_hdlr_pars();
12248 var PDU_BSSAP ass_req := f_gen_ass_req();
12249 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12250 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12251 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12252 f_establish_fully(ass_req, exp_compl);
12253
12254 /* Send a measurement report with bad rxlev except on 3rd entry. The
12255 * measurement report is divided into two sub lists, as described in
12256 * 3GPP TS 04.08 § 10.5.2.20. */
12257 var NcellReports neighbor_rep := {
12258 /* Sub list 1: same band */
Oliver Smitha6773042022-10-24 12:56:30 +020012259 { rxlev := 0, bcch_freq := 0, bsic := 12 }, /* ARFCN 800, band 1800, LAC 98 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012260 /* Sub list 2: different band */
Oliver Smitha6773042022-10-24 12:56:30 +020012261 { rxlev := 0, bcch_freq := 1, bsic := 13 }, /* ARFCN 200, band 850, LAC 97 */
12262 { rxlev := 40, bcch_freq := 2, bsic := 14 }, /* ARFCN 1000, band 900, LAC 99 */
12263 { rxlev := 0, bcch_freq := 3, bsic := 11 } /* ARFCN 0, band 900, LAC 96 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012264 };
12265 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
12266 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
12267 l3_mr, 0));
12268
12269 /* Expect a handover to the third entry. If the BSC parsed the report
Oliver Smitha6773042022-10-24 12:56:30 +020012270 * correctly, the third entry has LAC 99. */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012271 var template BSSMAP_FIELD_CellIdentificationList cid_list := {
Oliver Smitha6773042022-10-24 12:56:30 +020012272 cIl_LAC := { ts_BSSMAP_CI_LAC(99) }
Oliver Smithc9a5f532022-10-21 11:32:23 +020012273 };
12274 alt {
12275 [] BSSAP.receive(tr_BSSMAP_HandoverRequired(cid_list := cid_list)) {
12276 setverdict(pass);
12277 }
12278 [] BSSAP.receive(tr_BSSMAP_HandoverRequired()) {
12279 setverdict(fail, "Handover has unexpected LAC in Cell Identification List. The BSC probably"
12280 & " didn't parse the multi-band measurement report correctly.");
12281 }
12282 }
12283
12284 f_ho_out_of_this_bsc(skip_meas_rep := true);
12285}
12286testcase TC_ho_meas_rep_multi_band() runs on test_CT {
12287 /* Verify that the BSC parses the measurement report correctly when
12288 * neighbors in multiple bands are configured (OS#5717). See
12289 * gsm_arfcn2band_rc() in libosmocore src/gsm/gsm_utils.c for the
12290 * ARFCN -> band mapping. The MS is connected to band 1800. */
12291 var MSC_ConnHdlr vc_conn;
12292
12293 f_init_vty();
12294 f_bts_0_cfg(BSCVTY,
12295 {"neighbor-list mode automatic",
12296 "handover 1",
12297 "handover algorithm 2",
12298 "handover2 window rxlev averaging 1",
12299 "no neighbors",
12300 "neighbor lac 99 arfcn 1000 bsic any", /* band 900 */
12301 "neighbor lac 98 arfcn 800 bsic any", /* band 1800 */
12302 "neighbor lac 97 arfcn 200 bsic any", /* band 850 */
Oliver Smitha6773042022-10-24 12:56:30 +020012303 "neighbor lac 96 arfcn 0 bsic any"}); /* band 900 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012304 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
12305
12306 f_init(1, true);
12307 f_sleep(1.0);
12308
12309 f_ctrs_bsc_and_bts_handover_init();
12310
12311 vc_conn := f_start_handler(refers(f_tc_ho_meas_rep_multi_band));
12312 vc_conn.done;
12313
12314 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
12315 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
12316 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
12317 f_ctrs_bsc_and_bts_add(0, "handover:completed");
12318 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
12319 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
12320 f_ctrs_bsc_and_bts_verify();
12321 f_shutdown_helper(ho := true);
12322}
12323
Harald Welte28d943e2017-11-25 15:00:50 +010012324control {
Harald Welte898113b2018-01-31 18:32:21 +010012325 /* CTRL interface testing */
Harald Welte4003d112017-12-09 22:35:39 +010012326 execute( TC_ctrl_msc_connection_status() );
Stefan Sperlingb041b3d2018-01-03 17:14:55 +010012327 execute( TC_ctrl_msc0_connection_status() );
Neels Hofmeyrf65ce872021-09-23 18:40:10 +020012328 /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
12329 * these in the AoIP test suite. */
12330 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12331 execute( TC_stat_num_msc_connected_1() );
12332 execute( TC_stat_num_msc_connected_2() );
12333 execute( TC_stat_num_msc_connected_3() );
12334 }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020012335 execute( TC_stat_num_bts_connected_1() );
12336 execute( TC_stat_num_bts_connected_2() );
12337 execute( TC_stat_num_bts_connected_3() );
Harald Welte96c94412017-12-09 03:12:45 +010012338 execute( TC_ctrl() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012339 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +020012340 execute( TC_ctrl_location() );
12341 }
Harald Welte898113b2018-01-31 18:32:21 +010012342
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012343 execute( TC_si_default() );
Neels Hofmeyr66aeba42020-07-06 02:21:21 +020012344 execute( TC_si2quater_2_earfcns() );
12345 execute( TC_si2quater_3_earfcns() );
12346 execute( TC_si2quater_4_earfcns() );
12347 execute( TC_si2quater_5_earfcns() );
12348 execute( TC_si2quater_6_earfcns() );
Neels Hofmeyrad132f22020-07-08 02:20:16 +020012349 execute( TC_si2quater_12_earfcns() );
12350 execute( TC_si2quater_23_earfcns() );
12351 execute( TC_si2quater_32_earfcns() );
12352 execute( TC_si2quater_33_earfcns() );
12353 execute( TC_si2quater_42_earfcns() );
12354 execute( TC_si2quater_48_earfcns() );
12355 execute( TC_si2quater_49_earfcns() );
Pau Espin Pedrol85a84432020-07-20 18:45:03 +020012356 execute( TC_si_acc_rotate() );
Alexander Couzens4ad3a352020-09-10 22:29:12 +020012357 execute( TC_si_acc_ramp_rotate() );
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012358
Harald Welte898113b2018-01-31 18:32:21 +010012359 /* RSL DCHAN Channel ACtivation / Deactivation */
Harald Welteae026692017-12-09 01:03:01 +010012360 execute( TC_chan_act_noreply() );
Harald Welte4003d112017-12-09 22:35:39 +010012361 execute( TC_chan_act_counter() );
Harald Welteae026692017-12-09 01:03:01 +010012362 execute( TC_chan_act_ack_noest() );
Philipp Maier9c60a622020-07-09 15:08:46 +020012363 execute( TC_chan_act_ack_noest_emerg() );
Philipp Maier606f07d2020-08-12 17:21:58 +020012364 execute( TC_chan_rqd_emerg_deny() );
Harald Welteae026692017-12-09 01:03:01 +010012365 execute( TC_chan_act_ack_est_ind_noreply() );
12366 execute( TC_chan_act_ack_est_ind_refused() );
Harald Welte618ef642017-12-14 14:58:20 +010012367 execute( TC_chan_act_nack() );
Harald Welte799c97b2017-12-14 17:50:30 +010012368 execute( TC_chan_exhaustion() );
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +070012369 execute( TC_chan_deact_silence() );
Harald Welte4003d112017-12-09 22:35:39 +010012370 execute( TC_chan_rel_rll_rel_ind() );
12371 execute( TC_chan_rel_conn_fail() );
12372 execute( TC_chan_rel_hard_clear() );
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +020012373 execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
12374 execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
Harald Welte99787102019-02-04 10:41:36 +010012375 execute( TC_chan_rel_hard_clear_csfb() );
Harald Welted8c36cd2017-12-09 23:05:31 +010012376 execute( TC_chan_rel_hard_rlsd() );
Harald Welte550daf92018-06-11 19:22:13 +020012377 execute( TC_chan_rel_hard_rlsd_ms_dead() );
Harald Welte85804d42017-12-10 14:11:58 +010012378 execute( TC_chan_rel_a_reset() );
Pau Espin Pedrolc675b612020-01-09 19:55:40 +010012379 execute( TC_chan_rel_sccp_tiar_timeout() );
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +020012380 execute( TC_chan_rel_rr_cause() );
Harald Welte6f521d82017-12-11 19:52:02 +010012381
Harald Weltecfe2c962017-12-15 12:09:32 +010012382 execute( TC_outbound_connect() );
Harald Welte898113b2018-01-31 18:32:21 +010012383
12384 /* Assignment related */
Harald Welte16a4adf2017-12-14 18:54:01 +010012385 execute( TC_assignment_cic_only() );
Harald Welte235ebf12017-12-15 14:18:16 +010012386 execute( TC_assignment_csd() );
12387 execute( TC_assignment_ctm() );
12388 execute( TC_assignment_sign() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012389 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12390 execute( TC_assignment_aoip_tla_v6() );
12391 }
Harald Welte235ebf12017-12-15 14:18:16 +010012392 execute( TC_assignment_fr_a5_0() );
12393 execute( TC_assignment_fr_a5_1() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012394 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte8f67d1d2018-05-25 20:38:42 +020012395 execute( TC_assignment_fr_a5_1_codec_missing() );
12396 }
Harald Welte235ebf12017-12-15 14:18:16 +010012397 execute( TC_assignment_fr_a5_3() );
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +020012398 execute( TC_assignment_fr_a5_4() );
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +020012399 execute( TC_assignment_fr_a5_4_fail() );
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +020012400 execute( TC_assignment_fr_a5_not_sup() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012401 execute( TC_ciph_mode_a5_0() );
12402 execute( TC_ciph_mode_a5_1() );
Oliver Smith50b98122021-07-09 15:00:28 +020012403 execute( TC_ciph_mode_a5_2_0() );
Oliver Smith1dff88d2021-07-09 08:45:51 +020012404 execute( TC_ciph_mode_a5_2_1() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012405 execute( TC_ciph_mode_a5_3() );
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +020012406 execute( TC_ciph_mode_a5_4() );
Harald Welte16a4adf2017-12-14 18:54:01 +010012407
Harald Welte60aa5762018-03-21 19:33:13 +010012408 execute( TC_assignment_codec_fr() );
Neels Hofmeyr559d5d02021-04-16 16:50:49 +020012409 execute( TC_assignment_codec_fr_by_mode_modify() );
Harald Welte60aa5762018-03-21 19:33:13 +010012410 execute( TC_assignment_codec_hr() );
12411 execute( TC_assignment_codec_efr() );
12412 execute( TC_assignment_codec_amr_f() );
12413 execute( TC_assignment_codec_amr_h() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012414
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012415 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier8a581d22019-03-26 18:32:48 +010012416 execute( TC_assignment_codec_amr_f_S1() );
12417 execute( TC_assignment_codec_amr_h_S1() );
12418 execute( TC_assignment_codec_amr_f_S124() );
12419 execute( TC_assignment_codec_amr_h_S124() );
12420 execute( TC_assignment_codec_amr_f_S0() );
12421 execute( TC_assignment_codec_amr_f_S02() );
12422 execute( TC_assignment_codec_amr_f_S024() );
12423 execute( TC_assignment_codec_amr_f_S0247() );
12424 execute( TC_assignment_codec_amr_h_S0() );
12425 execute( TC_assignment_codec_amr_h_S02() );
12426 execute( TC_assignment_codec_amr_h_S024() );
12427 execute( TC_assignment_codec_amr_h_S0247() );
12428 execute( TC_assignment_codec_amr_f_S01234567() );
12429 execute( TC_assignment_codec_amr_f_S0234567() );
12430 execute( TC_assignment_codec_amr_f_zero() );
12431 execute( TC_assignment_codec_amr_f_unsupp() );
12432 execute( TC_assignment_codec_amr_h_S7() );
Neels Hofmeyr21863562020-11-26 00:34:33 +000012433 execute( TC_assignment_codec_amr_f_start_mode_auto() );
12434 execute( TC_assignment_codec_amr_h_start_mode_auto() );
Neels Hofmeyr3eb94562020-11-26 02:40:26 +000012435 execute( TC_assignment_codec_amr_f_start_mode_4() );
12436 execute( TC_assignment_codec_amr_h_start_mode_4() );
Neels Hofmeyr454d7922020-11-26 02:24:57 +000012437 execute( TC_assignment_codec_amr_startmode_cruft() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012438 }
Harald Welte60aa5762018-03-21 19:33:13 +010012439
Philipp Maierac09bfc2019-01-08 13:41:39 +010012440 execute( TC_assignment_codec_fr_exhausted_req_hr() );
12441 execute( TC_assignment_codec_fr_exhausted_req_fr() );
12442 execute( TC_assignment_codec_fr_exhausted_req_fr_hr() );
12443 execute( TC_assignment_codec_fr_exhausted_req_hr_fr() );
12444 execute( TC_assignment_codec_hr_exhausted_req_fr() );
12445 execute( TC_assignment_codec_hr_exhausted_req_hr() );
12446 execute( TC_assignment_codec_hr_exhausted_req_hr_fr() );
12447 execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
12448 execute( TC_assignment_codec_req_hr_fr() );
12449 execute( TC_assignment_codec_req_fr_hr() );
Pau Espin Pedrol14475352021-07-22 15:48:16 +020012450 execute( TC_assignment_sdcch_exhausted_req_signalling() );
12451 execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
12452 execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
Philipp Maierac09bfc2019-01-08 13:41:39 +010012453
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +020012454 execute( TC_assignment_codec_hr_osmux_on() );
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +020012455 execute( TC_assignment_osmux() );
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020012456 execute( TC_assignment_osmux_cn() );
12457 execute( TC_assignment_osmux_bts() );
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +020012458
Harald Welte898113b2018-01-31 18:32:21 +010012459 /* RLL Establish Indication on inactive DCHAN / SAPI */
Harald Welte5cd20ed2017-12-13 21:03:20 +010012460 execute( TC_rll_est_ind_inact_lchan() );
12461 execute( TC_rll_est_ind_inval_sapi1() );
12462 execute( TC_rll_est_ind_inval_sapi3() );
12463 execute( TC_rll_est_ind_inval_sacch() );
12464
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +070012465 /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
12466 execute( TC_tch_dlci_link_id_sapi() );
12467
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012468 /* SAPI N Reject triggered by RLL establishment failures */
12469 execute( TC_rll_rel_ind_sapi_n_reject() );
12470 execute( TC_rll_err_ind_sapi_n_reject() );
12471 execute( TC_rll_timeout_sapi_n_reject() );
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +070012472 execute( TC_rll_sapi_n_reject_dlci_cc() );
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012473
Harald Welte898113b2018-01-31 18:32:21 +010012474 /* Paging related tests */
Harald Welte6f521d82017-12-11 19:52:02 +010012475 execute( TC_paging_imsi_nochan() );
12476 execute( TC_paging_tmsi_nochan() );
12477 execute( TC_paging_tmsi_any() );
12478 execute( TC_paging_tmsi_sdcch() );
12479 execute( TC_paging_tmsi_tch_f() );
12480 execute( TC_paging_tmsi_tch_hf() );
12481 execute( TC_paging_imsi_nochan_cgi() );
12482 execute( TC_paging_imsi_nochan_lac_ci() );
12483 execute( TC_paging_imsi_nochan_ci() );
12484 execute( TC_paging_imsi_nochan_lai() );
12485 execute( TC_paging_imsi_nochan_lac() );
12486 execute( TC_paging_imsi_nochan_all() );
Harald Welte751d3eb2018-01-31 15:51:06 +010012487 execute( TC_paging_imsi_nochan_plmn_lac_rnc() );
12488 execute( TC_paging_imsi_nochan_rnc() );
12489 execute( TC_paging_imsi_nochan_lac_rnc() );
12490 execute( TC_paging_imsi_nochan_lacs() );
12491 execute( TC_paging_imsi_nochan_lacs_empty() );
Stefan Sperling049a86e2018-03-20 15:51:00 +010012492 execute( TC_paging_imsi_nochan_cgi_unknown_cid() );
Harald Welte10985002017-12-12 09:29:15 +010012493 execute( TC_paging_imsi_a_reset() );
Harald Weltee65d40e2017-12-13 00:09:06 +010012494 execute( TC_paging_imsi_load() );
Philipp Maier779a7922018-02-16 11:00:37 +010012495 execute( TC_paging_counter() );
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +010012496 execute( TC_paging_resp_unsol() );
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +020012497 execute( TC_paging_500req() );
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +020012498 execute( TC_paging_450req_no_paging_load_ind() );
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +010012499 execute( TC_paging_imsi_nochan_ci_resp_invalid_mi() );
Harald Welte4e9b9cc2017-12-14 18:31:02 +010012500
12501 execute( TC_rsl_drop_counter() );
Stefan Sperling830dc9d2018-02-12 21:08:28 +010012502 execute( TC_rsl_unknown_unit_id() );
12503
12504 execute( TC_oml_unknown_unit_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012505
12506 execute( TC_classmark() );
Harald Welteeddf0e92020-06-21 19:42:15 +020012507 execute( TC_common_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012508 execute( TC_unsol_ass_fail() );
Harald Welteea99a002018-01-31 20:46:43 +010012509 execute( TC_unsol_ass_compl() );
Harald Weltefbf9b5e2018-01-31 20:41:23 +010012510 execute( TC_unsol_ho_fail() );
Harald Weltee3bd6582018-01-31 22:51:25 +010012511 execute( TC_err_82_short_msg() );
Harald Weltee9e02e42018-01-31 23:36:25 +010012512 execute( TC_err_84_unknown_msg() );
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012513
Harald Welte261af4b2018-02-12 21:20:39 +010012514 execute( TC_ho_int() );
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +020012515 execute( TC_ho_int_a5_0() );
12516 execute( TC_ho_int_a5_1() );
12517 execute( TC_ho_int_a5_3() );
12518 execute( TC_ho_int_a5_4() );
Neels Hofmeyr5f144212020-11-03 15:41:58 +000012519 execute( TC_ho_int_radio_link_failure() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012520
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012521 /* TC_ho_out_of_this_bsc is run last, see comment below */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +020012522 execute( TC_ho_out_fail_no_msc_response() );
12523 execute( TC_ho_out_fail_rr_ho_failure() );
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +020012524 execute( TC_ho_out_fail_no_result_after_ho_cmd() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012525
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012526 execute( TC_ho_into_this_bsc() );
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +020012527 execute( TC_ho_into_this_bsc_a5_0() );
12528 execute( TC_ho_into_this_bsc_a5_1() );
12529 execute( TC_ho_into_this_bsc_a5_3() );
12530 execute( TC_ho_into_this_bsc_a5_4() );
Neels Hofmeyr93182e02022-02-17 21:59:07 +010012531 execute( TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() );
12532 execute( TC_ho_into_this_bsc_a5_1_3() );
Neels Hofmeyr907b23b2022-02-17 21:58:47 +010012533 execute( TC_ho_into_this_bsc_a5_mismatch() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012534 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12535 execute( TC_ho_into_this_bsc_tla_v6() );
12536 }
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +020012537 execute( TC_srvcc_eutran_to_geran() );
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +030012538 execute( TC_srvcc_eutran_to_geran_a5_3() );
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +010012539 execute( TC_srvcc_eutran_to_geran_src_sai() );
Pau Espin Pedrol35801c32021-04-19 13:03:20 +020012540 execute( TC_srvcc_eutran_to_geran_ho_out() );
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +020012541 execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
12542 execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012543 execute( TC_ho_in_fail_msc_clears() );
12544 execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
12545 execute( TC_ho_in_fail_no_detect() );
12546 execute( TC_ho_in_fail_no_detect2() );
Oliver Smith7a8594a2023-02-13 14:30:49 +010012547 execute( TC_ho_in_fail_mgw_mdcx_timeout() );
Oliver Smith4eed06f2023-02-15 15:43:19 +010012548 execute( TC_ho_in_fail_ipa_crcx_timeout() );
Neels Hofmeyra23f3b12022-03-02 19:57:12 +010012549 execute( TC_ho_into_this_bsc_sccp_cr_without_bssap() );
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012550
Neels Hofmeyr91401012019-07-11 00:42:35 +020012551 execute( TC_ho_neighbor_config_1() );
12552 execute( TC_ho_neighbor_config_2() );
12553 execute( TC_ho_neighbor_config_3() );
12554 execute( TC_ho_neighbor_config_4() );
12555 execute( TC_ho_neighbor_config_5() );
12556 execute( TC_ho_neighbor_config_6() );
12557 execute( TC_ho_neighbor_config_7() );
12558
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012559 execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() );
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010012560 execute( TC_bssmap_clear_does_not_cause_bssmap_reset() );
Neels Hofmeyrfd445c32018-03-09 15:39:31 +010012561 execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() );
Harald Welte94e0c342018-04-07 11:33:23 +020012562
12563 execute( TC_dyn_pdch_ipa_act_deact() );
12564 execute( TC_dyn_pdch_ipa_act_nack() );
12565 execute( TC_dyn_pdch_osmo_act_deact() );
12566 execute( TC_dyn_pdch_osmo_act_nack() );
Pau Espin Pedrol37a4c152021-11-16 19:02:23 +010012567 execute( TC_dyn_ts_sdcch8_act_deact() );
12568 execute( TC_dyn_ts_sdcch8_all_subslots_used() );
12569 execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
12570 execute( TC_dyn_ts_sdcch8_act_nack() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012571
Stefan Sperling0796a822018-10-05 13:01:39 +020012572 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +020012573 execute( TC_chopped_ipa_payload() );
Stefan Sperling0796a822018-10-05 13:01:39 +020012574
Pau Espin Pedrol8f773632019-11-05 11:46:53 +010012575 /* Power control related */
12576 execute( TC_assignment_verify_ms_power_params_ie() );
Vadim Yanitskiy4b233042021-06-30 00:58:43 +020012577 execute( TC_c0_power_red_mode() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012578
12579 /* MSC pooling */
12580 /* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
12581 * RESET->RESET-ACK is unconditionally negotiated for all configured MSCs, they always all appear as connected
12582 * to osmo-bsc. The MSC pooling tests however require disconnecting selected MSCs, and hence don't work out as
12583 * intended on SCCPlite. So for now, run these only for SCCP/M3UA. */
12584 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12585 execute( TC_mscpool_L3Compl_on_1_msc() );
12586 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
12587 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
12588 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
12589 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
12590 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
12591 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
12592 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
12593 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
12594 execute( TC_mscpool_paging_and_response_imsi() );
12595 execute( TC_mscpool_paging_and_response_tmsi() );
12596 execute( TC_mscpool_no_allow_attach_round_robin() );
12597 execute( TC_mscpool_no_allow_attach_valid_nri() );
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +020012598
12599 execute( TC_mscpool_sccp_n_pcstate_detaches_msc() );
Neels Hofmeyr38632aa2023-04-05 03:50:51 +020012600 execute( TC_mscpool_sccp_n_pcstate_attaches_msc() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012601 }
12602
Harald Welte99f3ca02018-06-14 13:40:29 +020012603 execute( TC_early_conn_fail() );
12604 execute( TC_late_conn_fail() );
Oliver Smithaf03bef2021-08-24 15:34:51 +020012605 execute( TC_stats_conn_fail() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012606
Philipp Maier783681c2020-07-16 16:47:06 +020012607 /* Emergency call handling (deny / allow) */
12608 execute( TC_assignment_emerg_setup_allow() );
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +010012609 execute( TC_assignment_emerg_setup_allow_imei() );
Philipp Maier783681c2020-07-16 16:47:06 +020012610 execute( TC_assignment_emerg_setup_deny_msc() );
12611 execute( TC_assignment_emerg_setup_deny_bts() );
Philipp Maier82812002020-08-13 18:48:27 +020012612 execute( TC_emerg_premption() );
12613
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +070012614 /* Frequency hopping parameters handling */
12615 execute( TC_fh_params_chan_activ() );
12616 execute( TC_fh_params_imm_ass() );
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070012617 execute( TC_fh_params_assignment_cmd() );
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070012618 execute( TC_fh_params_handover_cmd() );
Vadim Yanitskiyca974032020-09-01 07:20:39 +070012619 execute( TC_fh_params_si4_cbch() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012620
12621 if (mp_enable_lcs_tests) {
12622 execute( TC_lcs_loc_req_for_active_ms() );
12623 execute( TC_lcs_loc_req_for_active_ms_ta_req() );
12624 execute( TC_lcs_loc_req_for_idle_ms() );
12625 execute( TC_lcs_loc_req_no_subscriber() );
12626 execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
12627 execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
12628 execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
12629 execute( TC_cm_service_during_lcs_loc_req() );
12630 execute( TC_ho_during_lcs_loc_req() );
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020012631 execute( TC_emerg_call_and_lcs_loc_req() );
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020012632 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() );
12633 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012634 }
Neels Hofmeyrbf037052020-10-28 22:52:02 +000012635
12636 execute( TC_no_msc() );
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000012637
12638 execute( TC_refuse_chan_act_to_vamos() );
12639 execute( TC_refuse_mode_modif_to_vamos() );
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000012640
12641 execute( TC_reassignment_fr() );
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020012642
12643 execute( TC_cm_reestablishment() );
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020012644
12645 execute( TC_imm_ass_post_chan_ack() );
12646 execute( TC_imm_ass_pre_chan_ack() );
Neels Hofmeyr23158742021-09-07 19:08:07 +020012647 execute( TC_imm_ass_pre_ts_ack() );
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020012648 execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020012649 execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020012650
12651 execute( TC_ctrl_trx_rf_locked() );
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012652
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012653 execute( TC_ratectr_all_available_allocated() );
12654 execute( TC_ratectr_all_available_allocated_dyn() );
12655
Neels Hofmeyrb7581872021-11-07 14:02:49 +010012656 execute( TC_cm_serv_rej() );
12657
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012658 execute( TC_lost_sdcch_during_assignment() );
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012659
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012660 /* Channel allocator */
12661 execute( TC_chan_alloc_algo_ascending() );
12662 execute( TC_chan_alloc_algo_descending() );
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012663 execute( TC_chan_alloc_algo_ass_dynamic() );
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012664
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012665 /* MGW pool */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +010012666 execute( TC_mgwpool_all_used() );
12667 execute( TC_mgwpool_blocked_not_used() );
12668 execute( TC_mgwpool_pin_bts() );
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012669
Oliver Smithc9a5f532022-10-21 11:32:23 +020012670 execute( TC_ho_meas_rep_multi_band() );
12671
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012672 /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
12673 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
12674 execute( TC_ho_out_of_this_bsc() );
Harald Welte28d943e2017-11-25 15:00:50 +010012675}
12676
12677}