blob: 8dcff83a28aac2408e61a4fc272be2ae229f9b5d [file] [log] [blame]
Harald Welte28d943e2017-11-25 15:00:50 +01001module BSC_Tests {
2
Harald Welte21b46bd2017-12-17 19:46:32 +01003/* Integration Tests for OsmoBSC
Harald Weltea0630032018-03-20 21:09:55 +01004 * (C) 2017-2018 by Harald Welte <laforge@gnumonks.org>
Harald Welte21b46bd2017-12-17 19:46:32 +01005 * All rights reserved.
6 *
7 * Released under the terms of GNU General Public License, Version 2 or
8 * (at your option) any later version.
9 *
Harald Welte34b5a952019-05-27 11:54:11 +020010 * SPDX-License-Identifier: GPL-2.0-or-later
11 *
Harald Welte21b46bd2017-12-17 19:46:32 +010012 * This test suite tests OsmoBSC while emulating both multiple BTS + MS as
13 * well as the MSC. See README for more details.
14 *
15 * There are test cases that run in so-called 'handler mode' and test cases
16 * that run directly on top of the BSSAP and RSL CodecPorts. The "handler mode"
17 * tests abstract the multiplexing/demultiplexing of multiple SCCP connections
18 * and/or RSL channels and are hence suitable for higher-level test cases, while
19 * the "raw" tests directly on top of the CodecPorts are more suitable for lower-
20 * level testing.
21 */
22
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +020023friend module BSC_Tests_VAMOS;
Vadim Yanitskiy5eb06a32022-06-23 18:39:46 +070024friend module BSC_Tests_CBSP;
Vadim Yanitskiy3cc065b2023-01-06 21:35:12 +070025friend module BSC_Tests_LCLS;
Harald Welte801ed1a2023-04-30 15:07:00 +100026friend module BSC_Tests_ASCI;
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +020027
Neels Hofmeyr4f118412020-06-04 15:25:10 +020028import from Misc_Helpers all;
Harald Welte4003d112017-12-09 22:35:39 +010029import from General_Types all;
Harald Welte28d943e2017-11-25 15:00:50 +010030import from Osmocom_Types all;
Harald Welteae026692017-12-09 01:03:01 +010031import from GSM_Types all;
Harald Welte28d943e2017-11-25 15:00:50 +010032import from IPL4asp_Types all;
33
Harald Welte6f521d82017-12-11 19:52:02 +010034import from BSSAP_Types all;
Harald Welte6811d102019-04-14 22:23:14 +020035import from RAN_Adapter all;
Harald Welte47cd0e32020-08-21 12:39:11 +020036import from BSSAP_LE_Adapter all;
37import from BSSAP_LE_CodecPort all;
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020038import from BSSAP_LE_Types all;
39import from BSSLAP_Types all;
Harald Welteae026692017-12-09 01:03:01 +010040import from BSSAP_CodecPort all;
41import from BSSMAP_Templates all;
Harald Welte28d943e2017-11-25 15:00:50 +010042import from IPA_Emulation all;
Stefan Sperling830dc9d2018-02-12 21:08:28 +010043import from IPA_CodecPort all;
Harald Welteae026692017-12-09 01:03:01 +010044import from IPA_Types all;
Stefan Sperling0796a822018-10-05 13:01:39 +020045import from IPA_Testing all;
Harald Welteae026692017-12-09 01:03:01 +010046import from RSL_Types all;
Harald Welte624f9632017-12-16 19:26:04 +010047import from RSL_Emulation all;
Daniel Willmann191e0d92018-01-17 12:44:35 +010048import from MGCP_Emulation all;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010049import from MGCP_Templates all;
50import from MGCP_Types all;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +020051import from MGCP_CodecPort all;
Harald Welte28d943e2017-11-25 15:00:50 +010052
Harald Welte96c94412017-12-09 03:12:45 +010053import from Osmocom_CTRL_Functions all;
Harald Weltea5d2ab22017-12-09 14:21:42 +010054import from Osmocom_CTRL_Types all;
Harald Welteffe55fc2018-01-17 22:39:54 +010055import from Osmocom_CTRL_Adapter all;
Harald Welte96c94412017-12-09 03:12:45 +010056
Daniel Willmannebdecc02020-08-12 15:30:17 +020057import from StatsD_Types all;
58import from StatsD_CodecPort all;
59import from StatsD_CodecPort_CtrlFunct all;
60import from StatsD_Checker all;
61
Harald Weltebc03c762018-02-12 18:09:38 +010062import from Osmocom_VTY_Functions all;
63import from TELNETasp_PortType all;
64
Harald Welte6f521d82017-12-11 19:52:02 +010065import from MobileL3_CommonIE_Types all;
Harald Weltee3bd6582018-01-31 22:51:25 +010066import from MobileL3_Types all;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010067import from MobileL3_RRM_Types all;
Harald Welte6f521d82017-12-11 19:52:02 +010068import from L3_Templates all;
69import from GSM_RR_Types all;
70
Stefan Sperlingc307e682018-06-14 15:15:46 +020071import from SCCP_Templates all;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010072import from BSSMAP_Templates all;
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020073import from BSSMAP_LE_Templates all;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010074
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010075import from SCCPasp_Types all;
76
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020077import from GSM_SystemInformation all;
78import from GSM_RestOctets all;
Neels Hofmeyrad132f22020-07-08 02:20:16 +020079import from TCCConversion_Functions all;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020080
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060081const integer NUM_TRX := 4;
Harald Welte5d1a2202017-12-13 19:51:29 +010082const integer NUM_BTS := 3;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020083const integer NUM_BTS_CFG := 4; /* we have 4 BTS in the osmo-bsc.cfg (for inter-BSC HO tests) but use only 3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060084const integer NUM_TRX_CFG := 1; /* we support up to 4 TRX per BTS, but have only 1 TRX per BTS in osmo-bsc.cfg */
Neels Hofmeyrf246a922020-05-13 02:27:10 +020085const integer NUM_MSC := 3;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020086const integer NUM_MGW := 2;
Harald Welteae026692017-12-09 01:03:01 +010087const float T3101_MAX := 12.0;
Harald Welte28d943e2017-11-25 15:00:50 +010088
Harald Welte799c97b2017-12-14 17:50:30 +010089/* make sure to sync this with the osmo-bts.cfg you're using */
Philipp Maiercb6cc482018-03-26 13:08:00 +020090const integer NUM_TCHH_PER_BTS := 2;
91const integer NUM_TCHF_PER_BTS := 4;
Neels Hofmeyr74083c22020-07-29 00:43:01 +020092const integer NUM_SDCCH_PER_BTS := 3;
Harald Welte799c97b2017-12-14 17:50:30 +010093
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060094friend type record BtsTrxIdx {
95 uint8_t bts,
96 uint8_t trx
97}
98
99private type record BtsParams {
100 integer trx_num,
101 integer tsc
102}
103
Neels Hofmeyrbf720202021-10-02 12:58:24 +0200104/* Default Training Sequence Code expected for bts[i]:
105 * BTS 0 has BSIC 10 (and no explicit timeslot training_sequence_code config), so expecting TSC = (BSIC & 7) = 2.
106 * BTS 1 has BSIC 11, TSC = (BSIC & 7) = 3.
107 * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
108 * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
109 */
Harald Welte801ed1a2023-04-30 15:07:00 +1000110friend const BtsParams c_BtsParams[NUM_BTS_CFG] := {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600111 /* BTS0 */ { trx_num := 1, tsc := 2 },
112 /* BTS1 */ { trx_num := 1, tsc := 3 },
Vadim Yanitskiy7a3d2932022-05-29 20:37:46 +0600113 /* BTS2 */ { trx_num := 4, tsc := 4 },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600114 /* BTS3 */ { trx_num := 1, tsc := 4 }
Neels Hofmeyrbf720202021-10-02 12:58:24 +0200115}
Harald Welte4003d112017-12-09 22:35:39 +0100116
Vadim Yanitskiy59494702022-09-14 15:29:04 +0700117private const RSL_IE_Body c_mr_conf_5_90 :=
Pau Espin Pedrolf7634dc2022-09-02 17:56:00 +0200118 valueof(RSL_IE_Body:{multirate_cfg := ts_RSL_MultirateCfg(true, 0, '00000100'B /* 5,90k */)});
119
Harald Welte21b46bd2017-12-17 19:46:32 +0100120/* per-BTS state which we keep */
Harald Welte96c94412017-12-09 03:12:45 +0100121type record BTS_State {
Harald Welte21b46bd2017-12-17 19:46:32 +0100122 /* component reference to the IPA_Client component used for RSL */
Harald Weltea5d2ab22017-12-09 14:21:42 +0100123 IPA_Client rsl
Harald Welte96c94412017-12-09 03:12:45 +0100124}
125
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200126/* Default list of counters for an 'msc' entity. */
127const CounterNameVals counternames_msc_mscpool := {
128 { "mscpool:subscr:new", 0 },
129 { "mscpool:subscr:known", 0 },
130 { "mscpool:subscr:reattach", 0 },
131 { "mscpool:subscr:attach_lost", 0 },
132 { "mscpool:subscr:paged", 0 }
133};
134
Neels Hofmeyrbf037052020-10-28 22:52:02 +0000135/* List of global mscpool counters, not related to a specific 'msc' entity. */
136const CounterNameVals counternames_bsc_mscpool := {
137 { "mscpool:subscr:no_msc", 0 }
138};
139
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000140/* Default list of counters for 'bsc' and 'bts' entities. */
141const CounterNameVals counternames_bsc_bts_handover := {
142 { "assignment:attempted", 0 },
143 { "assignment:completed", 0 },
144 { "assignment:stopped", 0 },
145 { "assignment:no_channel", 0 },
146 { "assignment:timeout", 0 },
147 { "assignment:failed", 0 },
148 { "assignment:error", 0 },
149
150 { "handover:attempted", 0 },
151 { "handover:completed", 0 },
152 { "handover:stopped", 0 },
153 { "handover:no_channel", 0 },
154 { "handover:timeout", 0 },
155 { "handover:failed", 0 },
156 { "handover:error", 0 },
157
158 { "intra_cell_ho:attempted", 0 },
159 { "intra_cell_ho:completed", 0 },
160 { "intra_cell_ho:stopped", 0 },
161 { "intra_cell_ho:no_channel", 0 },
162 { "intra_cell_ho:timeout", 0 },
163 { "intra_cell_ho:failed", 0 },
164 { "intra_cell_ho:error", 0 },
165
166 { "intra_bsc_ho:attempted", 0 },
167 { "intra_bsc_ho:completed", 0 },
168 { "intra_bsc_ho:stopped", 0 },
169 { "intra_bsc_ho:no_channel", 0 },
170 { "intra_bsc_ho:timeout", 0 },
171 { "intra_bsc_ho:failed", 0 },
172 { "intra_bsc_ho:error", 0 },
173
174 { "interbsc_ho_out:attempted", 0 },
175 { "interbsc_ho_out:completed", 0 },
176 { "interbsc_ho_out:stopped", 0 },
177 { "interbsc_ho_out:timeout", 0 },
178 { "interbsc_ho_out:failed", 0 },
179 { "interbsc_ho_out:error", 0 },
180
181 { "interbsc_ho_in:attempted", 0 },
182 { "interbsc_ho_in:completed", 0 },
183 { "interbsc_ho_in:stopped", 0 },
184 { "interbsc_ho_in:no_channel", 0 },
185 { "interbsc_ho_in:timeout", 0 },
186 { "interbsc_ho_in:failed", 0 },
187 { "interbsc_ho_in:error", 0 }
188};
189
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100190const CounterNameVals counternames_bts_handover := {
191 { "incoming_intra_bsc_ho:attempted", 0 },
192 { "incoming_intra_bsc_ho:completed", 0 },
193 { "incoming_intra_bsc_ho:stopped", 0 },
194 { "incoming_intra_bsc_ho:no_channel", 0 },
195 { "incoming_intra_bsc_ho:timeout", 0 },
196 { "incoming_intra_bsc_ho:failed", 0 },
197 { "incoming_intra_bsc_ho:error", 0 }
198};
199
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200200/* Set of all System Information received during one RSL port's startup.
201 * Note that some System Information may be sent on RSL, but lacking actual SI data, to indicate that the BTS should not
202 * broadcast that SI type. That will be reflected as 'omit' here.
203 */
204type record SystemInformationConfig {
205 SystemInformationType1 si1 optional,
206 SystemInformationType2 si2 optional,
207 SystemInformationType2bis si2bis optional,
208 SystemInformationType2ter si2ter optional,
Neels Hofmeyrad132f22020-07-08 02:20:16 +0200209 SI2quaterRestOctetsList si2quater optional,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200210 SystemInformationType3 si3 optional,
211 SystemInformationType4 si4 optional,
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100212 SystemInformationType13 si13 optional,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200213 SystemInformationType5 si5 optional,
214 SystemInformationType5bis si5bis optional,
215 SystemInformationType5ter si5ter optional,
216 SystemInformationType6 si6 optional
217};
218
219const SystemInformationConfig SystemInformationConfig_omit := {
220 si1 := omit,
221 si2 := omit,
222 si2bis := omit,
223 si2ter := omit,
224 si2quater := omit,
225 si3 := omit,
226 si4 := omit,
227 si13 := omit,
228 si5 := omit,
229 si5bis := omit,
230 si5ter := omit,
231 si6 := omit
232};
233
234/* tr_EUTRAN_CellDesc with defaults used in BSC_Tests.ttcn */
235template EUTRAN_CellDesc tr_EUTRAN_CellDesc_default(template (present) uint16_t e_arfcn := ?,
236 template uint3_t meas_bw := 3)
237:= tr_EUTRAN_CellDesc(e_arfcn := e_arfcn,
238 meas_bw_presence := '1'B,
239 meas_bw := meas_bw);
240
241/* tr_EUTRAN_NeighbourCells with defaults used in BSC_Tests.ttcn */
Harald Welte65e419a2020-08-21 12:38:33 +0200242template EUTRAN_NeighbourCells tr_EUTRAN_NeighbourCells_default(template (present) EUTRAN_CellDescs cell_desc_list := { tr_EUTRAN_CellDesc_default },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200243 template uint3_t prio := 3,
244 template (present) uint5_t thresh_high := 20,
245 template uint5_t thresh_low := 10,
246 template uint5_t qrxlevmin := 22)
247:= tr_EUTRAN_NeighbourCells(
248 cell_desc_list := cell_desc_list,
249 prio_presence := '1'B,
250 prio := prio,
251 thresh_high := thresh_high,
252 thresh_low_presence := '1'B,
253 thresh_low := thresh_low,
254 qrxlevmin_presence := '1'B,
255 qrxlevmin := qrxlevmin);
256
257template SystemInformationConfig SystemInformationConfig_default := {
258 si1 := {
259 cell_chan_desc := '8FB38000000000000000000000000000'O,
260 rach_control := {
261 max_retrans := RACH_MAX_RETRANS_7,
262 tx_integer := '1001'B,
263 cell_barr_access := false,
264 re_not_allowed := true,
265 acc := '0000010000000000'B
266 },
267 rest_octets := ?
268 },
269 si2 := {
270 bcch_freq_list := '00000000000000000000000000000000'O,
271 ncc_permitted := '11111111'B,
272 rach_control := {
273 max_retrans := RACH_MAX_RETRANS_7,
274 tx_integer := '1001'B,
275 cell_barr_access := false,
276 re_not_allowed := true,
277 acc := '0000010000000000'B
278 }
279 },
280 si2bis := omit,
281 si2ter := {
282 extd_bcch_freq_list := '8E320000000000000000000000000800'O,
283 rest_octets := ?
284 },
285 si2quater := {
286 tr_SI2quaterRestOctets_EUTRAN( repeated_neigh_cells := { tr_EUTRAN_NeighbourCells_default } )
287 },
288 si3 := {
289 cell_id := 0,
290 lai := {
291 mcc_mnc := '001F01'H,
292 lac := 1
293 },
294 ctrl_chan_desc := {
295 msc_r99 := true,
296 att := true,
297 bs_ag_blks_res := 1,
298 ccch_conf := CCHAN_DESC_1CCCH_COMBINED,
299 si22ind := false,
300 cbq3 := CBQ3_IU_MODE_NOT_SUPPORTED,
301 spare := '00'B,
302 bs_pa_mfrms := 3,
303 t3212 := 30
304 },
305 cell_options := {
306 dn_ind := false,
307 pwrc := false,
308 dtx := MS_SHALL_USE_UL_DTX,
309 radio_link_tout_div4 := 7
310 },
311 cell_sel_par := {
312 cell_resel_hyst_2dB := 2,
313 ms_txpwr_max_cch := 7,
314 acs := '0'B,
315 neci := true,
316 rxlev_access_min := 0
317 },
318 rach_control := {
319 max_retrans := RACH_MAX_RETRANS_7,
320 tx_integer := '1001'B,
321 cell_barr_access := false,
322 re_not_allowed := true,
323 acc := '0000010000000000'B
324 },
325 rest_octets := {
326 sel_params := {
327 presence := '0'B,
328 params := omit
329 },
330 pwr_offset := {
331 presence := '0'B,
332 offset := omit
333 },
334 si_2ter_ind := '1'B,
335 early_cm_ind := '0'B,
336 sched_where := {
337 presence := '0'B,
338 where := omit
339 },
340 gprs_ind := {
341 presence := '1'B,
342 ind := {
343 ra_colour := 0,
344 si13_pos := '0'B
345 }
346 },
347 umts_early_cm_ind := '1'B,
348 si2_quater_ind := {
349 presence := '1'B,
350 ind := '0'B
351 },
352 iu_mode_ind := omit,
353 si21_ind := {
354 presence := '0'B,
355 pos := omit
356 }
357 }
358 },
359 si4 := {
360 lai := {
361 mcc_mnc := '001F01'H,
362 lac := 1
363 },
364 cell_sel_par := {
365 cell_resel_hyst_2dB := 2,
366 ms_txpwr_max_cch := 7,
367 acs := '0'B,
368 neci := true,
369 rxlev_access_min := 0
370 },
371 rach_control := {
372 max_retrans := RACH_MAX_RETRANS_7,
373 tx_integer := '1001'B,
374 cell_barr_access := false,
375 re_not_allowed := true,
376 acc := '0000010000000000'B
377 },
Neels Hofmeyr74083c22020-07-29 00:43:01 +0200378 cbch_chan_desc := {
379 iei := '64'O,
380 v := {
381 chan_nr := {
382 u := {
383 sdcch4 := {
384 tag := '001'B,
385 sub_chan := 2
386 }
387 },
388 tn := 0
389 },
390 tsc := 2,
391 h := false,
392 arfcn := 871,
393 maio_hsn := omit
394 }
395 },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200396 cbch_mobile_alloc := omit,
397 rest_octets := {
398 sel_params := {
399 presence := '0'B,
400 params := omit
401 },
402 pwr_offset := {
403 presence := '0'B,
404 offset := omit
405 },
406 gprs_ind := {
407 presence := '1'B,
408 ind := {
409 ra_colour := 0,
410 si13_pos := '0'B
411 }
412 },
413 s_presence := '0'B,
414 s := omit
415 }
416 },
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100417 si13 := {
418 rest_octets := {
419 presence := '1'B,
420 bcch_change_mark := ?,
421 si_change_field := '0000'B,
422 presence2 := '0'B,
423 si13_change_mark := omit,
424 gprs_ma := omit,
425 zero := '0'B, /* PBCCH not present in cell */
426 rac := 0,
427 spgc_ccch_sup := '0'B,
428 priority_access_thr := '110'B,
429 network_control_order := '00'B,
430 gprs_cell_opts := {
431 nmo := '01'B,
432 t3168 := '011'B,
433 t3192 := '010'B,
434 drx_timer_max := '011'B,
435 access_burst_type := '0'B,
436 control_ack_type := '1'B,
437 bs_cv_max := 15,
438 pan_presence := '1'B,
439 pan_dec := 1,
440 pan_inc := 1,
441 pan_max := '111'B,
442 ext_info_presence := ?,
443 ext_info_length := *,
444 ext_info := *
445 },
446 gprs_pwr_ctrl_params := {
447 alpha := 0,
448 t_avg_w := '10000'B,
449 t_avg_t := '10000'B,
450 pc_meas_chan := '0'B,
451 n_avg_i := '1000'B
452 }
453 }
454 },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200455 si5 := {
456 bcch_freq_list := '10000000000000000000000000000000'O
457 },
458 si5bis := omit,
459 si5ter := {
460 extd_bcch_freq_list := '9E050020000000000000000000000000'O
461 },
462 si6 := {
463 cell_id := 0,
464 lai := {
465 mcc_mnc := '001F01'H,
466 lac := 1
467 },
468 cell_options := {
469 dtx_ext := '1'B,
470 pwrc := false,
471 dtx := '01'B,
472 radio_link_timeout := '0111'B
473 },
474 ncc_permitted := '11111111'B,
Vadim Yanitskiy348b07c2022-03-10 17:11:22 +0300475 rest_octets := {
476 pch_nch_info := ?,
477 vbs_vgcs_options := ?,
478 dtm_support := '0'B,
479 rac := omit,
480 max_lapdm := omit,
481 band_ind := '0'B /* C0 ARFCN indicates 1800 band */
482 }
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200483 }
484 };
485
486
487/* List of all the System Information received on all RSL ports */
488type record of SystemInformationConfig SystemInformationConfig_list;
489
490function f_sysinfo_dec_raw(inout SystemInformationConfig si, RSL_Message rsl)
491{
492 var RSL_IE_Body sysinfo_type_ie;
493 var RSL_IE_SysinfoType si_type;
494 var octetstring data;
495
496 if (f_rsl_find_ie(rsl, RSL_IE_SYSINFO_TYPE, sysinfo_type_ie) == false) {
497 setverdict(fail, "Cannot find RSL_IE_SYSINFO_TYPE");
498 mtc.stop;
499 }
500 si_type := sysinfo_type_ie.sysinfo_type;
501
502 if (rsl.msg_type == RSL_MT_BCCH_INFO) {
503 var RSL_IE_Body bcch_ie;
504 if (f_rsl_find_ie(rsl, RSL_IE_FULL_BCCH_INFO, bcch_ie)) {
505 data := bcch_ie.other.payload;
506 }
507 } else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
508 var RSL_IE_Body l3_ie;
509 if (f_rsl_find_ie(rsl, RSL_IE_L3_INFO, l3_ie)) {
510 data := l3_ie.l3_info.payload;
511 }
512 } else {
513 setverdict(fail, "Don't understand this System Information message");
514 mtc.stop;
515 }
516
517 var boolean handled := false;
518
519 if (rsl.msg_type == RSL_MT_BCCH_INFO) {
520 handled := true;
521
522 if (si_type == RSL_SYSTEM_INFO_1) {
523 if (not isbound(data)) {
524 si.si1 := omit;
525 } else {
526 si.si1 := dec_SystemInformation(data).payload.si1;
527 }
528 } else if (si_type == RSL_SYSTEM_INFO_2) {
529 if (not isbound(data)) {
530 si.si2 := omit;
531 } else {
532 si.si2 := dec_SystemInformation(data).payload.si2;
533 }
534 } else if (si_type == RSL_SYSTEM_INFO_2bis) {
535 if (not isbound(data)) {
536 si.si2bis := omit;
537 } else {
538 si.si2bis := dec_SystemInformation(data).payload.si2bis;
539 }
540 } else if (si_type == RSL_SYSTEM_INFO_2ter) {
541 if (not isbound(data)) {
542 si.si2ter := omit;
543 } else {
544 si.si2ter := dec_SystemInformation(data).payload.si2ter;
545 }
546 } else if (si_type == RSL_SYSTEM_INFO_2quater) {
547 if (not isbound(data)) {
548 si.si2quater := {};
549 } else {
550 var SystemInformationType2quater decoded := dec_SystemInformation(data).payload.si2quater;
551 /* this is a *record* of SI2quaterRestOctets! (multiplexed) */
552 si.si2quater[decoded.rest_octets.si2quater_index] := decoded.rest_octets;
553 }
554 } else if (si_type == RSL_SYSTEM_INFO_3) {
555 if (not isbound(data)) {
556 si.si3 := omit;
557 } else {
558 si.si3 := dec_SystemInformation(data).payload.si3;
559 }
560 } else if (si_type == RSL_SYSTEM_INFO_4) {
561 if (not isbound(data)) {
562 si.si4 := omit;
563 } else {
564 si.si4 := dec_SystemInformation(data).payload.si4;
565 }
566 } else if (si_type == RSL_SYSTEM_INFO_13) {
567 if (not isbound(data)) {
568 si.si13 := omit;
569 } else {
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100570 si.si13 := dec_SystemInformation(data).payload.si13;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200571 }
572 } else {
573 handled := false;
574 }
575 } else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
576 handled := true;
577
578 if (si_type == RSL_SYSTEM_INFO_5) {
579 if (not isbound(data)) {
580 si.si5 := omit;
581 } else {
582 si.si5 := dec_SystemInformation(data).payload.si5;
583 }
584 } else if (si_type == RSL_SYSTEM_INFO_5bis) {
585 if (not isbound(data)) {
586 si.si5bis := omit;
587 } else {
588 si.si5bis := dec_SystemInformation(data).payload.si5bis;
589 }
590 } else if (si_type == RSL_SYSTEM_INFO_5ter) {
591 if (not isbound(data)) {
592 si.si5ter := omit;
593 } else {
594 si.si5ter := dec_SystemInformation(data).payload.si5ter;
595 }
596 } else if (si_type == RSL_SYSTEM_INFO_6) {
597 if (not isbound(data)) {
598 si.si6 := omit;
599 } else {
600 si.si6 := dec_SystemInformation(data).payload.si6;
601 }
602 } else {
603 handled := false;
604 }
605 }
606
607 if (not handled) {
608 setverdict(fail, "Unexpected SI type in ", rsl.msg_type, " message: ", si_type);
609 }
610}
611
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +0100612friend function gen_l3_valid_payload(hexstring imsi := ''H) return octetstring {
613 var octetstring l3_payload;
614 if (lengthof(imsi) == 0) {
615 imsi := f_rnd_imsi('00101'H);
616 }
617 l3_payload := enc_PDU_ML3_MS_NW(valueof(ts_LU_REQ(LU_Type_IMSI_Attach, ts_MI_LV(ts_MI_IMSI(imsi)))));
618 return l3_payload;
619}
620
Harald Weltea4ca4462018-02-09 00:17:14 +0100621type component test_CT extends CTRL_Adapter_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600622 /* Array of per-BTS/TRX state */
623 var BTS_State bts[NUM_BTS][NUM_TRX];
Harald Welte89ab1912018-02-23 18:56:29 +0100624 /* RSL common Channel Port (for RSL_Emulation) */
625 port RSL_CCHAN_PT RSL_CCHAN[NUM_BTS];
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600626 /* array of per-BTS/TRX RSL test ports */
627 port IPA_RSL_PT IPA_RSL[NUM_BTS][NUM_TRX];
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100628 port IPA_CODEC_PT IPA; /* Required for compilation of TC_rsl_unknown_unit_id() */
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +0200629 /* CTRL muxed over IPA in SCCPlite conn BSC<->MSC (or BSC-NAT) */
630 port IPA_CTRL_PT SCCPLITE_IPA_CTRL;
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200631 /* Configure/manage IPA_Emulation per-BTS/TRX port: */
632 port IPA_CFG_PT IPA_CFG_PORT[NUM_BTS][NUM_TRX];
Harald Weltea5d2ab22017-12-09 14:21:42 +0100633
Pau Espin Pedrol3c630532022-10-20 19:00:11 +0200634 var MGCP_Emulation_CT vc_MGCP[NUM_MGW];
635 var integer g_nr_mgw; /* number of vc_MGCP to initialize */
Harald Weltebc03c762018-02-12 18:09:38 +0100636 port TELNETasp_PT BSCVTY;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100637
Daniel Willmannebdecc02020-08-12 15:30:17 +0200638 /* StatsD */
639 var StatsD_Checker_CT vc_STATSD;
640
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200641 var RAN_Adapter g_bssap[NUM_MSC];
Harald Welte47cd0e32020-08-21 12:39:11 +0200642 var BSSAP_LE_Adapter g_bssap_le;
Harald Weltea4ca4462018-02-09 00:17:14 +0100643 /* for old legacy-tests only */
644 port BSSAP_CODEC_PT BSSAP;
Harald Welte47cd0e32020-08-21 12:39:11 +0200645 port BSSAP_LE_CODEC_PT BSSAP_LE;
Harald Weltea4ca4462018-02-09 00:17:14 +0100646
Harald Welte21b46bd2017-12-17 19:46:32 +0100647 /* are we initialized yet */
Harald Welte28d943e2017-11-25 15:00:50 +0100648 var boolean g_initialized := false;
Harald Welte21b46bd2017-12-17 19:46:32 +0100649
Neels Hofmeyr38632aa2023-04-05 03:50:51 +0200650 var boolean g_handler_mode := false;
651
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200652 /* Osmux is enabled through VTY */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200653 var boolean g_osmux_enabled_cn := false;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +0200654 var boolean g_osmux_enabled_bts := false;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200655
Pau Espin Pedrolc675b612020-01-09 19:55:40 +0100656 /*Configure T(tias) over VTY, seconds */
657 var integer g_bsc_sccp_timer_ias := 7 * 60;
658 /*Configure T(tiar) over VTY, seconds */
659 var integer g_bsc_sccp_timer_iar := 15 * 60;
660
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +0200661 /* global test case guard timer (actual timeout value is set in f_init()) */
Harald Welteae026692017-12-09 01:03:01 +0100662 timer T_guard := 30.0;
663
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200664 var CounterNameValsList g_ctr_msc;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000665 var CounterNameValsList g_ctr_bsc;
666 var CounterNameValsList g_ctr_bts;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200667
668 /* System Information bytes as received during RSL startup, for each RSL[idx]. */
669 var SystemInformationConfig_list g_system_information := {};
Harald Welte28d943e2017-11-25 15:00:50 +0100670}
671
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200672type record of charstring phys_chan_configs;
Harald Welte28d943e2017-11-25 15:00:50 +0100673modulepar {
Harald Welte21b46bd2017-12-17 19:46:32 +0100674 /* IP address at which the BSC can be reached */
Harald Welte696ddb62017-12-08 14:01:43 +0100675 charstring mp_bsc_ip := "127.0.0.1";
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100676 /* port number to which to establish the IPA OML connections */
677 integer mp_bsc_oml_port := 3002;
Harald Welte21b46bd2017-12-17 19:46:32 +0100678 /* port number to which to establish the IPA RSL connections */
Harald Welte696ddb62017-12-08 14:01:43 +0100679 integer mp_bsc_rsl_port := 3003;
Harald Welte21b46bd2017-12-17 19:46:32 +0100680 /* port number to which to establish the IPA CTRL connection */
Harald Welte96c94412017-12-09 03:12:45 +0100681 integer mp_bsc_ctrl_port := 4249;
Daniel Willmannebdecc02020-08-12 15:30:17 +0200682 /* port number to which to listen for STATSD metrics */
683 integer mp_bsc_statsd_port := 8125;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100684 /* IP address at which the test binds */
685 charstring mp_test_ip := "127.0.0.1";
Harald Weltea4ca4462018-02-09 00:17:14 +0100686
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200687 RAN_Configurations mp_bssap_cfg := {
688 {
689 transport := BSSAP_TRANSPORT_AoIP,
690 sccp_service_type := "mtp3_itu",
691 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
692 own_pc := 185, /* 0.23.1 first MSC emulation */
693 own_ssn := 254,
694 peer_pc := 187, /* 0.23.3 osmo-bsc */
695 peer_ssn := 254,
696 sio := '83'O,
Harald Weltecb0cc432020-06-21 19:42:31 +0200697 rctx := 1
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200698 },
699 {
700 transport := BSSAP_TRANSPORT_AoIP,
701 sccp_service_type := "mtp3_itu",
702 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
703 own_pc := 2, /* 0.0.2 second MSC emulation */
704 own_ssn := 254,
705 peer_pc := 187, /* 0.23.3 osmo-bsc */
706 peer_ssn := 254,
707 sio := '83'O,
708 rctx := 2
709 },
710 {
711 transport := BSSAP_TRANSPORT_AoIP,
712 sccp_service_type := "mtp3_itu",
713 sctp_addr := { 23907, "127.0.0.1", 2905, "127.0.0.1" },
714 own_pc := 3, /* 0.0.3 third MSC emulation */
715 own_ssn := 254,
716 peer_pc := 187, /* 0.23.3 osmo-bsc */
717 peer_ssn := 254,
718 sio := '83'O,
719 rctx := 3
720 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100721 };
Pau Espin Pedrol58cf6822019-05-28 18:11:33 +0200722
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200723 /* Must match per BTS config in osmo-bsc.cfg */
724 phys_chan_configs phys_chan_config := {
725 "CCCH+SDCCH4+CBCH",
726 "TCH/F",
727 "TCH/F",
728 "TCH/F",
729 "TCH/F",
Vadim Yanitskiy343c9eb2021-07-16 18:36:01 +0600730 "TCH/H",
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200731 "PDCH",
732 "PDCH"
733 };
734
Harald Welte47cd0e32020-08-21 12:39:11 +0200735 BSSAP_LE_Configuration mp_bssap_le_cfg := {
736 sccp_service_type := "mtp3_itu",
737 sctp_addr := { 23908, "127.0.0.1", 2905, "127.0.0.1" },
Neels Hofmeyrac086c12020-09-18 23:46:42 +0200738 own_pc := 190, /* 0.23.6 SMLC emulation */
Harald Welte47cd0e32020-08-21 12:39:11 +0200739 own_ssn := 252, /* SMLC side SSN */
740 peer_pc := 187, /* 0.23.3 osmo-bsc */
741 peer_ssn := 250, /* BSC side SSN */
742 sio := '83'O,
743 rctx := 6
744 };
Neels Hofmeyrcfe44062020-10-15 02:28:08 +0200745 boolean mp_enable_lcs_tests := true;
Harald Welte47cd0e32020-08-21 12:39:11 +0200746
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100747 /* Value set in osmo-bsc.cfg "ms max power" */
748 uint8_t mp_exp_ms_power_level := 7;
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600749
750 /* Whether to check for memory leaks */
751 boolean mp_verify_talloc_count := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100752}
753
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200754friend function f_gen_test_hdlr_pars(integer bssap_idx := 0) return TestHdlrParams {
Philipp Maier48604732018-10-09 15:00:37 +0200755
756 var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200757 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier48604732018-10-09 15:00:37 +0200758 pars.aoip := true;
759 } else {
760 pars.aoip := false;
761 }
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100762 pars.exp_ms_power_level := mp_exp_ms_power_level;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200763 pars.mscpool.bssap_idx := bssap_idx;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600764 pars.expect_tsc := c_BtsParams[0].tsc;
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300765 pars.imsi := f_rnd_imsi('00101'H);
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +0100766 pars.imei := f_rnd_imei('00101'H);
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300767
768 log(testcasename(), ": using IMSI ", pars.imsi);
Neels Hofmeyrb5b7a6e2021-06-04 19:03:45 +0200769
Philipp Maier48604732018-10-09 15:00:37 +0200770 return pars;
771}
772
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200773/* Convenience functions for rate counters using g_ctr_msc. */
774
775private function f_ctrs_msc_init(integer mscs_count := NUM_MSC, CounterNameVals counternames := counternames_msc_mscpool) runs on test_CT {
776 g_ctr_msc := f_counter_name_vals_get_n(IPA_CTRL, "msc", mscs_count, counternames);
777 log("initial msc rate counters: ", g_ctr_msc);
778}
779
780private function f_ctrs_msc_add(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr9656e922020-06-30 01:27:01 +0200781 f_counter_name_vals_list_add(g_ctr_msc, msc_nr, countername, val);
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200782}
783
784/* f_ctrs_msc_init();
785 * f_do_thing(on_msc := 0);
786 * f_do_thing(on_msc := 0);
787 * f_do_other(on_msc := 1);
788 * f_ctrs_msc_add(0, "thing", 2);
789 * f_ctrs_msc_add(1, "other");
790 * f_ctrs_msc_verify();
791 */
792private function f_ctrs_msc_verify() runs on test_CT {
793 log("verifying msc rate counters: ", g_ctr_msc);
794 f_counter_name_vals_expect_n(IPA_CTRL, "msc", g_ctr_msc);
795}
796
797/* convenience: f_ctrs_msc_add() and f_ctrs_msc_verify() in one call.
798 * f_ctrs_msc_init();
799 * f_do_thing(on_msc := 0);
800 * f_do_thing(on_msc := 0);
801 * f_do_thing(on_msc := 0);
802 * f_ctrs_msc_expect(0, "thing", 3);
803 */
804private function f_ctrs_msc_expect(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
805 f_ctrs_msc_add(msc_nr, countername, val);
806 f_ctrs_msc_verify();
807}
808
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000809/* Convenience functions for rate counters using g_ctr_bts, always also including g_ctr_bsc. */
810
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100811private function f_ctrs_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000812 g_ctr_bts := f_counter_name_vals_get_n(IPA_CTRL, "bts", bts_count, counternames);
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100813 log("initial bts rate counters: ", g_ctr_bts);
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100814}
815
816function f_ctrs_bsc_and_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
817 f_ctrs_bts_init(bts_count, counternames);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000818 f_ctrs_bsc_init(counternames);
819}
820
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100821private function f_ctrs_bsc_and_bts_handover_init(integer bts_count := NUM_BTS) runs on test_CT {
822 var CounterNameVals bts_names := counternames_bsc_bts_handover & counternames_bts_handover;
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100823 f_ctrs_bts_init(bts_count, bts_names);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100824 f_ctrs_bsc_init(counternames_bsc_bts_handover);
825}
826
827private function f_ctrs_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000828 f_counter_name_vals_list_add(g_ctr_bts, bts_nr, countername, val);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100829}
830
831private function f_ctrs_bsc_and_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
832 f_ctrs_bts_add(bts_nr, countername, val);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000833 f_ctrs_bsc_add(countername, val);
834}
835
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100836function f_ctrs_bts_verify() runs on test_CT {
837 f_counter_name_vals_expect_n(IPA_CTRL, "bts", g_ctr_bts);
838}
839
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000840/* f_ctrs_bsc_and_bts_init();
841 * f_do_thing(on_bts := 0);
842 * f_do_thing(on_bts := 0);
843 * f_do_other(on_bts := 1);
844 * f_ctrs_bsc_and_bts_add(0, "thing", 2);
845 * f_ctrs_bsc_and_bts_add(1, "other");
846 * f_ctrs_bsc_and_bts_verify();
847 */
848private function f_ctrs_bsc_and_bts_verify() runs on test_CT {
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100849 f_ctrs_bts_verify();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000850 f_ctrs_bsc_verify();
851}
852
853/* convenience: f_ctrs_bsc_and_bts_add() and f_ctrs_bsc_and_bts_verify() in one call.
854 * f_ctrs_bsc_and_bts_init();
855 * f_do_thing(on_bts := 0);
856 * f_do_thing(on_bts := 0);
857 * f_do_thing(on_bts := 0);
858 * f_ctrs_bsc_and_bts_expect(0, "thing", 3);
859 */
860private function f_ctrs_bsc_and_bts_expect(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
861 f_ctrs_bsc_and_bts_add(bts_nr, countername, val);
862 f_ctrs_bsc_and_bts_verify();
863}
864
865
866/* Convenience functions for rate counters using g_ctr_bsc. */
867
868private function f_ctrs_bsc_init(CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
869 g_ctr_bsc := f_counter_name_vals_get_n(IPA_CTRL, "bsc", 1, counternames);
870 log("initial bsc rate counters: ", g_ctr_bsc);
871}
872
873private function f_ctrs_bsc_add(charstring countername, integer val := 1) runs on test_CT {
874 f_counter_name_vals_list_add(g_ctr_bsc, 0, countername, val);
875}
876
877/* f_ctrs_bsc_init();
878 * f_do_thing();
879 * f_do_thing();
880 * f_do_other();
881 * f_ctrs_bsc_add("thing", 2);
882 * f_ctrs_bsc_add("other");
883 * f_ctrs_bsc_verify();
884 */
885private function f_ctrs_bsc_verify() runs on test_CT {
886 f_counter_name_vals_expect_n(IPA_CTRL, "bsc", g_ctr_bsc);
887}
888
889/* convenience: f_ctrs_bsc_add() and f_ctrs_bsc_verify() in one call.
890 * f_ctrs_bsc_init();
891 * f_do_thing();
892 * f_ctrs_bsc_expect("thing", 1);
893 */
894private function f_ctrs_bsc_expect(charstring countername, integer val := 1) runs on test_CT {
895 f_ctrs_bsc_add(countername, val);
896 f_ctrs_bsc_verify();
897}
898
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200899
Oliver Smith39f53072022-10-27 14:44:04 +0200900friend function f_shutdown_helper(boolean ho := false) runs on test_CT {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100901 /* Run the subscr and conn leak test only when the VTY is initialized */
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600902 if (BSCVTY.checkstate("Mapped") and mp_verify_talloc_count) {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100903 f_verify_talloc_count(BSCVTY, {"struct bsc_subscr", "struct gsm_subscriber_connection"});
904 }
905
Oliver Smith39f53072022-10-27 14:44:04 +0200906 /* Reset handover related configuration */
907 if (ho) {
908 f_bts_0_cfg(BSCVTY,
909 {"no neighbors",
910 "neighbor-list mode manual-si5",
911 "neighbor-list add arfcn 100",
912 "neighbor-list add arfcn 200",
913 "si5 neighbor-list add arfcn 10",
914 "si5 neighbor-list add arfcn 20",
915 "handover algorithm 1"});
916 }
917
Daniel Willmann637ef6c2018-07-25 10:49:09 +0200918 all component.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100919 setverdict(pass);
Daniel Willmannafce8662018-07-06 23:11:32 +0200920 mtc.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100921}
922
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200923private function f_legacy_bssap_reset(integer bssap_idx := 0) runs on test_CT {
Harald Weltea4ca4462018-02-09 00:17:14 +0100924 var BSSAP_N_UNITDATA_ind ud_ind;
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200925 var boolean reset_received := false;
Harald Weltea4ca4462018-02-09 00:17:14 +0100926 timer T := 5.0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200927 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200928 ts_BSSMAP_Reset(0, g_osmux_enabled_cn)));
Harald Weltea4ca4462018-02-09 00:17:14 +0100929 T.start;
930 alt {
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200931 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[bssap_idx].sccp_addr_own, g_bssap[bssap_idx].sccp_addr_peer,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200932 tr_BSSMAP_ResetAck(g_osmux_enabled_cn))) {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200933 log("BSSMAP: Received RESET-ACK in response to RESET, we're ready to go!");
Harald Weltea4ca4462018-02-09 00:17:14 +0100934 }
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200935 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200936 log("BSSMAP: Respoding to inbound RESET with RESET-ACK");
Harald Weltea4ca4462018-02-09 00:17:14 +0100937 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200938 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200939 reset_received := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100940 repeat;
941 }
942 [] BSSAP.receive { repeat; }
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200943 [] T.timeout {
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) {
Pau Espin Pedrola1d113a2024-04-16 21:00:49 +0200949 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
950 "BSSMAP: Timeout waiting for RESET-ACK after sending RESET");
951 } else {
952 log("BSSMAP: Timeout waiting for RESET-ACK after sending RESET");
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200953 }
954 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100955 }
Harald Welte28d943e2017-11-25 15:00:50 +0100956}
957
Harald Welteae026692017-12-09 01:03:01 +0100958type record IPA_Client {
Harald Welte21b46bd2017-12-17 19:46:32 +0100959 /* IPA Emulation component reference */
Harald Welteae026692017-12-09 01:03:01 +0100960 IPA_Emulation_CT vc_IPA,
Harald Welte21b46bd2017-12-17 19:46:32 +0100961 /* Unit-ID and other CCM parameters to use for IPA client emulation */
Harald Welteae026692017-12-09 01:03:01 +0100962 IPA_CCM_Parameters ccm_pars,
Harald Welte21b46bd2017-12-17 19:46:32 +0100963 /* String identifier for this IPA Client */
Harald Welte624f9632017-12-16 19:26:04 +0100964 charstring id,
Harald Welte21b46bd2017-12-17 19:46:32 +0100965 /* Associated RSL Emulation Component (if any). Only used in "Handler mode" */
Harald Welte624f9632017-12-16 19:26:04 +0100966 RSL_Emulation_CT vc_RSL optional
Harald Welte28d943e2017-11-25 15:00:50 +0100967}
968
Harald Welte21b46bd2017-12-17 19:46:32 +0100969/*! Start the IPA/RSL related bits for one IPA_Client.
970 * \param clnt IPA_Client for which to establish
971 * \param bsc_host IP address / hostname of the BSC
972 * \param bsc_port TCP port number of the BSC
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600973 * \param idx BTS/TRX index values
Harald Welte21b46bd2017-12-17 19:46:32 +0100974 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600975function f_ipa_rsl_start(inout IPA_Client clnt, charstring bsc_host, PortNumber bsc_port,
976 BtsTrxIdx idx := {0, 0}, boolean handler_mode := false)
Harald Welte28d943e2017-11-25 15:00:50 +0100977runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +0100978 timer T := 10.0;
979
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600980 clnt.id := "IPA-BTS" & int2str(idx.bts) & "-TRX" & int2str(idx.trx) & "-RSL";
Harald Welte71389132021-12-09 21:58:18 +0100981 clnt.vc_IPA := IPA_Emulation_CT.create(clnt.id & "-IPA") alive;
Harald Welteae026692017-12-09 01:03:01 +0100982 clnt.ccm_pars := c_IPA_default_ccm_pars;
983 clnt.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
Vadim Yanitskiy7ed7bd62024-04-20 03:29:11 +0700984 clnt.ccm_pars.unit_id := enc_IpaUnitId({1234 + idx.bts, 0, idx.trx});
Harald Welte624f9632017-12-16 19:26:04 +0100985 if (handler_mode) {
Harald Welte71389132021-12-09 21:58:18 +0100986 clnt.vc_RSL := RSL_Emulation_CT.create(clnt.id & "-RSL") alive;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600987 connect(clnt.vc_RSL:CCHAN_PT, self:RSL_CCHAN[idx.bts]);
Harald Welte624f9632017-12-16 19:26:04 +0100988 }
Harald Welteae026692017-12-09 01:03:01 +0100989
990 map(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200991 connect(clnt.vc_IPA:CFG_PORT, self:IPA_CFG_PORT[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100992 if (handler_mode) {
993 connect(clnt.vc_IPA:IPA_RSL_PORT, clnt.vc_RSL:IPA_PT);
994 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600995 connect(clnt.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100996 }
Harald Welteae026692017-12-09 01:03:01 +0100997
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600998 var integer local_port := 10000 + idx.bts * 1000 + idx.trx;
999 clnt.vc_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", local_port, clnt.ccm_pars));
Harald Welte624f9632017-12-16 19:26:04 +01001000 if (handler_mode) {
1001 clnt.vc_RSL.start(RSL_Emulation.main());
1002 return;
1003 }
Harald Welteae026692017-12-09 01:03:01 +01001004
1005 /* wait for IPA RSL link to connect and send ID ACK */
1006 T.start;
1007 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001008 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) {
Harald Welteae026692017-12-09 01:03:01 +01001009 T.stop;
Harald Welteae026692017-12-09 01:03:01 +01001010 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001011 [] IPA_RSL[idx.bts][idx.trx].receive(ASP_IPA_Event:?) { repeat }
1012 [] IPA_RSL[idx.bts][idx.trx].receive { repeat }
Harald Welteae026692017-12-09 01:03:01 +01001013 [] T.timeout {
Harald Welte96c94412017-12-09 03:12:45 +01001014 setverdict(fail, "Timeout RSL waiting for ASP_IPA_EVENT_ID_ACK");
Daniel Willmannafce8662018-07-06 23:11:32 +02001015 mtc.stop;
Harald Welteae026692017-12-09 01:03:01 +01001016 }
1017 }
1018}
1019
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001020function f_ipa_rsl_stop(inout IPA_Client clnt, BtsTrxIdx idx := {0, 0}) runs on test_CT {
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001021 var IPL4asp_Types.Result res := {
1022 errorCode := omit,
1023 connId := omit,
1024 os_error_code := omit,
1025 os_error_text := omit
1026 };
1027
Harald Welte12055472018-03-17 20:10:08 +01001028 if (not isbound(clnt) or not isbound(clnt.vc_IPA)) {
1029 return;
1030 }
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001031
1032 /* Alive components don't finish sockets (TCP FIN) when they are
1033 * stopped. Hence, we need to manually call close() on them to make sure
1034 * the IUT knows about it. */
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001035 f_ipa_cfg_disconnect(IPA_CFG_PORT[idx.bts][idx.trx], res);
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001036
Harald Welte12055472018-03-17 20:10:08 +01001037 clnt.vc_IPA.stop;
1038 if (isbound(clnt.vc_RSL)) {
1039 clnt.vc_RSL.stop;
1040 }
1041}
1042
Harald Welte21b46bd2017-12-17 19:46:32 +01001043/* Wait for the OML connection to be brought up by the external osmo-bts-omldummy */
Harald Weltea5d2ab22017-12-09 14:21:42 +01001044function f_wait_oml(integer bts_nr, charstring status, float secs_max) runs on test_CT {
1045 timer T := secs_max;
1046 T.start;
1047 while (true) {
1048 if (f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-connection-state") == status) {
1049 T.stop;
Harald Weltebd868bd2017-12-10 18:28:40 +01001050 /* the 'degraded' state exists from OML connection time, and we have to wait
1051 * until all MO's are initialized */
1052 T.start(1.0);
1053 T.timeout;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001054 return;
1055 }
Harald Weltef0d6ac62017-12-17 17:02:21 +01001056 f_sleep(0.1);
Harald Weltea5d2ab22017-12-09 14:21:42 +01001057 if (not T.running) {
Max99253902018-11-16 17:57:39 +01001058 setverdict(fail, "Timeout waiting for BTS" & int2str(bts_nr) & " oml-connection-state ", status);
Daniel Willmannafce8662018-07-06 23:11:32 +02001059 mtc.stop;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001060 }
1061 }
1062}
1063
Harald Welte21b46bd2017-12-17 19:46:32 +01001064/* global altstep for global guard timer; also takes care of responding RESET witH RESET-ACK */
Harald Welteae026692017-12-09 01:03:01 +01001065altstep as_Tguard() runs on test_CT {
Harald Welte60e823a2017-12-10 14:10:59 +01001066 var BSSAP_N_UNITDATA_ind ud_ind;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001067 [] T_guard.timeout {
1068 setverdict(fail, "Timeout of T_guard");
Daniel Willmannafce8662018-07-06 23:11:32 +02001069 mtc.stop;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001070 }
Harald Welte60e823a2017-12-10 14:10:59 +01001071 /* always respond with RESET ACK to RESET */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001072 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Harald Welte60e823a2017-12-10 14:10:59 +01001073 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001074 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Harald Welte69c1c262017-12-13 21:02:08 +01001075 repeat;
Harald Welte60e823a2017-12-10 14:10:59 +01001076 }
Harald Welte28d943e2017-11-25 15:00:50 +01001077}
1078
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001079altstep no_bssmap_reset() runs on test_CT {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001080 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001081 setverdict(fail, "unexpected BSSMAP Reset");
Daniel Willmannafce8662018-07-06 23:11:32 +02001082 mtc.stop;
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001083 }
1084}
1085
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001086function f_init_mgcp(integer mgw_nr, charstring id) runs on test_CT {
1087 id := id & "-MGCP-" & int2str(mgw_nr);
Daniel Willmann191e0d92018-01-17 12:44:35 +01001088
1089 var MGCPOps ops := {
1090 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
1091 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
1092 };
1093 var MGCP_conn_parameters mgcp_pars := {
1094 callagent_ip := mp_bsc_ip,
Harald Welte9e4273e2018-01-29 22:01:22 +01001095 callagent_udp_port := -1,
Daniel Willmann191e0d92018-01-17 12:44:35 +01001096 mgw_ip := mp_test_ip,
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001097 mgw_udp_port := 2427 + mgw_nr,
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02001098 /* Enable it for SCCPlite, since we have 2 MGCP sockets towards MGW (UDP one +
Pau Espin Pedrol36eeaf72022-10-20 16:50:31 +02001099 the one with MGCP over IPA forwarded from MSC one) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001100 multi_conn_mode := (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER)
Daniel Willmann191e0d92018-01-17 12:44:35 +01001101 };
1102
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001103 vc_MGCP[mgw_nr] := MGCP_Emulation_CT.create(id) alive;
1104 vc_MGCP[mgw_nr].start(MGCP_Emulation.main(ops, mgcp_pars, id));
Daniel Willmann191e0d92018-01-17 12:44:35 +01001105}
1106
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001107/* Enable or disable (current default) Osmux. When enabling, BSSMAP Reset
1108 * contains extra IE (OsmuxSupport) and osmo-bsc will handle AssignReq with
1109 * OsmuxCID IE.
1110 */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001111private function f_vty_allow_osmux_cn(boolean allow) runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001112 f_vty_enter_cfg_msc(BSCVTY, 0);
1113 if (allow) {
1114 f_vty_transceive(BSCVTY, "osmux on");
1115 } else {
1116 f_vty_transceive(BSCVTY, "osmux off");
1117 }
1118 f_vty_transceive(BSCVTY, "exit");
1119 f_vty_transceive(BSCVTY, "exit");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001120}
1121
Max2253c0b2018-11-06 19:28:05 +01001122function f_init_vty(charstring id := "foo") runs on test_CT {
Harald Welte94e0c342018-04-07 11:33:23 +02001123 if (BSCVTY.checkstate("Mapped")) {
1124 /* skip initialization if already executed once */
1125 return;
1126 }
Harald Weltebc03c762018-02-12 18:09:38 +01001127 map(self:BSCVTY, system:BSCVTY);
1128 f_vty_set_prompts(BSCVTY);
1129 f_vty_transceive(BSCVTY, "enable");
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01001130 f_cs7_inst_0_cfg(BSCVTY, {"sccp-timer ias " & int2str(g_bsc_sccp_timer_ias),
1131 "sccp-timer iar " & int2str(g_bsc_sccp_timer_iar)});
Harald Weltebc03c762018-02-12 18:09:38 +01001132}
1133
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001134private function f_sysinfo_seen(integer rsl_idx, RSL_Message rsl) runs on test_CT
1135{
1136 if (rsl_idx >= lengthof(g_system_information)) {
1137 g_system_information[rsl_idx] := SystemInformationConfig_omit
1138 }
1139 f_sysinfo_dec_raw(g_system_information[rsl_idx], rsl);
1140}
1141
1142altstep as_catch_RSL_sysinfo(integer rsl_idx) runs on test_CT {
1143 var ASP_RSL_Unitdata rx_rsl_ud;
1144
1145 /* For handler_mode := false, receiving the RSL bootstrap messages directly on IPA_RSL */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001146 [] 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 +02001147 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1148 repeat;
1149 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001150 [] 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 +02001151 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1152 repeat;
1153 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001154 [] 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 +02001155 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1156 repeat;
1157 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001158 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001159 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1160 repeat;
1161 }
1162
1163 /* For handler_mode := true, receiving the RSL bootstrap messages via RSL_Emulation */
1164 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
1165 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1166 repeat;
1167 }
1168 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
1169 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1170 repeat;
1171 }
1172 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
1173 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1174 repeat;
1175 }
1176 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
1177 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1178 repeat;
1179 }
1180}
1181
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001182/* TODO: use BooleanList from COMMON/src/General_Types.ttcn */
1183private type record of boolean my_BooleanList;
1184
1185private function f_vty_msc_allow_attach(TELNETasp_PT pt, my_BooleanList allow_attach_list)
1186{
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001187 var charstring config := f_vty_transceive_ret(pt, "show running-config");
1188
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001189 for (var integer msc_nr := 0; msc_nr < sizeof(allow_attach_list); msc_nr := msc_nr+1) {
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001190 if (f_strstr(config, "\nmsc " & int2str(msc_nr) & "\n") < 0) {
1191 /* There is no 'msc N' for this msc_nr in the running config, so don't create an empty msc by
1192 * stepping into that config node. */
1193 log("msc ", msc_nr, " is not configured, skipping");
1194 continue;
1195 }
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001196 f_vty_enter_cfg_msc(pt, msc_nr);
1197 if (allow_attach_list[msc_nr]) {
1198 /* strict := false: ignore if osmo-bsc does not support this config option (latest build) */
1199 f_vty_transceive(pt, "allow-attach", strict := false);
1200 } else {
1201 f_vty_transceive(pt, "no allow-attach", strict := false);
1202 }
1203 f_vty_transceive(pt, "exit");
1204 f_vty_transceive(pt, "exit");
1205 }
1206}
1207
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02001208private function f_bssap_idx_init(integer bssap_idx) runs on test_CT {
1209 /* Call a function of our 'parent component' RAN_Adapter_CT to start the
1210 * MSC-side BSSAP emulation */
1211 if (g_handler_mode) {
1212 var RanOps ranops := MSC_RanOps;
1213 ranops.use_osmux := g_osmux_enabled_cn;
1214 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", ranops);
1215 connect(self:SCCPLITE_IPA_CTRL, g_bssap[bssap_idx].vc_RAN:CTRL_CLIENT);
1216 f_ran_adapter_start(g_bssap[bssap_idx]);
1217 } else {
1218 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", omit);
1219 connect(self:BSSAP, g_bssap[bssap_idx].vc_SCCP:SCCP_SP_PORT);
1220 f_ran_adapter_start(g_bssap[bssap_idx]);
1221 f_legacy_bssap_reset();
1222 }
1223}
1224
1225private function f_bssap_idx_disconnect(integer bssap_idx) runs on test_CT {
1226 f_ran_adapter_cleanup(g_bssap[bssap_idx]);
1227}
1228
Harald Welte21b46bd2017-12-17 19:46:32 +01001229/* global initialization function
1230 * \param nr_bts Number of BTSs we should start/bring up
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001231 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false).
1232 * \param nr_msc Number of virtual MSCs to bring up to connect to osmo-bsc.
1233 */
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001234function f_init(integer nr_bts := NUM_BTS, boolean handler_mode := false,
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001235 integer nr_msc := 1, integer nr_mgw := 1, float guard_timeout := 30.0) runs on test_CT {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001236 var integer bssap_idx;
Harald Welte28d943e2017-11-25 15:00:50 +01001237
Harald Welteae026692017-12-09 01:03:01 +01001238 if (g_initialized) {
1239 return;
Harald Welte28d943e2017-11-25 15:00:50 +01001240 }
Harald Welteae026692017-12-09 01:03:01 +01001241 g_initialized := true;
1242
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +02001243 T_guard.start(guard_timeout);
Daniel Willmanne68f9272018-11-27 15:15:28 +01001244 activate(as_Tguard());
1245
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001246 f_init_vty("VirtMSC");
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001247 f_vty_allow_osmux_cn(g_osmux_enabled_cn);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001248
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001249 var my_BooleanList allow_attach := { false, false, false };
Daniel Willmannebdecc02020-08-12 15:30:17 +02001250 f_init_statsd("VirtMSC", vc_STATSD, mp_test_ip, mp_bsc_statsd_port);
1251
Neels Hofmeyr9db8e0e2021-08-23 20:45:58 +02001252 /* Make sure each MSC's internal state is "DISCONNECTED" at first */
1253 for (bssap_idx := 0; bssap_idx < NUM_MSC; bssap_idx := bssap_idx+1) {
1254 f_vty_transceive(BSCVTY, "msc " & int2str(bssap_idx) & " bssmap reset", strict := false);
1255 }
1256
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02001257 g_handler_mode := handler_mode;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001258 for (bssap_idx := 0; bssap_idx < nr_msc; bssap_idx := bssap_idx+1) {
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001259 allow_attach[bssap_idx] := true;
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02001260 f_bssap_idx_init(bssap_idx);
Harald Welte67089ee2018-01-17 22:19:03 +01001261 }
Harald Welted5833a82018-05-27 16:52:56 +02001262
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02001263 if (mp_enable_lcs_tests) {
1264 if (handler_mode) {
1265 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", SMLC_BssapLeOps);
1266 } else {
1267 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", omit);
1268 connect(self:BSSAP_LE, g_bssap_le.vc_SCCP:SCCP_SP_PORT);
1269 }
1270 f_bssap_le_adapter_start(g_bssap_le);
Harald Welte47cd0e32020-08-21 12:39:11 +02001271 }
Harald Welte47cd0e32020-08-21 12:39:11 +02001272
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001273 /* start the test with exactly all enabled MSCs allowed to attach */
1274 f_vty_msc_allow_attach(BSCVTY, allow_attach);
1275
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01001276 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Harald Welte28d943e2017-11-25 15:00:50 +01001277
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001278 g_nr_mgw := nr_mgw;
1279 for (var integer i := 0; i < g_nr_mgw; i := i+1) {
1280 f_init_mgcp(i, "VirtMGW");
1281 }
Daniel Willmann191e0d92018-01-17 12:44:35 +01001282
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001283 for (var integer i := 0; i < nr_bts; i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001284 f_init_bts(i, c_BtsParams[i].trx_num, handler_mode);
Harald Welte696ddb62017-12-08 14:01:43 +01001285 }
Neels Hofmeyr9c0f9c82022-01-23 01:20:28 +01001286
1287 /* Emit a marker to appear in the SUT's own logging output */
1288 f_logp(BSCVTY, testcasename() & "() start");
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001289}
Harald Welte696ddb62017-12-08 14:01:43 +01001290
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001291function f_init_bts(integer bts_idx := 0,
1292 integer trx_num := NUM_TRX_CFG,
1293 boolean handler_mode := false)
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001294runs on test_CT {
1295 /* wait until osmo-bts-omldummy has respawned */
1296 f_wait_oml(bts_idx, "degraded", 5.0);
1297
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001298 /* start RSL connection(s) */
1299 for (var integer trx_idx := 0; trx_idx < trx_num; trx_idx := trx_idx + 1) {
1300 f_ipa_rsl_start(bts[bts_idx][trx_idx].rsl,
1301 mp_bsc_ip, mp_bsc_rsl_port,
1302 {bts_idx, trx_idx}, handler_mode);
1303 }
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001304 /* wait until BSC tells us "connected" */
1305 f_wait_oml(bts_idx, "connected", 5.0);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001306
1307 /* Set up BTS with VTY commands: */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01001308 f_vty_enter_cfg_bts(BSCVTY, bts_idx);
1309 if (g_osmux_enabled_bts) {
1310 f_vty_transceive(BSCVTY, "osmux on");
1311 } else {
1312 f_vty_transceive(BSCVTY, "osmux off");
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001313 }
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01001314 f_vty_transceive(BSCVTY, "end");
Harald Welte28d943e2017-11-25 15:00:50 +01001315}
1316
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001317function f_init_bts_and_check_sysinfo(integer bts_idx := 0,
1318 integer trx_num := NUM_TRX_CFG,
1319 boolean handler_mode := false,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001320 template SystemInformationConfig expect_si)
1321runs on test_CT {
1322 var default sysinfo := activate(as_catch_RSL_sysinfo(bts_idx));
1323
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001324 f_init_bts(bts_idx, trx_num, handler_mode);
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001325
1326 /* Give some time to (hopefully/most likely) collect all system informations from RSL startup.
1327 * We could stop as soon as all expected SI are received, but then we might miss SI that we don't expect and
1328 * that might be sent afterwards. So rather give a generous timeout and be quite sure to catch all SI.
1329 */
1330 f_sleep(5.0);
1331 log("RSL ", bts_idx, " SYSTEM INFORMATION: ", g_system_information[bts_idx]);
1332
1333 deactivate(sysinfo);
1334
1335 if (match(g_system_information[bts_idx], expect_si)) {
1336 setverdict(pass);
1337 } else {
1338 log("RSL ", bts_idx, ": EXPECTED SI: ", expect_si);
1339 log("RSL ", bts_idx, ": GOT SI: ", g_system_information[bts_idx]);
1340 setverdict(fail, "received SI does not match expectations");
1341 return;
1342 }
1343}
1344
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001345/* expect to receive a RSL message matching a specified template on a given BTS / TRX */
1346function f_exp_ipa_rx(template (present) RSL_Message t_rx,
1347 BtsTrxIdx idx := {0, 0},
1348 float Tval := 2.0)
Harald Welteae026692017-12-09 01:03:01 +01001349runs on test_CT return RSL_Message {
1350 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001351 timer T := Tval;
Harald Welteae026692017-12-09 01:03:01 +01001352
1353 T.start;
1354 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001355 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Harald Welteae026692017-12-09 01:03:01 +01001356 T.stop;
1357 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001358 [] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
Harald Welteb2917702017-12-10 15:48:52 +01001359 [] T.timeout {
1360 setverdict(fail, "Timeout expecting ", t_rx);
Daniel Willmannafce8662018-07-06 23:11:32 +02001361 mtc.stop;
Harald Welteb2917702017-12-10 15:48:52 +01001362 }
Harald Welteae026692017-12-09 01:03:01 +01001363 }
1364 return rx_rsl_ud.rsl;
1365}
1366
Harald Welte21b46bd2017-12-17 19:46:32 +01001367/* helper function to transmit RSL on a given BTS/stream */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001368function f_ipa_tx(template (value) RSL_Message t_tx,
1369 BtsTrxIdx idx := {0, 0},
1370 IpaStreamId sid := IPAC_PROTO_RSL_TRX0)
Harald Welteae026692017-12-09 01:03:01 +01001371runs on test_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001372 IPA_RSL[idx.bts][idx.trx].send(ts_ASP_RSL_UD(t_tx, sid));
Harald Welteae026692017-12-09 01:03:01 +01001373}
1374
1375
Harald Welte4003d112017-12-09 22:35:39 +01001376/* verify we get a CHAN_ACT after CHAN RQD */
Harald Welteae026692017-12-09 01:03:01 +01001377testcase TC_chan_act_noreply() runs on test_CT {
1378 var BSSAP_N_UNITDATA_ind ud_ind;
Harald Welte930d0a72018-03-22 22:08:40 +01001379 var RSL_Message rsl_unused;
Harald Welte28d943e2017-11-25 15:00:50 +01001380
Harald Welte89d42e82017-12-17 16:42:41 +01001381 f_init(1);
Harald Welte28d943e2017-11-25 15:00:50 +01001382
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001383 f_ipa_tx(ts_RSL_CHAN_RQD('23'O, 23));
1384 rsl_unused := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001385 f_shutdown_helper();
Harald Welte28d943e2017-11-25 15:00:50 +01001386}
1387
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001388const CounterNameVals counternames_bts_chreq := {
1389 { "chreq:total", 0 },
1390 { "chreq:attempted_emerg", 0 },
1391 { "chreq:attempted_call", 0 },
1392 { "chreq:attempted_location_upd", 0 },
1393 { "chreq:attempted_pag", 0 },
1394 { "chreq:attempted_pdch", 0 },
1395 { "chreq:attempted_other", 0 },
1396 { "chreq:attempted_unknown", 0 },
1397 { "chreq:successful", 0 },
1398 { "chreq:successful_emerg", 0 },
1399 { "chreq:successful_call", 0 },
1400 { "chreq:successful_location_upd", 0 },
1401 { "chreq:successful_pag", 0 },
1402 { "chreq:successful_pdch", 0 },
1403 { "chreq:successful_other", 0 },
1404 { "chreq:successful_unknown", 0 },
1405 { "chreq:no_channel", 0 },
1406 { "chreq:max_delay_exceeded", 0 }
1407};
1408
1409/* verify the "chreq:*" counters */
1410private function f_chan_act_counter(OCT1 ra, charstring chreq_ctr_suffix) runs on test_CT
1411{
1412 var GsmFrameNumber fn := 23;
1413
1414 f_logp(BSCVTY, "f_chan_act_counter(" & chreq_ctr_suffix & ")");
1415
1416 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001417 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn));
1418 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001419 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1420
1421 f_ctrs_bts_add(0, "chreq:total");
1422 f_ctrs_bts_add(0, "chreq:attempted_" & chreq_ctr_suffix);
1423 f_ctrs_bts_verify();
1424
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001425 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
1426 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001427
1428 f_ctrs_bts_add(0, "chreq:successful");
1429 f_ctrs_bts_add(0, "chreq:successful_" & chreq_ctr_suffix);
1430 f_ctrs_bts_verify();
1431
1432 /* test is done, release RSL Conn Fail Ind to clean up */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001433 f_ipa_tx(ts_RSL_CONN_FAIL_IND(chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1434 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
1435 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001436 f_sleep(1.0);
1437}
1438
Harald Welte4003d112017-12-09 22:35:39 +01001439testcase TC_chan_act_counter() runs on test_CT {
1440 var BSSAP_N_UNITDATA_ind ud_ind;
1441 var integer chreq_total;
Harald Welte930d0a72018-03-22 22:08:40 +01001442 var RSL_Message rsl_unused;
Harald Welte4003d112017-12-09 22:35:39 +01001443
Harald Welte89d42e82017-12-17 16:42:41 +01001444 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001445
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001446 f_vty_allow_emerg_bts(true, 0);
1447
1448 f_ctrs_bts_init(1, counternames_bts_chreq);
1449
1450 /* emergency call: RA & 0xe0 == 0xa0 --> CHREQ_T_EMERG_CALL */
1451 f_chan_act_counter('a3'O, "emerg");
1452
1453 /* voice TCH/H: RA & 0xf0 == 0x40 --> CHREQ_T_VOICE_CALL_TCH_H */
1454 f_chan_act_counter('43'O, "call");
1455
1456 /* LU: RA & 0xf0 == 0x00 --> CHREQ_T_LOCATION_UPD */
1457 f_chan_act_counter('03'O, "location_upd");
1458
1459 /* Paging: RA & 0xf0 == 0x20 --> CHREQ_T_PAG_R_TCH_F */
1460 f_chan_act_counter('23'O, "pag");
1461 /* Paging: RA & 0xf0 == 0x30 --> CHREQ_T_PAG_R_TCH_FH */
1462 f_chan_act_counter('33'O, "pag");
1463
1464 /* LU: RA & 0xfc == 0x78 --> CHREQ_T_PDCH_TWO_PHASE */
1465 /* no PCU, so PDCH not allowed. Skip this test for now. */
1466 /* f_chan_act_counter('7b'O, "pdch"); */
1467
1468 /* LU: RA & 0xf0 == 0x10 --> CHREQ_T_SDCCH */
1469 f_chan_act_counter('13'O, "other");
Harald Welte4003d112017-12-09 22:35:39 +01001470
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001471 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001472}
1473
Harald Welteae026692017-12-09 01:03:01 +01001474/* CHAN RQD -> CHAN ACT -> CHAN ACT ACK -> RF CHAN REL */
Philipp Maier9c60a622020-07-09 15:08:46 +02001475private function f_TC_chan_act_ack_noest(OCT1 ra := '23'O) runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +01001476 var RSL_Message rx_rsl;
1477
Harald Welteae026692017-12-09 01:03:01 +01001478 /* Send CHAN RQD and wait for allocation; acknowledge it */
Philipp Maier9c60a622020-07-09 15:08:46 +02001479 var RslChannelNr chan_nr := f_chreq_act_ack(ra);
Harald Welteae026692017-12-09 01:03:01 +01001480
1481 /* expect BSC to disable the channel again if there's no RLL EST IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001482 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := T3101_MAX);
Harald Welteae026692017-12-09 01:03:01 +01001483
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001484 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001485}
1486
Philipp Maier9c60a622020-07-09 15:08:46 +02001487/* Normal variant */
1488testcase TC_chan_act_ack_noest() runs on test_CT {
Philipp Maieraf58db22020-08-12 17:24:40 +02001489 f_init(1);
Philipp Maier9c60a622020-07-09 15:08:46 +02001490 f_TC_chan_act_ack_noest();
1491}
1492
1493/* Emergency call variant */
1494testcase TC_chan_act_ack_noest_emerg() runs on test_CT {
1495 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
Philipp Maieraf58db22020-08-12 17:24:40 +02001496 f_init(1);
1497 f_vty_allow_emerg_bts(true, 0);
Philipp Maier9c60a622020-07-09 15:08:46 +02001498 f_TC_chan_act_ack_noest(ra := 'A5'O);
1499}
1500
Philipp Maier606f07d2020-08-12 17:21:58 +02001501/* Emergency call variant, but emergency calls are not allowed */
1502testcase TC_chan_rqd_emerg_deny() runs on test_CT {
1503 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
1504
1505 var RSL_Message rx_rsl;
1506 var GsmRrMessage rr;
1507
1508 f_init(1);
1509 f_vty_allow_emerg_bts(false, 0);
1510
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001511 IPA_RSL[0][0].clear;
1512 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier606f07d2020-08-12 17:21:58 +02001513
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001514 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Philipp Maier606f07d2020-08-12 17:21:58 +02001515 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
1516 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1517 setverdict(pass);
1518 } else {
1519 setverdict(fail, "immediate assignment not rejected");
1520 }
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01001521
1522 f_shutdown_helper();
Philipp Maier606f07d2020-08-12 17:21:58 +02001523}
1524
Harald Welteae026692017-12-09 01:03:01 +01001525/* Test behavior if MSC never answers to CR */
1526testcase TC_chan_act_ack_est_ind_noreply() runs on test_CT {
Harald Weltef77aef62018-01-28 15:35:42 +01001527 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
1528 var IpaStreamId sid := IPAC_PROTO_RSL_TRX0;
Harald Welteae026692017-12-09 01:03:01 +01001529 var RSL_Message rx_rsl;
Harald Weltef77aef62018-01-28 15:35:42 +01001530 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001531 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welteae026692017-12-09 01:03:01 +01001532
Harald Welte89d42e82017-12-17 16:42:41 +01001533 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001534
1535 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001536 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001537
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001538 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welteae026692017-12-09 01:03:01 +01001539
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001540 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload)));
Harald Welteae026692017-12-09 01:03:01 +01001541
1542 /* expect BSC to disable the channel again if there's no response from MSC */
Harald Weltef77aef62018-01-28 15:35:42 +01001543 /* MS waits 20s (T3210) at LU; 10s (T3230) at CM SERV REQ and 5s (T3220) AT detach */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001544 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001545 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001546}
1547
1548/* Test behavior if MSC answers with CREF to CR */
1549testcase TC_chan_act_ack_est_ind_refused() runs on test_CT {
1550 var BSSAP_N_CONNECT_ind rx_c_ind;
1551 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001552 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welteae026692017-12-09 01:03:01 +01001553
Harald Welte89d42e82017-12-17 16:42:41 +01001554 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001555
1556 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001557 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001558
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001559 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welteae026692017-12-09 01:03:01 +01001560
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001561 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Harald Welteae026692017-12-09 01:03:01 +01001562 BSSAP.send(ts_BSSAP_DISC_req(rx_c_ind.connectionId, 0));
1563
1564 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001565 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001566 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001567}
1568
Harald Welte618ef642017-12-14 14:58:20 +01001569/* CHAN RQD -> CHAN ACT -> CHAN ACT NACK -> RF CHAN REL */
1570testcase TC_chan_act_nack() runs on test_CT {
1571 var RSL_Message rx_rsl;
1572 var integer chact_nack;
1573
Harald Welte89d42e82017-12-17 16:42:41 +01001574 f_init(1);
Harald Welte618ef642017-12-14 14:58:20 +01001575
1576 chact_nack := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack");
1577
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001578 f_ipa_tx(ts_RSL_CHAN_RQD('33'O, 33));
1579 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Harald Welte618ef642017-12-14 14:58:20 +01001580 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1581
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001582 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte618ef642017-12-14 14:58:20 +01001583
1584 /* wait for some time to hope the NACK arrives before the CTRL GET below */
1585 f_sleep(0.5);
1586
1587 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack", chact_nack+1);
1588
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001589 f_shutdown_helper();
Harald Welte618ef642017-12-14 14:58:20 +01001590}
1591
Harald Welte799c97b2017-12-14 17:50:30 +01001592/* Test for channel exhaustion due to RACH overload */
1593testcase TC_chan_exhaustion() runs on test_CT {
1594 var ASP_RSL_Unitdata rsl_ud;
1595 var integer i;
1596 var integer chreq_total, chreq_nochan;
1597
Harald Welte89d42e82017-12-17 16:42:41 +01001598 f_init(1);
Harald Welte799c97b2017-12-14 17:50:30 +01001599
1600 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
1601 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
1602
Neels Hofmeyr85fa37f2021-10-06 13:50:38 +02001603 /* GSM 44.018 Table 9.1.8.2:
Pau Espin Pedrolfe200d72018-12-10 12:41:04 +01001604 * RA = '33'O -> Establishment cause = 0011xxxx (MS dual rate capable and asks for "TCH/H or TCH/F").
1605 * With current setup, expect 4xSDCCH + 4xTCH/F + 1xTCH/H to succeed */
Philipp Maiercb6cc482018-03-26 13:08:00 +02001606 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 +01001607 var RslChannelNr chan_nr := f_chreq_act_ack('33'O, i);
Harald Welte799c97b2017-12-14 17:50:30 +01001608 }
1609
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001610 IPA_RSL[0][0].clear;
Harald Welte799c97b2017-12-14 17:50:30 +01001611
Harald Weltedd8cbf32018-01-28 12:07:52 +01001612 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001613 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
Harald Welte799c97b2017-12-14 17:50:30 +01001614
1615 /* now expect additional channel activations to fail */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001616 f_ipa_tx(ts_RSL_CHAN_RQD('42'O, 42));
Harald Welte799c97b2017-12-14 17:50:30 +01001617
1618 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001619 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV))) {
Harald Welte799c97b2017-12-14 17:50:30 +01001620 setverdict(fail, "Received CHAN ACT ACK without resources?!?");
1621 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001622 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) -> value rsl_ud {
Harald Welte799c97b2017-12-14 17:50:30 +01001623 var GsmRrMessage rr;
1624 /* match on IMM ASS REJ */
1625 rr := dec_GsmRrMessage(rsl_ud.rsl.ies[1].body.full_imm_ass_info.payload);
1626 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1627 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001628 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS+1);
Harald Welte799c97b2017-12-14 17:50:30 +01001629 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel",
1630 chreq_nochan+1);
1631 setverdict(pass);
1632 } else {
1633 repeat;
1634 }
1635 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001636 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte799c97b2017-12-14 17:50:30 +01001637 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001638 f_shutdown_helper();
Harald Welte799c97b2017-12-14 17:50:30 +01001639}
1640
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001641/* Test channel deactivation due to silence from MS */
1642testcase TC_chan_deact_silence() runs on test_CT {
1643 var RslChannelNr chan_nr;
1644
1645 f_init(1);
1646
1647 /* Request for a dedicated channel */
1648 chan_nr := f_chreq_act_ack('23'O);
1649
1650 /* Wait some time until the channel is released */
1651 f_sleep(2.0);
1652
1653 /* Expect CHANnel RELease */
1654 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001655 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001656 log("Received CHANnel RELease");
1657 setverdict(pass);
1658 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001659 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001660 /* See OS#3709, OsmoBSC should not send Immediate
1661 * Assignment Reject since a dedicated channel was
1662 * already allocated, and Immediate Assignment was
1663 * already sent. */
1664 setverdict(fail, "Unexpected Immediate Assignment!");
1665 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001666 [] IPA_RSL[0][0].receive {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001667 setverdict(fail, "Unexpected RSL message!");
1668 }
1669 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001670 f_shutdown_helper();
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001671}
1672
Harald Weltecfe2c962017-12-15 12:09:32 +01001673/***********************************************************************
1674 * Assignment Testing
1675 ***********************************************************************/
1676
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02001677/* Verify that the BSC refuses any BSSAP connection from the MSC (They are all BSC->MSC direction,
1678 * except for the inter-BSC handover, MT side) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001679testcase TC_outbound_connect(integer bssap_idx := 0) runs on test_CT {
Harald Welte89d42e82017-12-17 16:42:41 +01001680 f_init(1);
Harald Weltecfe2c962017-12-15 12:09:32 +01001681
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001682 BSSAP.send(ts_BSSAP_CONNECT_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
1683 2342, ts_BSSMAP_AssignmentReq));
Harald Weltecfe2c962017-12-15 12:09:32 +01001684 BSSAP.receive(tr_BSSAP_DISC_ind(2342, ?, ?));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001685 f_shutdown_helper();
Harald Weltecfe2c962017-12-15 12:09:32 +01001686}
1687
Harald Welte16a4adf2017-12-14 18:54:01 +01001688/* Test behavior if MSC answers with CREF to CR */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001689testcase TC_assignment_cic_only(integer bssap_idx := 0) runs on test_CT {
Harald Welte16a4adf2017-12-14 18:54:01 +01001690 var BSSAP_N_CONNECT_ind rx_c_ind;
1691 var RSL_Message rx_rsl;
1692 var DchanTuple dt;
1693
Harald Welte89d42e82017-12-17 16:42:41 +01001694 f_init(1);
Harald Welte16a4adf2017-12-14 18:54:01 +01001695
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001696 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001697 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte17b27da2018-05-25 20:33:53 +02001698 /* send assignment without AoIP IEs */
1699 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(ts_BSSMAP_IE_CIC(0, 1))));
1700 } else {
Pau Espin Pedrol35609792023-01-03 16:56:59 +01001701 /* Send assignment without CIC in IPA case */
Harald Welte17b27da2018-05-25 20:33:53 +02001702 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
1703 valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
1704 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(omit, tla)));
1705 }
Harald Welte16a4adf2017-12-14 18:54:01 +01001706 alt {
1707 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1708 setverdict(fail, "AoIP BSC cannot accept ASSIGNMENT without AoIP Transport IE");
1709 }
Harald Welte235ebf12017-12-15 14:18:16 +01001710 /* TODO: Actually expect GSM0808_CAUSE_REQ_A_IF_TYPE_NOT_SUPP */
Harald Welte16a4adf2017-12-14 18:54:01 +01001711 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1712 setverdict(pass);
1713 }
1714 [] BSSAP.receive { repeat; }
1715 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001716 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001717 f_shutdown_helper();
Harald Welte16a4adf2017-12-14 18:54:01 +01001718}
1719
Harald Welteed848512018-05-24 22:27:58 +02001720/* generate an assignment request for either AoIP or SCCPlite */
Pau Espin Pedrolb522e1c2023-09-28 13:38:50 +02001721function f_gen_ass_req(boolean osmux_enabled := false, uint8_t ass_cid := 0, integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4") return PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001722 var PDU_BSSAP ass_cmd;
Pau Espin Pedrolb522e1c2023-09-28 13:38:50 +02001723 var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(ass_cid));
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001724 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welteed848512018-05-24 22:27:58 +02001725 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001726 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001727 if (osmux_enabled) {
1728 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla, osmux_cid));
1729 } else {
1730 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla));
1731 }
Harald Welteed848512018-05-24 22:27:58 +02001732 } else {
Pau Espin Pedrolb522e1c2023-09-28 13:38:50 +02001733 var BIT8 ass_cid_bit := int2bit(ass_cid, 8);
1734 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(bit2int(ass_cid_bit >> 5),
1735 bit2int(ass_cid_bit and4b '00011111'B)));
Pau Espin Pedrol096d73d2019-06-06 12:49:17 +02001736 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(cic, omit));
Harald Welteed848512018-05-24 22:27:58 +02001737 }
1738 return ass_cmd;
1739}
1740
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02001741function f_gen_handover_req(integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4",
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001742 template (value) BSSMAP_IE_CellIdentifier cell_id_source := ts_CellID_LAC_CI(1, 1),
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001743 template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit,
1744 template (omit) TestHdlrEncrParams enc := omit) return PDU_BSSAP {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001745 var PDU_BSSAP ho_req;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001746
1747 var BSSMAP_IE_EncryptionInformation encryptionInformation :=
1748 valueof(ts_BSSMAP_IE_EncrInfo('0000000000000000'O,'01'O));
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03001749 var template (omit) BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := omit;
1750 var template (omit) BSSMAP_IE_KC128 kc128 := omit;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001751 if (ispresent(enc)) {
1752 var TestHdlrEncrParams v_enc := valueof(enc);
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01001753 encryptionInformation := valueof(ts_BSSMAP_IE_EncrInfo(v_enc.enc_key, v_enc.enc_alg_permitted));
1754 if (ispresent(v_enc.enc_alg_chosen)) {
1755 chosenEncryptionAlgorithm := valueof(
1756 ts_BSSMAP_IE_ChosenEncryptionAlgorithm(int2oct(enum2int(
1757 f_cipher_mode_bssmap_to_rsl(v_enc.enc_alg_chosen)), 1)));
1758 }
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001759 if (ispresent(v_enc.enc_kc128)) {
1760 kc128 := ts_BSSMAP_IE_Kc128(v_enc.enc_kc128);
1761 }
1762 }
1763
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001764 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001765 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001766 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001767 ho_req := valueof(ts_BSSMAP_HandoverRequest(omit, tla,
1768 cell_id_source := cell_id_source,
1769 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001770 encryptionInformation := encryptionInformation,
1771 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
Neels Hofmeyr9fe13202022-03-04 00:05:43 +01001772 kC128 := kc128,
1773 /* on AoIP, allow "all" codecs (until we add more concise
1774 * tests) */
1775 codecList := ts_BSSMAP_IE_CodecList(
1776 {ts_CodecAMR_F, ts_CodecAMR_H,
1777 ts_CodecEFR, ts_CodecFR, ts_CodecHR})));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001778 } else {
1779 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001780 ho_req := valueof(ts_BSSMAP_HandoverRequest(cic, omit,
1781 cell_id_source := cell_id_source,
1782 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001783 encryptionInformation := encryptionInformation,
1784 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
1785 kC128 := kc128));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001786 }
1787 return ho_req;
1788}
1789
Harald Welteed848512018-05-24 22:27:58 +02001790/* generate an assignment complete template for either AoIP or SCCPlite */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001791function f_gen_exp_compl(integer bssap_idx := 0)
1792runs on MSC_ConnHdlr return template PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001793 var template PDU_BSSAP exp_compl;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001794 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001795 var template BSSMAP_IE_Osmo_OsmuxCID exp_osmux_cid := omit;
1796 if (g_pars.use_osmux_cn) {
1797 var template (present) INT1 exp_cid := ?;
1798 if (isbound(g_media.mgcp_conn[0].local_osmux_cid) and isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1799 exp_cid := (g_media.mgcp_conn[0].local_osmux_cid, g_media.mgcp_conn[1].local_osmux_cid);
1800 } else if (isbound(g_media.mgcp_conn[0].local_osmux_cid)) {
1801 exp_cid := g_media.mgcp_conn[0].local_osmux_cid;
1802 } else if (isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1803 exp_cid := g_media.mgcp_conn[1].local_osmux_cid;
1804 }
1805 exp_osmux_cid := tr_OsmuxCID(exp_cid);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001806 }
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001807 exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, exp_osmux_cid);
Harald Welteed848512018-05-24 22:27:58 +02001808 } else {
1809 /* CIC is optional "*" as the MSC allocated it */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001810 exp_compl := tr_BSSMAP_AssignmentComplete(*, omit, omit);
Harald Welteed848512018-05-24 22:27:58 +02001811 }
1812 return exp_compl;
1813}
1814
Harald Welte235ebf12017-12-15 14:18:16 +01001815/* Run everything required up to sending a caller-specified assignment command and expect response */
1816function f_assignment_exp(PDU_BSSAP ass_cmd, template PDU_BSSAP exp, charstring fail_text)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001817runs on test_CT return DchanTuple {
Harald Welte235ebf12017-12-15 14:18:16 +01001818 var BSSAP_N_CONNECT_ind rx_c_ind;
1819 var RSL_Message rx_rsl;
1820 var DchanTuple dt;
1821
Harald Welte89d42e82017-12-17 16:42:41 +01001822 f_init(1);
Harald Welte235ebf12017-12-15 14:18:16 +01001823
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001824 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte235ebf12017-12-15 14:18:16 +01001825 /* send assignment without AoIP IEs */
1826 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
1827 alt {
1828 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1829 if (ischosen(exp.pdu.bssmap.assignmentComplete)) {
1830 setverdict(pass);
1831 } else {
1832 setverdict(fail, fail_text);
1833 }
1834 }
1835 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1836 if (ischosen(exp.pdu.bssmap.assignmentFailure)) {
1837 setverdict(pass);
1838 } else {
1839 setverdict(fail, fail_text);
1840 }
1841 }
1842 [] BSSAP.receive { repeat; }
1843 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001844 return dt;
Harald Welte235ebf12017-12-15 14:18:16 +01001845}
Oliver Smithdd002752023-02-21 13:35:00 +01001846
Oliver Smith545492d2023-04-19 13:05:30 +02001847private 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 +01001848 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welteed848512018-05-24 22:27:58 +02001849 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Oliver Smithbc392a82023-04-17 14:06:42 +02001850 var SDP_FIELD_PayloadType pt_csd := PT_CSD;
Oliver Smithdd002752023-02-21 13:35:00 +01001851
Harald Welte235ebf12017-12-15 14:18:16 +01001852 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smithdd002752023-02-21 13:35:00 +01001853 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecCSData}));
1854
Oliver Smith545492d2023-04-19 13:05:30 +02001855 /* Non-transparent service (3GPP TS 48.008 § 3.2.2.11, oct 5, bit 7) */
1856 if (not transp) {
1857 data_rate := data_rate or4b '40'O;
1858 }
1859
Oliver Smithcb617912023-04-18 11:29:10 +02001860 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := data_rate;
1861
1862 log("-----------------------------------------------");
1863 log("Assignment req with data rate: " & data_rate_str);
1864 log("-----------------------------------------------");
Oliver Smithdd002752023-02-21 13:35:00 +01001865
1866 f_establish_fully(ass_cmd, exp_compl);
Oliver Smithbc392a82023-04-17 14:06:42 +02001867
1868 if (g_media.bts.rtp_pt != enum2int(pt_csd)) {
1869 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("unexpected RTP payload type: ", g_media.bts.rtp_pt));
1870 }
1871
Oliver Smithdd002752023-02-21 13:35:00 +01001872 f_perform_clear();
Oliver Smithace447a2023-05-08 14:07:21 +02001873 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Oliver Smithdd002752023-02-21 13:35:00 +01001874}
Oliver Smithcb617912023-04-18 11:29:10 +02001875private function f_tc_assignment_csd_all(charstring id) runs on MSC_ConnHdlr {
1876 /* Data rates that require multi-slot HSCSD assignment are not tested
Oliver Smith545492d2023-04-19 13:05:30 +02001877 * on purpose (not supported): T_32k0, T_28k8, NT_43k5, NT_29k0 */
Oliver Smithcb617912023-04-18 11:29:10 +02001878 f_tc_assignment_csd("T_14k4", GSM0808_DATA_RATE_TRANSP_14k4);
1879 f_tc_assignment_csd("T_9k6", GSM0808_DATA_RATE_TRANSP_9k6);
1880 f_tc_assignment_csd("T_4k8", GSM0808_DATA_RATE_TRANSP_4k8);
1881 f_tc_assignment_csd("T_2k4", GSM0808_DATA_RATE_TRANSP_2k4);
1882 f_tc_assignment_csd("T_1k2", GSM0808_DATA_RATE_TRANSP_1k2);
1883 f_tc_assignment_csd("T_600", GSM0808_DATA_RATE_TRANSP_600);
1884 f_tc_assignment_csd("T_1200_75", GSM0808_DATA_RATE_TRANSP_1200_75);
Oliver Smith545492d2023-04-19 13:05:30 +02001885
1886 f_tc_assignment_csd("NT_12000_6000", GSM0808_DATA_RATE_NON_TRANSP_12000_6000, false);
1887 f_tc_assignment_csd("NT_14k5", GSM0808_DATA_RATE_NON_TRANSP_14k5, false);
1888 f_tc_assignment_csd("NT_12k0", GSM0808_DATA_RATE_NON_TRANSP_12k0, false);
1889 f_tc_assignment_csd("NT_6k0", GSM0808_DATA_RATE_NON_TRANSP_6k0, false);
Oliver Smithcb617912023-04-18 11:29:10 +02001890}
Oliver Smithdd002752023-02-21 13:35:00 +01001891testcase TC_assignment_csd() runs on test_CT {
Vadim Yanitskiy02c086f2023-09-22 15:32:41 +07001892 var MSC_ConnHdlr vc_conn;
1893 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Oliver Smithdd002752023-02-21 13:35:00 +01001894
Vadim Yanitskiy02c086f2023-09-22 15:32:41 +07001895 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
1896
1897 f_init(1, true, guard_timeout := 120.0);
1898 f_sleep(1.0);
1899 vc_conn := f_start_handler(refers(f_tc_assignment_csd_all), pars);
1900 vc_conn.done;
1901
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001902 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001903}
1904
1905testcase TC_assignment_ctm() runs on test_CT {
1906 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001907 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001908 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
1909 //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 +01001910 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
1911 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001912 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001913}
1914
Harald Welte4003d112017-12-09 22:35:39 +01001915type record DchanTuple {
1916 integer sccp_conn_id,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001917 RslChannelNr rsl_chan_nr,
1918 BtsTrxIdx idx
Harald Weltea5d2ab22017-12-09 14:21:42 +01001919}
1920
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +02001921type record of DchanTuple DchanTuples;
1922
Harald Welted6939652017-12-13 21:02:46 +01001923/* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001924private function f_chreq_act_ack(OCT1 ra := '23'O,
1925 GsmFrameNumber fn := 23,
1926 BtsTrxIdx idx := {0, 0})
Harald Welted6939652017-12-13 21:02:46 +01001927runs on test_CT return RslChannelNr {
1928 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001929 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
1930 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Harald Welted6939652017-12-13 21:02:46 +01001931 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001932 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10), idx);
1933 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Harald Welted6939652017-12-13 21:02:46 +01001934 return chan_nr;
1935}
1936
Harald Welte4003d112017-12-09 22:35:39 +01001937/* helper function to establish a dedicated channel via BTS and MSC */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001938function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1939 BtsTrxIdx idx := {0, 0})
Harald Welte4003d112017-12-09 22:35:39 +01001940runs on test_CT return DchanTuple {
1941 var BSSAP_N_CONNECT_ind rx_c_ind;
Harald Welte4003d112017-12-09 22:35:39 +01001942 var DchanTuple dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001943
Harald Welte4003d112017-12-09 22:35:39 +01001944 /* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001945 dt.rsl_chan_nr := f_chreq_act_ack(ra, fn, idx);
Harald Welte4003d112017-12-09 22:35:39 +01001946
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001947 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 +01001948
1949 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1950 dt.sccp_conn_id := rx_c_ind.connectionId;
1951 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1952
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001953 dt.idx := idx;
Harald Welte4003d112017-12-09 22:35:39 +01001954 return dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001955}
1956
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001957/* 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 +06001958function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1959 BtsTrxIdx idx := {0, 0})
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001960runs on test_CT return DchanTuple {
1961 var BSSAP_N_CONNECT_ind rx_c_ind;
1962 var DchanTuple dt;
1963
1964 /* Send CHAN RQD */
1965 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001966 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001967
1968 /* The dyn TS first deactivates PDCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001969 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 +02001970 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001971 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001972
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001973 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001974 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1975
1976 /* Now activates the signalling channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001977 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10), idx);
1978 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001979
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001980 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 +02001981
1982 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1983 dt.sccp_conn_id := rx_c_ind.connectionId;
1984 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1985
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001986 dt.idx := idx;
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001987 return dt;
1988}
1989
Harald Welte641fcbe2018-06-14 10:58:35 +02001990/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001991private function f_exp_chan_rel_and_clear(DchanTuple dt)
1992runs on test_CT {
Harald Welte641fcbe2018-06-14 10:58:35 +02001993 var RSL_Message rx_rsl;
1994 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001995 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 +02001996 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001997 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), dt.idx);
Harald Welte641fcbe2018-06-14 10:58:35 +02001998
1999 /* expect Clear Complete from BSC */
2000 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2001
2002 /* MSC disconnects as instructed. */
2003 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2004}
2005
Harald Welte4003d112017-12-09 22:35:39 +01002006/* Test behavior of channel release after unilateral RLL REL IND (DISC from MS) */
2007testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002008 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002009 var DchanTuple dt;
Harald Welte96c94412017-12-09 03:12:45 +01002010
Harald Welte89d42e82017-12-17 16:42:41 +01002011 f_init(1);
Harald Welte96c94412017-12-09 03:12:45 +01002012
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002013 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002014
2015 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002016 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Harald Welte4003d112017-12-09 22:35:39 +01002017
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002018 /* expect Clear Request on MSC side */
2019 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2020
2021 /* Instruct BSC to clear channel */
2022 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2023 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2024
Harald Welte4003d112017-12-09 22:35:39 +01002025 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002026 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002027
2028 /* wait for SCCP emulation to do its job */
2029 f_sleep(1.0);
Harald Welte4003d112017-12-09 22:35:39 +01002030
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002031 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002032}
2033
2034/* Test behavior of channel release after CONN FAIL IND from BTS */
2035testcase TC_chan_rel_conn_fail() runs on test_CT {
2036 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002037 var DchanTuple dt;
2038
Harald Welte89d42e82017-12-17 16:42:41 +01002039 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002040
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002041 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002042
Vadim Yanitskiy01d0a902022-12-14 22:41:42 +07002043 /* Sending CONN FAIL IND immediately may trigger a race condition.
2044 * Give the BSC some time to process a new SCCP connection (OS#5823). */
2045 f_sleep(0.2);
2046
Harald Welte4003d112017-12-09 22:35:39 +01002047 /* simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002048 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte4003d112017-12-09 22:35:39 +01002049 /* TODO: different cause values? */
2050
Harald Welte4003d112017-12-09 22:35:39 +01002051 /* expect Clear Request from BSC */
2052 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2053
2054 /* Instruct BSC to clear channel */
2055 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2056 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2057
Harald Welte6ff76ea2018-01-28 13:08:01 +01002058 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002059 f_exp_chan_rel_and_clear(dt);
Harald Welte4003d112017-12-09 22:35:39 +01002060
2061 /* wait for SCCP emulation to do its job */
2062 f_sleep(1.0);
2063
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002064 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002065}
2066
Harald Welte99f3ca02018-06-14 13:40:29 +02002067/* Test behavior of early CONN FAIL IND from BTS (before EST IND!) */
2068/* See also https://www.osmocom.org/issues/3182 */
2069testcase TC_early_conn_fail() runs on test_CT {
2070 var RSL_Message rx_rsl;
2071 var DchanTuple dt;
2072
2073 f_init(1);
2074
2075 /* BTS->BSC: Send CHAN RQD and wait for allocation; acknowledge it */
Harald Weltec46ea3c2020-10-10 18:46:12 +02002076 dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_ra_cs(), 23);
Harald Welte99f3ca02018-06-14 13:40:29 +02002077
2078 /* BTS->BSC: simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002079 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002080
2081 /* BTS->BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002082 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002083
2084 /* BTS<-BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002085 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002086
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002087 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002088}
2089
2090/* Test behavior of late CONN FAIL IND from BTS (ater REL IND!) */
2091/* See also https://www.osmocom.org/issues/3182 */
2092testcase TC_late_conn_fail() runs on test_CT {
2093 var RSL_Message rx_rsl;
2094 var DchanTuple dt;
2095
2096 f_init(1);
2097
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002098 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99f3ca02018-06-14 13:40:29 +02002099
2100 /* BSC<-MSC: Instruct BSC to clear connection */
2101 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(0)));
2102
2103 /* BTS->BSC: expect BSC to deactivate SACCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002104 rx_rsl := f_exp_ipa_rx(tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002105
2106 /* BTS->BSC: simulate a late CONN FAIL IND from BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002107 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002108
2109 /* BTS<-BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002110 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002111 /* BTS->BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002112 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002113
2114 /* BSC->MSC: expect Clear Complete from BSC */
2115 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2116
2117 /* BSC<-MSC: MSC disconnects as requested. */
2118 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2119
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002120 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002121}
2122
Oliver Smithaf03bef2021-08-24 15:34:51 +02002123private function f_TC_stats_conn_fail(charstring id) runs on MSC_ConnHdlr {
2124 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
2125 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2126
2127 f_statsd_reset();
2128
Oliver Smith15890b42023-03-08 14:12:28 +01002129 /* Establish SDCCH (invalid DataIndicator for exp_fail) */
Oliver Smithaf03bef2021-08-24 15:34:51 +02002130 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smith15890b42023-03-08 14:12:28 +01002131 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := 'ff'O;
Oliver Smithaf03bef2021-08-24 15:34:51 +02002132 f_establish_fully(ass_cmd, exp_fail);
2133
2134 /* Expect stats to be 0 */
2135 var StatsDExpects expect := {
2136 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
2137 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
2138 };
2139 f_statsd_expect(expect);
2140
2141 /* Simulate CONN FAIL IND on SDCCH */
2142 RSL.send(ts_ASP_RSL_UD(
2143 ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
2144 IPAC_PROTO_RSL_TRX0));
2145
Neels Hofmeyr58be48a2021-09-07 18:39:21 +02002146 f_sleep(1.0);
2147
Oliver Smithaf03bef2021-08-24 15:34:51 +02002148 /* Expect stats to be 1 */
2149 expect := {
2150 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
2151 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
2152 };
2153 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002154 BSSAP.receive(tr_BSSMAP_ClearRequest);
2155 f_perform_clear();
Oliver Smithaf03bef2021-08-24 15:34:51 +02002156}
2157testcase TC_stats_conn_fail() runs on test_CT {
2158 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2159 var MSC_ConnHdlr vc_conn;
2160
2161 f_init(1, true);
2162 f_sleep(1.0);
2163
2164 vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
2165 vc_conn.done;
2166
2167 f_shutdown_helper();
2168}
2169
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002170function f_expect_chan_rel(RslChannelNr rsl_chan_nr,
2171 BtsTrxIdx idx := {0, 0},
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002172 boolean expect_deact_sacch := true,
2173 boolean expect_rr_chan_rel := true,
2174 boolean expect_rll_rel_req := true,
Harald Welte99787102019-02-04 10:41:36 +01002175 boolean handle_rll_rel := true,
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002176 template CellSelIndValue expect_cells := omit,
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002177 template (present) RR_Cause expect_rr_cause := ?
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002178 ) runs on test_CT {
Harald Welte91d54a52018-01-28 15:35:07 +01002179
2180 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002181 var boolean got_deact_sacch := false;
2182 var boolean got_rr_chan_rel := false;
2183 var boolean got_rll_rel_req := false;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002184 var ASP_RSL_Unitdata ud;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002185 var RSL_IE_Body l3_ie;
2186 var PDU_ML3_NW_MS l3;
2187 var RR_Cause got_cause;
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002188 log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
2189 " expect_rll_rel_req=", expect_rll_rel_req);
Harald Welte91d54a52018-01-28 15:35:07 +01002190 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002191 [] 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 +01002192 got_deact_sacch := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002193 repeat;
2194 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002195 [] 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 +01002196 got_rr_chan_rel := true;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002197
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002198 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2199 setverdict(fail, "cannot find L3");
2200 mtc.stop;
2201 }
2202 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2203
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002204 if (not istemplatekind(expect_cells, "omit")) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002205 var CellSelIndValue cells := dec_CellSelIndValue(
2206 l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
2207
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002208 log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
2209 if (match(cells, expect_cells)) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002210 setverdict(pass);
2211 } else {
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002212 log("EXPECTED CELLS: ", expect_cells);
2213 setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002214 }
2215 }
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002216
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002217 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2218 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2219 if (match(got_cause, expect_rr_cause)) {
2220 setverdict(pass);
2221 } else {
2222 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2223 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002224 }
Harald Welte99787102019-02-04 10:41:36 +01002225 repeat;
2226 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002227 [] 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 +01002228 got_rll_rel_req := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002229 /* FIXME: Why are we getting this for LinkID SACCH? */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002230 if (handle_rll_rel) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002231 f_ipa_tx(ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002232 }
Harald Welte91d54a52018-01-28 15:35:07 +01002233 repeat;
2234 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002235 [] 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 +01002236 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002237 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
Harald Welte91d54a52018-01-28 15:35:07 +01002238 }
2239 /* ignore any user data */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002240 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002241 repeat;
2242 }
2243 }
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002244
2245 log("f_expect_chan_rel() summary: got_deact_sacch=", got_deact_sacch, " got_rr_chan_rel=", got_rr_chan_rel,
2246 " got_rll_rel_req=", got_rll_rel_req);
2247
2248 if (expect_deact_sacch != got_deact_sacch) {
2249 setverdict(fail, "f_expect_chan_rel(): expect_deact_sacch=", expect_deact_sacch, " got_deact_sacch=", got_deact_sacch);
2250 }
2251 if (expect_rr_chan_rel != got_rr_chan_rel) {
2252 setverdict(fail, "f_expect_chan_rel(): expect_rr_chan_rel=", expect_rr_chan_rel, " got_rr_chan_rel=", got_rr_chan_rel);
2253 }
2254 if (expect_rll_rel_req != got_rll_rel_req) {
2255 setverdict(fail, "f_expect_chan_rel(): expect_rll_rel_req=", expect_rll_rel_req, " got_rll_rel_req=", got_rll_rel_req);
2256 }
Harald Welte91d54a52018-01-28 15:35:07 +01002257}
2258
Harald Welte4003d112017-12-09 22:35:39 +01002259/* Test behavior of channel release after hard Clear Command from MSC */
2260testcase TC_chan_rel_hard_clear() runs on test_CT {
2261 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002262 var DchanTuple dt;
Harald Welte4003d112017-12-09 22:35:39 +01002263
Harald Welte89d42e82017-12-17 16:42:41 +01002264 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002265
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002266 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002267
2268 /* Instruct BSC to clear channel */
2269 var BssmapCause cause := 0;
2270 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2271
2272 /* expect Clear Complete from BSC on A */
2273 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2274 /* release the SCCP connection */
2275 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2276 }
2277
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002278 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002279 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002280}
2281
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002282function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
2283 var BSSAP_N_DATA_ind rx_di;
2284 var DchanTuple dt;
2285
2286 f_init(1);
2287
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002288 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002289 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2290 /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
2291 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
2292
2293 /* Instruct BSC to clear channel */
2294 var BssmapCause cause := 0;
2295 if (tx_csfb_ind) {
2296 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2297 } else {
2298 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2299 }
2300
2301 /* expect Clear Complete from BSC on A */
2302 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2303 /* release the SCCP connection */
2304 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2305 }
2306
2307 /* 1 neighbor is added by default in osmo-bts.cfg and
2308 SystemInformationConfig_default, use that: */
2309 var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
2310
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002311 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 +02002312 f_shutdown_helper();
2313}
2314
2315/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
2316 from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
2317 PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2318 EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
2319 Indicator or not shouldn't matter at all. */
2320testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
2321 f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
2322}
2323
2324/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
2325 MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
2326 Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2327 EUTRAN neighbor list sent later on by BSC in RR Channel. */
2328testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
2329 f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
2330}
2331
2332/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
2333 MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
2334 Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
2335 CSFB Indicator should not be used anymore, and hence, there should be no
2336 EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
2337 Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
Harald Welte99787102019-02-04 10:41:36 +01002338testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
2339 var BSSAP_N_DATA_ind rx_di;
2340 var DchanTuple dt;
2341
2342 f_init(1);
2343
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002344 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99787102019-02-04 10:41:36 +01002345
2346 /* Instruct BSC to clear channel */
2347 var BssmapCause cause := 0;
2348 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2349
2350 /* expect Clear Complete from BSC on A */
2351 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2352 /* release the SCCP connection */
2353 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2354 }
2355
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002356 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002357 f_shutdown_helper();
Harald Welte99787102019-02-04 10:41:36 +01002358}
2359
Harald Welted8c36cd2017-12-09 23:05:31 +01002360/* Test behavior of channel release after hard RLSD from MSC */
2361testcase TC_chan_rel_hard_rlsd() runs on test_CT {
Harald Welted8c36cd2017-12-09 23:05:31 +01002362 var DchanTuple dt;
Harald Welted8c36cd2017-12-09 23:05:31 +01002363
Harald Welte89d42e82017-12-17 16:42:41 +01002364 f_init(1);
Harald Welted8c36cd2017-12-09 23:05:31 +01002365
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002366 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welted8c36cd2017-12-09 23:05:31 +01002367
2368 /* release the SCCP connection */
2369 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2370
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002371 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002372 f_shutdown_helper();
Harald Welted8c36cd2017-12-09 23:05:31 +01002373}
2374
Harald Welte550daf92018-06-11 19:22:13 +02002375/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
2376testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
2377 var DchanTuple dt;
2378
2379 f_init(1);
2380
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002381 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte550daf92018-06-11 19:22:13 +02002382
2383 /* release the SCCP connection */
2384 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2385
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002386 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002387 f_shutdown_helper();
Harald Welte550daf92018-06-11 19:22:13 +02002388}
2389
Harald Welte85804d42017-12-10 14:11:58 +01002390/* Test behavior of channel release after BSSMAP RESET from MSC */
2391testcase TC_chan_rel_a_reset() runs on test_CT {
Harald Welte85804d42017-12-10 14:11:58 +01002392 var DchanTuple dt;
Harald Welte85804d42017-12-10 14:11:58 +01002393
Harald Welte89d42e82017-12-17 16:42:41 +01002394 f_init(1);
Harald Welte85804d42017-12-10 14:11:58 +01002395
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002396 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte85804d42017-12-10 14:11:58 +01002397
2398 /* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002399 IPA_RSL[0][0].clear;
Harald Welte85804d42017-12-10 14:11:58 +01002400
2401 /* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002402 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 +01002403 interleave {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002404 [] 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 +01002405 [] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
2406 }
2407
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002408 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002409 f_shutdown_helper();
Harald Welte85804d42017-12-10 14:11:58 +01002410}
2411
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002412/* Verify T(iar) triggers and releases the channel */
2413testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
2414 var DchanTuple dt;
2415
2416 /* Set T(iar) in BSC low enough that it will trigger before other side
2417 has time to keep alive with a T(ias). Keep recommended ratio of
2418 T(iar) >= T(ias)*2 */
2419 g_bsc_sccp_timer_ias := 2;
2420 g_bsc_sccp_timer_iar := 5;
2421
2422 f_init(1);
2423
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002424 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002425 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002426 f_shutdown_helper();
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002427}
2428
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002429private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause,
2430 template (present) RR_Cause expect_rr_cause)
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002431runs on test_CT
2432{
2433 var DchanTuple dt;
2434
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002435 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002436 var BssmapCause cause := 0;
2437 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
2438 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2439 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2440 }
2441
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002442 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 +02002443}
2444
2445/* Test that Clear Command cause codes affect the RR Channel Release cause code */
2446testcase TC_chan_rel_rr_cause() runs on test_CT {
2447 f_init(1);
2448
2449 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
2450 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
2451 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
2452 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
2453 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
2454 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
Vadim Yanitskiye18aebb2021-01-03 13:10:43 +01002455
2456 f_shutdown_helper();
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002457}
2458
Harald Welte5cd20ed2017-12-13 21:03:20 +01002459/* Test behavior if RSL EST IND for non-active channel */
2460testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
2461 timer T := 2.0;
2462
Harald Welte89d42e82017-12-17 16:42:41 +01002463 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002464
Harald Welte5cd20ed2017-12-13 21:03:20 +01002465 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002466 var octetstring l3_payload := gen_l3_valid_payload();
2467 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002468
2469 T.start;
2470 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002471 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002472 setverdict(fail, "MSC received COMPL L3 for non-active lchan");
2473 }
2474 [] BSSAP.receive {}
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002475 [] IPA_RSL[0][0].receive {}
Harald Welte5cd20ed2017-12-13 21:03:20 +01002476 [] T.timeout {}
2477 }
2478
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002479 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002480}
2481
2482/* Test behavior if RSL EST IND for invalid SAPI */
2483testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
2484 var RslChannelNr chan_nr;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002485 var octetstring l3_payload;
Harald Welte5cd20ed2017-12-13 21:03:20 +01002486
Harald Welte89d42e82017-12-17 16:42:41 +01002487 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002488
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002489 chan_nr := f_chreq_act_ack();
2490 l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002491
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002492 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002493
2494 timer T := 2.0;
2495 T.start;
2496 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002497 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002498 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
2499 }
2500 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002501 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002502 [] T.timeout {}
2503 }
2504
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002505 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002506}
2507
2508/* Test behavior if RSL EST IND for invalid SAPI */
2509testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
2510 timer T := 2.0;
2511
Harald Welte89d42e82017-12-17 16:42:41 +01002512 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002513
2514 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002515 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002516
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002517 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002518
2519 T.start;
2520 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002521 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002522 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
2523 }
2524 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002525 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002526 [] T.timeout {}
2527 }
2528
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002529 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002530}
2531
2532/* Test behavior if RSL EST IND for invalid SACCH */
2533testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
2534 timer T := 2.0;
2535
Harald Welte89d42e82017-12-17 16:42:41 +01002536 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002537
2538 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002539 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002540
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002541 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002542
2543 T.start;
2544 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002545 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002546 setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
2547 }
2548 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002549 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002550 [] T.timeout {}
2551 }
2552
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002553 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002554}
2555
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002556/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
2557private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
2558 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
2559 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2560
2561 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
2562 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
2563
2564 f_establish_fully(ass_cmd, exp_compl);
2565
2566 /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
2567 RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
2568 /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
2569 BSSAP.receive(PDU_BSSAP:{
2570 discriminator := '1'B,
2571 spare := '0000000'B,
2572 dlci := 'C3'O,
2573 lengthIndicator := ?,
2574 pdu := { dtap := '0904'O }
2575 });
2576
2577 /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
2578 for (var integer i := 0; i < 32; i := i + 1) {
2579 var octetstring l3 := '09'O & f_rnd_octstring(14);
2580 var template (value) RslLinkId link_id;
2581 var template (value) OCT1 dlci;
2582
2583 if (i mod 2 == 0) {
2584 /* SAPI0 on FACCH or SDCCH */
2585 link_id := ts_RslLinkID_DCCH(0);
2586 dlci := '80'O;
2587 } else {
2588 /* SAPI3 on SACCH */
2589 link_id := ts_RslLinkID_SACCH(3);
2590 dlci := 'C3'O;
2591 }
2592
2593 /* Send MO message: RSL -> BSSAP */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002594 f_mo_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002595 /* Send MT message: BSSAP -> RSL */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002596 f_mt_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002597 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002598 f_perform_clear();
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002599}
2600testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
2601 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2602 var MSC_ConnHdlr vc_conn;
2603
2604 f_init(1, true);
2605 f_sleep(1.0);
2606
2607 vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
2608 vc_conn.done;
2609
2610 f_shutdown_helper();
2611}
2612
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002613private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002614 template (present) myBSSMAP_Cause cause := ?,
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002615 template (present) BIT2 cc := ?,
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002616 float T_val := 2.0)
2617runs on test_CT {
2618 var BSSAP_N_DATA_ind rx_di;
2619 timer T;
2620
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002621 var template (present) BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
2622 var template (present) PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002623
2624 T.start(T_val);
2625 alt {
2626 [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
2627 var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
2628 if (not match(rx_cause, tr_cause)) {
2629 setverdict(fail, "Rx unexpected Cause IE: ",
2630 rx_cause, " vs expected ", tr_cause);
2631 }
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002632
2633 /* Who ever on the earth decided to define this field as two separate bits?!? */
2634 var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
2635 & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
2636 if (not match(rx_cc, cc)) {
2637 setverdict(fail, "Rx unexpected Control Channel type: ",
2638 rx_cc, " vs expected ", cc);
2639 }
2640
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002641 setverdict(pass);
2642 }
2643 [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
2644 setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
2645 }
2646 [] T.timeout {
2647 setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
2648 }
2649 }
2650}
2651
2652/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
2653testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002654 var RSL_Message rx_rsl;
2655 var DchanTuple dt;
2656
2657 f_init(1);
2658
2659 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002660 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002661
2662 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002663 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 +07002664 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002665 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 +07002666
2667 /* MS sends unexpected RELease INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002668 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002669 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2670 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
2671
2672 /* Clean up the connection */
2673 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002674 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002675
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002676 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002677}
2678
2679/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
2680testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002681 var RSL_Message rx_rsl;
2682 var DchanTuple dt;
2683
2684 f_init(1);
2685
2686 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002687 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002688
2689 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002690 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 +07002691 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002692 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 +07002693
2694 /* BTS sends unexpected ERROR INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002695 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002696 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2697 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
2698
2699 /* Clean up the connection */
2700 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002701 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002702
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002703 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002704}
2705
2706/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
2707testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002708 var RSL_Message rx_rsl;
2709 var DchanTuple dt;
2710
2711 f_init(1);
2712
2713 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002714 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002715
2716 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002717 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 +07002718 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002719 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 +07002720
2721 /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
2722 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
2723
2724 /* Clean up the connection */
2725 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002726 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002727
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002728 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002729}
2730
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002731/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
2732testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002733 var RSL_Message rx_rsl;
2734 var DchanTuple dt;
2735
2736 f_init(1);
2737
2738 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002739 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002740
2741 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002742 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 +07002743 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002744 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 +07002745
2746 /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002747 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Pau Espin Pedrol121f27f2022-01-12 12:02:10 +01002748 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, '10'B);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002749
2750 /* Clean up the connection */
2751 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002752 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002753
2754 f_shutdown_helper();
2755}
2756
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002757testcase TC_si_default() runs on test_CT {
2758 f_init(0);
2759 f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002760 f_shutdown_helper();
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002761}
Harald Welte4003d112017-12-09 22:35:39 +01002762
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002763/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
2764 * the entire value range. This function provides the same EARFCN numbers for the same earfcn_index */
2765private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uint16_t
2766{
2767 select (earfcn_index) {
2768 case (0) {
2769 /* E-ARFCN 111 is already added in the osmo-bsc.cfg */
2770 return 111;
2771 }
2772 case (1) {
2773 return 1;
2774 }
2775 case (2) {
2776 return 0;
2777 }
2778 case (3) {
2779 return 65535;
2780 }
2781 case else {
2782 return 23 * (earfcn_index - 3);
2783 }
2784 }
2785}
2786
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002787function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
2788 template CellSelIndValue expect_cells := omit) runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002789
2790 f_init(0);
2791
2792 /* E-ARFCN 111 is already added in the osmo-bsc.cfg, so only add more arfcns if total_earfcns > 1 */
2793 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002794 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2795 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002796 }
2797
2798 f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
2799
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002800 if (not istemplatekind(expect_cells, "omit")) {
2801 /* Also check that RR Channel Release contains these EARFCNs.
2802 * (copied code from TC_chan_rel_hard_clear_csfb) */
2803 var BSSAP_N_DATA_ind rx_di;
2804 var DchanTuple dt;
2805
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002806 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrold0046312021-04-19 16:35:58 +02002807 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2808 * yet when generating the EUTRAN neigh list in RR CHannel Release) */
2809 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002810
2811 /* Instruct BSC to clear channel */
2812 var BssmapCause cause := 0;
2813 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2814
2815 /* expect Clear Complete from BSC on A */
2816 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2817 /* release the SCCP connection */
2818 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2819 }
2820
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002821 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := expect_cells);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002822 }
2823
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002824 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002825 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 +02002826 }
2827}
2828
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002829private function f_tr_si2quater_earfcns(integer count) return template SI2quaterRestOctetsList
2830{
2831 var template SI2quaterRestOctetsList si2quater := {};
2832 var integer si2quater_count := (count + 2) / 3;
2833
2834 for (var integer i := 0; i < count; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002835 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002836 var integer index := i / 3;
2837 var integer earfcn_index := i mod 3;
2838 if (index >= lengthof(si2quater)) {
2839 si2quater[index] := tr_SI2quaterRestOctets_EUTRAN(index := index, count := si2quater_count - 1);
2840 }
2841 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);
2842 }
2843
2844 return si2quater;
2845}
2846
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002847private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
2848{
2849 var template CellSelIndValue_EUTRAN_Descrs cells := {};
2850
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002851 /* the lte neighbors must match the config & vty to pass this test */
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002852 for (var integer i := 0; i < count; i := i + 1) {
2853 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002854 cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002855 }
2856
2857 return tr_CellSelIndValue_EUTRAN(cells);
2858}
2859
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002860private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
2861{
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002862 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrol8ab62e42020-12-18 16:19:11 +01002863 sic.si2quater := f_tr_si2quater_earfcns(n);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002864 var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
2865 f_test_si2quater(n, sic, cells);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002866}
2867
2868testcase TC_si2quater_2_earfcns() runs on test_CT {
2869 f_tc_si2quater_n_earfcns(2);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002870 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002871}
2872
2873testcase TC_si2quater_3_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002874 f_tc_si2quater_n_earfcns(3);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002875 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002876}
2877
2878testcase TC_si2quater_4_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002879 f_tc_si2quater_n_earfcns(4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002880 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002881}
2882
2883testcase TC_si2quater_5_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002884 f_tc_si2quater_n_earfcns(5);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002885 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002886}
2887
2888testcase TC_si2quater_6_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002889 f_tc_si2quater_n_earfcns(6);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002890 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002891}
2892
2893testcase TC_si2quater_12_earfcns() runs on test_CT {
2894 f_tc_si2quater_n_earfcns(12);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002895 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002896}
2897
2898testcase TC_si2quater_23_earfcns() runs on test_CT {
2899 f_tc_si2quater_n_earfcns(23);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002900 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002901}
2902
2903testcase TC_si2quater_32_earfcns() runs on test_CT {
2904 f_tc_si2quater_n_earfcns(32);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002905 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002906}
2907
2908testcase TC_si2quater_33_earfcns() runs on test_CT {
2909 f_tc_si2quater_n_earfcns(33);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002910 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002911}
2912
2913testcase TC_si2quater_42_earfcns() runs on test_CT {
2914 f_tc_si2quater_n_earfcns(42);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002915 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002916}
2917
2918testcase TC_si2quater_48_earfcns() runs on test_CT {
2919 f_tc_si2quater_n_earfcns(48);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002920 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002921}
2922
2923/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
2924 * 48 EARFCNs. */
2925testcase TC_si2quater_49_earfcns() runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002926 var template SystemInformationConfig sic := SystemInformationConfig_default;
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002927 sic.si2quater := f_tr_si2quater_earfcns(48); /* 48, not 49! */
2928 f_init(0);
2929
2930 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002931 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2932 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002933 }
2934
2935 /* The 49th EARFCN no longer fits, expect VTY error */
2936 f_vty_enter_cfg_bts(BSCVTY, 0);
2937 var charstring vty_error;
2938 vty_error := f_vty_transceive_ret(BSCVTY,
2939 "si2quater neighbor-list add earfcn 70 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3")
2940 f_vty_transceive(BSCVTY, "end");
2941
2942 if (f_strstr(vty_error, "Unable to add ARFCN 70") >= 0) {
2943 log("Got expected VTY error: ", vty_error);
2944 setverdict(pass);
2945 } else {
2946 setverdict(fail, "Expected the 49th EUTRAN ARFCN to be rejected by vty config, got: ", vty_error);
2947 }
2948
2949 f_init_bts_and_check_sysinfo(0, expect_si := sic);
2950
2951 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002952 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 +02002953 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002954 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002955}
2956
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002957private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
2958{
2959 var uint8_t count := 0;
2960 for (var integer i := 5; i < 16; i := i + 1) {
2961 if (acc[i] == '0'B) { /* the list marks barred, we count allowed */
2962 count := count + 1;
2963 }
2964 }
2965 return count;
2966}
2967
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002968private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return SystemInformationType1
2969{
2970 var ASP_RSL_Unitdata rx_rsl_ud;
2971 var SystemInformationType1 last_si1;
2972
2973 timer T := 30.0;
2974 T.start;
2975 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002976 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
2977 tr_RSL_BCCH_INFO,
2978 tr_RSL_NO_SACCH_FILL,
2979 tr_RSL_SACCH_FILL))) -> value rx_rsl_ud {
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002980 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
2981 if (g_system_information[rsl_idx].si1 == omit) {
2982 repeat;
2983 }
2984 last_si1 := g_system_information[rsl_idx].si1;
2985 g_system_information[rsl_idx].si1 := omit;
2986 T.stop;
2987 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002988 [] IPA_RSL[rsl_idx][0].receive { repeat; }
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002989 [] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
2990 }
2991 return last_si1;
2992}
2993
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002994/* verify ACC rotate feature */
2995testcase TC_si_acc_rotate() runs on test_CT {
2996 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002997 var SystemInformationType1 last_si1;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002998 var AccessControlClass acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002999 var uint8_t count;
3000 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3001
3002 f_init(0, guard_timeout := 60.0);
3003
3004 f_bts_0_cfg(BSCVTY, {"rach access-control-class 5 barred",
3005 "access-control-class-rotate 3",
3006 "access-control-class-rotate-quantum 1"});
3007
3008 /* Init and get first sysinfo */
3009 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3010
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003011 for (var integer i:= 0; i < 20; i := i + 1) {
3012 last_si1 := f_recv_next_si1(0);
3013 acc := last_si1.rach_control.acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003014 count := f_acc09_count_allowed(acc);
3015 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3016
3017 if (count != 3) {
3018 log("RSL: EXPECTED SI ACC len=3");
3019 setverdict(fail, "received SI does not match expectations");
3020 break;
3021 }
3022
3023 for (var integer j := 0; j < 10; j := j + 1) {
3024 if (acc[16 - 1 - j] == '0'B) { /* the list marks barred, we count allowed */
3025 times_allowed[j] := times_allowed[j] + 1;
3026 }
3027 }
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003028 }
3029
3030 for (var integer j := 0; j < 10; j := j + 1) {
3031 log("ACC", j, " allowed ", times_allowed[j], " times" );
3032 if (j != 5 and times_allowed[j] < 3) {
3033 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " < 1 times");
3034 } else if (j == 5 and times_allowed[j] > 0) {
3035 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " > 0 times");
3036 }
3037 }
3038
3039 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3040 "rach access-control-class 5 allowed"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003041 f_shutdown_helper();
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003042}
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02003043
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003044/* verify ACC startup ramp+rotate feature */
3045testcase TC_si_acc_ramp_rotate() runs on test_CT {
3046 var template SystemInformationConfig sic := SystemInformationConfig_default;
3047 var SystemInformationType1 last_si1;
3048 var AccessControlClass acc;
3049 var ASP_RSL_Unitdata rx_rsl_ud;
3050 var uint8_t count;
3051 var uint8_t prev_count;
3052 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3053
3054 f_init(0, guard_timeout := 80.0);
3055
3056 f_bts_0_cfg(BSCVTY, {"rach access-control-class 4 barred",
3057 "access-control-class-rotate 0",
3058 "access-control-class-rotate-quantum 1",
3059 "access-control-class-ramping",
3060 "access-control-class-ramping-step-interval 5",
3061 "access-control-class-ramping-step-size 5"});
3062
3063 /* Init and get first sysinfo */
3064 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3065 last_si1 := g_system_information[0].si1;
3066 acc := last_si1.rach_control.acc;
3067 count := f_acc09_count_allowed(acc);
3068 /* Adm subset size was set to 0 above, so wait until all ACC are barred */
3069 while (count > 0) {
3070 last_si1 := f_recv_next_si1(0);
3071 acc := last_si1.rach_control.acc;
3072 count := f_acc09_count_allowed(acc);
3073 log("RSL: wait len()=0: GOT SI1 ACC len=", count, ": ", acc);
3074 }
3075
3076 /* Increase adm subset size, we should see ramping start up */
3077 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10"});
3078 prev_count := 0;
3079 while (true) {
3080 last_si1 := f_recv_next_si1(0);
3081 acc := last_si1.rach_control.acc;
3082 count := f_acc09_count_allowed(acc);
3083 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3084
3085 if (prev_count > count) {
3086 setverdict(fail, "ACC allowed count dropped while expecting grow: ", prev_count, " -> ", count);
3087 break;
3088 }
3089
3090 if (count == 9) {
3091 break; /* Maximum reached (10 - 1 perm barred), done here */
3092 }
3093
3094 prev_count := count;
3095 }
3096
3097 setverdict(pass);
3098
3099 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3100 "rach access-control-class 4 allowed",
3101 "no access-control-class-ramping"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003102 f_shutdown_helper();
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003103}
3104
Oliver Smith45a6dd32023-09-27 10:52:50 +02003105/* Verify NCC Permitted in System Information Type 2
3106 * 3GPP TS 44.018 § 10.5.2.27 */
3107testcase TC_si2_ncc_permitted() runs on test_CT {
3108 var ASP_RSL_Unitdata rx_rsl_ud;
3109 timer T := 5.0;
3110 var BIT8 exp;
3111
3112 f_init_vty();
3113
3114 /* Set NCC Permitted to 6 7 8 */
3115 f_vty_enter_cfg_bts(BSCVTY, 0);
3116 f_vty_transceive(BSCVTY, "ncc-permitted 6 7 8");
3117 f_vty_transceive(BSCVTY, "end");
3118 exp := '11100000'B;
3119
3120 f_init(1);
3121 T.start;
3122
3123 /* Check value in SI 2 */
3124 alt {
3125 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO(RSL_SYSTEM_INFO_2))) -> value rx_rsl_ud {
3126 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
3127 var SystemInformation si := dec_SystemInformation(ie.other.payload);
3128
3129 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_2) {
3130 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
3131 repeat;
3132 }
3133
3134 if (si.payload.si2.ncc_permitted != exp) {
3135 setverdict(fail, "NCC Permitted is ", si.payload.si2.ncc_permitted, " but expected ", exp);
3136 break;
3137 }
3138
3139 }
3140 [] IPA_RSL[0][0].receive { repeat; }
3141 [] T.timeout {
3142 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI2)");
3143 }
3144 }
3145
3146 /* Reset NCC Permitted to default (all permitted). This is already
3147 * getting tested in TC_si_default(). */
3148 f_vty_enter_cfg_bts(BSCVTY, 0);
3149 f_vty_transceive(BSCVTY, "ncc-permitted all");
3150 f_vty_transceive(BSCVTY, "end");
3151
3152 f_shutdown_helper();
3153}
3154
Harald Welte4003d112017-12-09 22:35:39 +01003155testcase TC_ctrl_msc_connection_status() runs on test_CT {
3156 var charstring ctrl_resp;
3157
Harald Welte89d42e82017-12-17 16:42:41 +01003158 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003159
3160 /* See https://osmocom.org/issues/2729 */
3161 f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003162 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01003163}
3164
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003165testcase TC_ctrl_msc0_connection_status() runs on test_CT {
3166 var charstring ctrl_resp;
3167
3168 f_init(1);
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003169
3170 f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003171 f_shutdown_helper();
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003172}
3173
Neels Hofmeyr0bc470d2021-08-21 13:37:13 +02003174/* Verify correct stats on the number of configured and connected MSCs */
3175private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
3176 g_pars := f_gen_test_hdlr_pars();
3177 var StatsDExpects expect := {
3178 { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
3179 { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
3180 };
3181 f_statsd_expect(expect);
3182}
3183
3184private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
3185{
3186 var MSC_ConnHdlr vc_conn;
3187
3188 f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
3189 f_sleep(1.0);
3190 vc_conn := f_start_handler(tc_fn);
3191 vc_conn.done;
3192
3193 /* Also verify stat exposed on CTRL interface */
3194 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
3195 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
3196
3197 f_shutdown_helper();
3198}
3199
3200/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
3201private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
3202 f_tc_stat_num_msc_connected_msc_connhdlr(1);
3203}
3204testcase TC_stat_num_msc_connected_1() runs on test_CT {
3205 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
3206}
3207
3208/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
3209private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
3210 f_tc_stat_num_msc_connected_msc_connhdlr(2);
3211}
3212testcase TC_stat_num_msc_connected_2() runs on test_CT {
3213 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
3214}
3215
3216/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
3217private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
3218 f_tc_stat_num_msc_connected_msc_connhdlr(3);
3219}
3220testcase TC_stat_num_msc_connected_3() runs on test_CT {
3221 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
3222}
3223
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003224/* Verify correct stats on the number of configured and connected MSCs */
3225private 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 +06003226 var integer num_trx_connected := 0;
3227 var integer num_trx_total := 0;
3228
3229 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3230 var integer trx_num := c_BtsParams[i].trx_num;
3231 num_trx_total := num_trx_total + trx_num;
3232 if (i < expect_num_bts_connected) {
3233 num_trx_connected := num_trx_connected + trx_num;
3234 }
3235 }
3236
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003237 var StatsDExpects expect := {
3238 { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
3239 { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3240 { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003241 { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := num_trx_connected, max := num_trx_connected },
3242 { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := num_trx_total, max := num_trx_total }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003243 };
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003244
3245 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003246 f_statsd_expect(expect);
3247}
3248
3249private 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 +06003250 var integer num_trx_connected := 0;
3251 var integer num_trx_total := 0;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003252 var MSC_ConnHdlr vc_conn;
3253
3254 f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
3255 f_sleep(1.0);
3256 vc_conn := f_start_handler(tc_fn);
3257 vc_conn.done;
3258
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003259 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3260 var integer trx_num := c_BtsParams[i].trx_num;
3261 num_trx_total := num_trx_total + trx_num;
3262 if (i < nr_bts) {
3263 num_trx_connected := num_trx_connected + trx_num;
3264 }
3265 }
3266
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003267 /* Also verify stat exposed on CTRL interface */
3268 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
3269 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 +06003270 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(num_trx_connected));
3271 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 +02003272
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003273 /* Verify rf_states exposed on CTRL interface */
3274 var charstring expect_net_rf_states := "";
3275 for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003276 var charstring expect_bts_rf_states := "";
3277
3278 for (var integer j := 0; j < c_BtsParams[i].trx_num; j := j + 1) {
3279 expect_bts_rf_states := expect_bts_rf_states &
3280 int2str(i) & "," & int2str(j) & ",";
3281 if (i < NUM_BTS) {
3282 /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
3283 expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
3284 } else {
3285 /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
3286 expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
3287 }
3288 /* The RF policy is still global in osmo-bsc, i.e. always "on" */
3289 expect_bts_rf_states := expect_bts_rf_states & "on,";
3290 if (i < nr_bts) {
3291 /* For BTS where RSL is connected, the RSL state will be "up" */
3292 expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
3293 } else {
3294 expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
3295 }
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003296 }
3297
3298 f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
3299 expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
3300 }
3301 f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
3302
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003303 f_shutdown_helper();
3304}
3305
3306/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
3307private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
3308 f_tc_stat_num_bts_connected_msc_connhdlr(1);
3309}
3310testcase TC_stat_num_bts_connected_1() runs on test_CT {
3311 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
3312}
3313
3314/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
3315private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
3316 f_tc_stat_num_bts_connected_msc_connhdlr(2);
3317}
3318testcase TC_stat_num_bts_connected_2() runs on test_CT {
3319 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
3320}
3321
3322/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
3323private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
3324 f_tc_stat_num_bts_connected_msc_connhdlr(3);
3325}
3326testcase TC_stat_num_bts_connected_3() runs on test_CT {
3327 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
3328}
3329
Harald Welte4003d112017-12-09 22:35:39 +01003330testcase TC_ctrl() runs on test_CT {
3331 var charstring ctrl_resp;
3332
Harald Welte89d42e82017-12-17 16:42:41 +01003333 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003334
3335 /* all below values must match the osmo-bsc.cfg config file used */
3336
Harald Welte6a129692018-03-17 17:30:14 +01003337 f_ctrl_get_exp(IPA_CTRL, "mcc", "001");
3338 f_ctrl_get_exp(IPA_CTRL, "mnc", "01");
Oliver Smith75aa0202019-08-19 14:17:50 +02003339 f_ctrl_get_exp(IPA_CTRL, "number-of-bts", "4");
Harald Welte4003d112017-12-09 22:35:39 +01003340
3341 var integer bts_nr := 0;
3342 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "location-area-code", "1");
3343 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "cell-identity", "0");
3344 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "oml-connection-state", "connected");
3345 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "gprs-mode", "gprs");
3346 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "rf_state", "operational,unlocked,on");
3347 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "arfcn", "871");
3348 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "max-power-reduction", "20");
3349
3350 var integer uptime := str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime"));
3351 f_sleep(2.0);
3352 if (str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime")) < uptime+1) {
3353 setverdict(fail, "oml-uptime not incrementing as expected");
3354 }
3355 /* TODO: Disconnect RSL, imply that OML is disconnected and check for uptime zero? */
3356
3357 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
3358
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003359 f_shutdown_helper();
Harald Welte96c94412017-12-09 03:12:45 +01003360}
3361
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003362/* Verify that Upon receival of SET "location", BSC forwards a TRAP
3363 "location-state" over the SCCPlite IPA conn */
3364testcase TC_ctrl_location() runs on test_CT {
3365 var MSC_ConnHdlr vc_conn;
3366 var integer bts_nr := 0;
3367
3368 f_init(1, true);
3369 f_sleep(1.0);
3370
3371 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234567,fix3d,0.340000,0.560000,0.780000");
3372 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3373 "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
3374
3375 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "1");
3376 f_sleep(2.0);
3377
3378 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234888,fix3d,0.350000,0.570000,0.790000");
3379 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3380 "1234888,fix3d,0.350000,0.570000,0.790000,operational,locked,off,001,01");
3381
3382 /* should match the one from config */
3383 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
3384
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003385 f_shutdown_helper();
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003386}
3387
Harald Welte6f521d82017-12-11 19:52:02 +01003388
3389/***********************************************************************
3390 * Paging Testing
3391 ***********************************************************************/
3392
3393type record Cell_Identity {
3394 GsmMcc mcc,
3395 GsmMnc mnc,
3396 GsmLac lac,
3397 GsmCellId ci
3398};
Harald Welte24135bd2018-03-17 19:27:53 +01003399private const Cell_Identity cid := { '001'H, '01'H, 1, 0 };
Stefan Sperling049a86e2018-03-20 15:51:00 +01003400private const Cell_Identity unknown_cid := { '678'H, 'f90'H, 1, 0 };
Harald Welte6f521d82017-12-11 19:52:02 +01003401
Harald Welte5d1a2202017-12-13 19:51:29 +01003402type set of integer BtsIdList;
3403
3404private function f_bts_in_list(integer bts_id, BtsIdList bts_ids) return boolean {
3405 for (var integer j := 0; j < sizeof(bts_ids); j := j + 1) {
3406 if (bts_id == bts_ids[j]) {
3407 return true;
3408 }
3409 }
3410 return false;
3411}
Harald Welte6f521d82017-12-11 19:52:02 +01003412
3413/* core paging test helper function; used by most paging test cases */
3414private function f_pageing_helper(hexstring imsi,
3415 template BSSMAP_FIELD_CellIdentificationList cid_list,
Harald Welte5d1a2202017-12-13 19:51:29 +01003416 BtsIdList bts_ids := { 0 },
Harald Welte6f521d82017-12-11 19:52:02 +01003417 template RSL_ChanNeeded rsl_chneed := omit,
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003418 template (omit) OCT4 tmsi := omit) runs on test_CT
Harald Welte6f521d82017-12-11 19:52:02 +01003419{
3420 var template BSSMAP_IE_ChannelNeeded bssmap_chneed;
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003421 var template MobileIdentityV mi;
Harald Welte6f521d82017-12-11 19:52:02 +01003422 var RSL_Message rx_rsl;
3423 var integer paging_group := hex2int(imsi[lengthof(imsi)-1]);
Harald Welte5d1a2202017-12-13 19:51:29 +01003424 var integer i;
Harald Welte6f521d82017-12-11 19:52:02 +01003425
3426 f_init();
Harald Welte6f521d82017-12-11 19:52:02 +01003427
3428 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Harald Weltec3068592018-03-17 19:55:31 +01003429 for (i := 0; i < NUM_BTS; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003430 IPA_RSL[i][0].clear;
Harald Welte5d1a2202017-12-13 19:51:29 +01003431 }
Harald Welte6f521d82017-12-11 19:52:02 +01003432
3433 if (isvalue(rsl_chneed)) {
3434 /* The values of 08.08 3.2.2.36 and 08.58 9.3.40 are luckily identical */
3435 bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
3436 } else {
3437 bssmap_chneed := omit;
3438 }
3439
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003440 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
3441 ts_BSSMAP_Paging(imsi, cid_list, tmsi, bssmap_chneed)));
Harald Welte6f521d82017-12-11 19:52:02 +01003442
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003443 if (not istemplatekind(tmsi, "omit")) {
3444 mi := t_MI_TMSI(tmsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003445 } else {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003446 mi := tr_MI_IMSI(imsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003447 }
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003448
Harald Welte5d1a2202017-12-13 19:51:29 +01003449 for (i := 0; i < sizeof(bts_ids); i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003450 rx_rsl := f_exp_ipa_rx(tr_RSL_PAGING_CMD(mi), idx := {bts_ids[i], 0});
Harald Welte5d1a2202017-12-13 19:51:29 +01003451 /* check channel type, paging group */
3452 if (rx_rsl.ies[1].body.paging_group != paging_group) {
3453 setverdict(fail, "Paging for wrong paging group");
3454 }
3455 if (ispresent(rsl_chneed) and
3456 rx_rsl.ies[3].body.chan_needed.chan_needed != valueof(rsl_chneed)) {
3457 setverdict(fail, "RSL Channel Needed != BSSMAP Channel Needed");
3458 }
Harald Welte6f521d82017-12-11 19:52:02 +01003459 }
Harald Welte2fccd982018-01-31 15:48:19 +01003460 f_sleep(2.0);
Harald Welte5d1a2202017-12-13 19:51:29 +01003461 /* do a quick check on all not-included BTSs if they received paging */
3462 for (i := 0; i < NUM_BTS; i := i + 1) {
3463 timer T := 0.1;
3464 if (f_bts_in_list(i, bts_ids)) {
3465 continue;
3466 }
3467 T.start;
3468 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003469 [] IPA_RSL[i][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003470 setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
3471 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003472 [] IPA_RSL[i][0].receive { repeat; }
Harald Welte5d1a2202017-12-13 19:51:29 +01003473 [] T.timeout { }
3474 }
Harald Welte6f521d82017-12-11 19:52:02 +01003475 }
3476
3477 setverdict(pass);
3478}
3479
Harald Welte5d1a2202017-12-13 19:51:29 +01003480const BtsIdList c_BtsId_all := { 0, 1, 2 };
Harald Welte751d3eb2018-01-31 15:51:06 +01003481const BtsIdList c_BtsId_none := { };
Harald Welte5d1a2202017-12-13 19:51:29 +01003482const BtsIdList c_BtsId_LAC1 := { 0, 1 };
3483const BtsIdList c_BtsId_LAC2 := { 2 };
3484
Harald Welte6f521d82017-12-11 19:52:02 +01003485/* PAGING by IMSI + TMSI */
3486testcase TC_paging_imsi_nochan() runs on test_CT {
3487 var BSSMAP_FIELD_CellIdentificationList cid_list;
3488 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Philipp Maier8c04b0a2018-02-23 13:48:48 +01003489 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, omit);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003490 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003491}
3492
3493/* PAGING by IMSI + TMSI */
3494testcase TC_paging_tmsi_nochan() runs on test_CT {
3495 var BSSMAP_FIELD_CellIdentificationList cid_list;
3496 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003497 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, 'A1B2C301'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003498 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003499}
3500
3501/* Paging with different "channel needed' values */
3502testcase TC_paging_tmsi_any() runs on test_CT {
3503 var BSSMAP_FIELD_CellIdentificationList cid_list;
3504 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003505 f_pageing_helper('001010100000002'H, cid_list, c_BtsId_all, RSL_CHANNEED_ANY, 'A1B2C302'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003506 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003507}
3508testcase TC_paging_tmsi_sdcch() runs on test_CT {
3509 var BSSMAP_FIELD_CellIdentificationList cid_list;
3510 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003511 f_pageing_helper('001010100000003'H, cid_list, c_BtsId_all, RSL_CHANNEED_SDCCH, 'A1B2C303'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003512 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003513}
3514testcase TC_paging_tmsi_tch_f() runs on test_CT {
3515 var BSSMAP_FIELD_CellIdentificationList cid_list;
3516 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003517 f_pageing_helper('001010000000004'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_F, 'A1B2C304'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003518 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003519}
3520testcase TC_paging_tmsi_tch_hf() runs on test_CT {
3521 var BSSMAP_FIELD_CellIdentificationList cid_list;
3522 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003523 f_pageing_helper('001010000000005'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_ForH, 'A1B2C305'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003524 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003525}
3526
3527/* Paging by CGI */
3528testcase TC_paging_imsi_nochan_cgi() runs on test_CT {
3529 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3530 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(cid.mcc, cid.mnc, cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003531 f_pageing_helper('001010000000006'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003532 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003533}
3534
3535/* Paging by LAC+CI */
3536testcase TC_paging_imsi_nochan_lac_ci() runs on test_CT {
3537 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3538 cid_list := { cIl_LAC_CI := { ts_BSSMAP_CI_LAC_CI(cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003539 f_pageing_helper('001010000000007'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003540 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003541}
3542
3543/* Paging by CI */
3544testcase TC_paging_imsi_nochan_ci() runs on test_CT {
3545 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3546 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003547 f_pageing_helper('001010000000008'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003548 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003549}
3550
3551/* Paging by LAI */
3552testcase TC_paging_imsi_nochan_lai() runs on test_CT {
3553 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3554 cid_list := { cIl_LAI := { ts_BSSMAP_CI_LAI(cid.mcc, cid.mnc, cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003555 f_pageing_helper('001010000000009'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003556 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003557}
3558
3559/* Paging by LAC */
3560testcase TC_paging_imsi_nochan_lac() runs on test_CT {
3561 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3562 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003563 f_pageing_helper('001010000000010'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003564 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003565}
3566
3567/* Paging by "all in BSS" */
3568testcase TC_paging_imsi_nochan_all() runs on test_CT {
3569 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3570 cid_list := { cIl_allInBSS := ''O };
Harald Welte5d1a2202017-12-13 19:51:29 +01003571 f_pageing_helper('001010000000011'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003572 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003573}
3574
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003575/* Paging by PLMN+LAC+RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003576testcase TC_paging_imsi_nochan_plmn_lac_rnc() runs on test_CT {
3577 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3578 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 +01003579 f_pageing_helper('001010000000012'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003580 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003581}
Harald Welte6f521d82017-12-11 19:52:02 +01003582
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003583/* Paging by RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003584testcase TC_paging_imsi_nochan_rnc() runs on test_CT {
3585 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3586 cid_list := { cIl_RNC := { int2oct(13, 2) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003587 f_pageing_helper('001010000000013'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003588 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003589}
3590
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003591/* Paging by LAC+RNC; We do not implement; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003592testcase TC_paging_imsi_nochan_lac_rnc() runs on test_CT {
3593 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3594 cid_list := { cIl_LAC_RNC := { ts_BSSMAP_CI_LAC_RNC(cid.lac, 14) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003595 f_pageing_helper('001010000000014'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003596 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003597}
3598
Harald Welte6f521d82017-12-11 19:52:02 +01003599/* Paging on multiple cells (multiple entries in list): Verify all of them page */
Harald Welte751d3eb2018-01-31 15:51:06 +01003600testcase TC_paging_imsi_nochan_lacs() runs on test_CT {
3601 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3602 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(1), ts_BSSMAP_CI_LAC(2) } };
3603 f_pageing_helper('001010000000015'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003604 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003605}
3606
3607/* Paging on empty list: Verify none of them page */
3608testcase TC_paging_imsi_nochan_lacs_empty() runs on test_CT {
3609 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3610 cid_list := { cIl_LAC := { } };
3611 f_pageing_helper('001010000000016'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003612 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003613}
3614
Stefan Sperling049a86e2018-03-20 15:51:00 +01003615/* Paging by CGI with unknown MCC/MNC: Verify nothing is paged. */
3616testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
3617 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3618 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(unknown_cid.mcc, unknown_cid.mnc, unknown_cid.lac, unknown_cid.ci) } };
3619 f_pageing_helper('001010000000006'H, cid_list, c_BtsId_none);
3620 f_shutdown_helper();
3621}
3622
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +01003623/* Send paging response containing invalid (wrongly formatted) MobileIdentity IE. */
3624testcase TC_paging_imsi_nochan_ci_resp_invalid_mi() runs on test_CT {
3625 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3626 var BSSAP_N_CONNECT_ind rx_c_ind;
3627 var DchanTuple dt;
3628 var octetstring rr_pag_resp := '06270003535992617965720000'O;
3629 /* { 06 27 } is { GSM48_PDISC_RR, GSM48_MT_RR_PAG_RESP }
3630 * see 3GPP TS 44.018, table 9.1.25.1
3631 * { 00 } or { 01 } is CKSN + Spare Half Octet, not important
3632 * { 03 53 59 92 } is Mobile Station Classmark
3633 * { 61 79 65 72 00 00 } is the invalid Mobile Identity IE (3GPP TS 24.008, 10.5.1.4),
3634 * Length is 0x61 (97 in decimal).
3635 */
3636
3637 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
3638 f_pageing_helper('001010000000008'H, cid_list, { 0 });
3639
3640 /* Send CHAN RQD and wait for allocation; acknowledge it */
3641 dt.rsl_chan_nr := f_chreq_act_ack();
3642 dt.idx := {0, 0};
3643
3644 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
3645 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), rr_pag_resp));
3646
3647 /* Expevct a CR with a matching Paging response on the A-Interface */
3648 timer T := 5.0;
3649 T.start;
3650 alt {
3651 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
3652 setverdict(pass);
3653 dt.sccp_conn_id := rx_c_ind.connectionId;
3654 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
3655 }
3656 [] BSSAP.receive {
3657 setverdict(fail, "Received unexpected message on A-Interface!");
3658 }
3659 [] T.timeout {
3660 setverdict(fail, "Received nothing on A-Interface!");
3661 }
3662 }
3663
3664 f_perform_clear_test_ct(dt);
3665 f_shutdown_helper();
3666}
3667
Harald Welte6f521d82017-12-11 19:52:02 +01003668/* Verify paging retransmission interval + count */
3669/* Verify paging stops after channel establishment */
Harald Welte6f521d82017-12-11 19:52:02 +01003670/* Test behavior under paging overload */
Harald Welteae026692017-12-09 01:03:01 +01003671
Harald Weltee65d40e2017-12-13 00:09:06 +01003672/* Verify PCH load */
3673testcase TC_paging_imsi_load() runs on test_CT {
3674 var BSSMAP_FIELD_CellIdentificationList cid_list;
3675 timer T := 4.0;
Harald Welte2caa1062018-03-17 18:19:05 +01003676 timer T_retrans := 1.0;
Harald Weltee65d40e2017-12-13 00:09:06 +01003677 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003678 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Weltee65d40e2017-12-13 00:09:06 +01003679
3680 /* tell BSC there is no paging space anymore */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003681 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte3b57ab52018-03-17 18:01:10 +01003682 f_sleep(0.2);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003683 IPA_RSL[0][0].clear;
Harald Weltee65d40e2017-12-13 00:09:06 +01003684
3685 /* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
3686 * there would be 8 retransmissions during 4 seconds */
3687 T.start;
Harald Welte2caa1062018-03-17 18:19:05 +01003688 T_retrans.start;
Harald Weltee65d40e2017-12-13 00:09:06 +01003689 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003690 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Weltee65d40e2017-12-13 00:09:06 +01003691 setverdict(fail, "Received PAGING after LOAD_IND(0)");
Daniel Willmannafce8662018-07-06 23:11:32 +02003692 mtc.stop;
Harald Weltee65d40e2017-12-13 00:09:06 +01003693 }
Harald Welte2caa1062018-03-17 18:19:05 +01003694 [] T_retrans.timeout {
3695 /* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003696 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte2caa1062018-03-17 18:19:05 +01003697 T_retrans.start;
3698 repeat;
3699 }
Harald Weltee65d40e2017-12-13 00:09:06 +01003700 [] T.timeout {
3701 setverdict(pass);
3702 }
3703 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003704
3705 f_shutdown_helper();
Harald Weltee65d40e2017-12-13 00:09:06 +01003706}
3707
Harald Welte235ebf12017-12-15 14:18:16 +01003708/* Verify Paging Counter */
Harald Welte1ff69992017-12-14 12:31:17 +01003709testcase TC_paging_counter() runs on test_CT {
3710 var BSSMAP_FIELD_CellIdentificationList cid_list;
3711 timer T := 4.0;
3712 var integer i;
3713 var integer paging_attempted_bsc;
3714 var integer paging_attempted_bts[NUM_BTS];
Oliver Smith8b343d32021-11-26 13:01:42 +01003715 var integer paging_expired_bsc;
Harald Welte1ff69992017-12-14 12:31:17 +01003716 var integer paging_expired_bts[NUM_BTS];
3717 cid_list := valueof(ts_BSSMAP_CIL_noCell);
3718
3719 f_init();
3720
3721 /* read counters before paging */
3722 paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003723 paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
Harald Welte1ff69992017-12-14 12:31:17 +01003724 for (i := 0; i < NUM_BTS; i := i+1) {
3725 paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
3726 paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
3727 }
3728
3729 f_pageing_helper('001230000000001'H, cid_list, c_BtsId_all);
3730
3731 /* expect the attempted pages on BSC and each BTSs to have incremented by one */
3732 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", paging_attempted_bsc+1);
3733 for (i := 0; i < NUM_BTS; i := i+1) {
3734 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted",
3735 paging_attempted_bts[i]+1);
3736 }
3737
3738 /* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
3739 f_sleep(12.0);
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003740 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
Harald Welte1ff69992017-12-14 12:31:17 +01003741 for (i := 0; i < NUM_BTS; i := i+1) {
3742 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
3743 paging_expired_bts[i]+1);
3744 }
Harald Welte1ff69992017-12-14 12:31:17 +01003745
Philipp Maier282ca4b2018-02-27 17:17:00 +01003746 f_shutdown_helper();
Harald Welte1ff69992017-12-14 12:31:17 +01003747}
3748
3749
Harald Welte10985002017-12-12 09:29:15 +01003750/* Verify paging stops after A-RESET */
3751testcase TC_paging_imsi_a_reset() runs on test_CT {
3752 var BSSMAP_FIELD_CellIdentificationList cid_list;
3753 timer T := 3.0;
3754 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003755 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Welte10985002017-12-12 09:29:15 +01003756
3757 /* Perform a BSSMAP Reset and wait for ACK */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003758 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 +01003759 alt {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003760 [] 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 +01003761 [] BSSAP.receive { repeat; }
3762 }
3763
Daniel Willmanncbef3982018-07-30 09:22:40 +02003764 /* Wait to avoid a possible race condition if a paging message is
3765 * received right before the reset ACK. */
3766 f_sleep(0.2);
3767
Harald Welte10985002017-12-12 09:29:15 +01003768 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Philipp Maier1e6b4422018-02-23 14:02:13 +01003769 for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003770 IPA_RSL[i][0].clear;
Philipp Maier1e6b4422018-02-23 14:02:13 +01003771 }
Harald Welte10985002017-12-12 09:29:15 +01003772
3773 /* Wait for 3 seconds if any more PAGING CMD are received on RSL */
3774 T.start;
3775 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003776 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte10985002017-12-12 09:29:15 +01003777 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003778 mtc.stop;
Harald Welte10985002017-12-12 09:29:15 +01003779 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003780 [] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003781 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003782 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003783 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003784 [] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003785 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003786 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003787 }
Harald Welte10985002017-12-12 09:29:15 +01003788 [] T.timeout {
3789 setverdict(pass);
3790 }
3791 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003792
3793 f_shutdown_helper();
Harald Welte10985002017-12-12 09:29:15 +01003794}
Harald Welteae026692017-12-09 01:03:01 +01003795
Philipp Maierf45824a2019-08-14 14:44:10 +02003796/* Verify how we handle unsolicited Paging Response. In case of an unsolicit
3797 * paging response we can not know which MSC is in charge, so we will blindly
3798 * pick the first configured MSC. This behavior is required in order to make
3799 * MT-CSFB calls working because in those cases the BSC can not know that the
3800 * MSC has already paged the subscriver via SGs. So any MT-CSFB call will look
3801 * like an unsolicited Paging Response to the MSC.
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003802 */
3803testcase TC_paging_resp_unsol() runs on test_CT {
3804
3805 f_init(1);
Philipp Maierf45824a2019-08-14 14:44:10 +02003806 timer T := 5.0;
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003807
3808 var BSSAP_N_CONNECT_ind rx_c_ind;
3809 var DchanTuple dt;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02003810 var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010008880018'H)));
Philipp Maierf45824a2019-08-14 14:44:10 +02003811 var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003812
3813 /* Send CHAN RQD and wait for allocation; acknowledge it */
3814 dt.rsl_chan_nr := f_chreq_act_ack();
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003815 dt.idx := {0, 0};
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003816
3817 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
Pau Espin Pedrole8a51012023-01-03 11:59:59 +01003818 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 +01003819
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003820
Philipp Maierf45824a2019-08-14 14:44:10 +02003821 /* Expevct a CR with a matching Paging response on the A-Interface */
3822 T.start;
3823 alt {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003824 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
Philipp Maierf45824a2019-08-14 14:44:10 +02003825 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003826 dt.sccp_conn_id := rx_c_ind.connectionId;
3827 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
Philipp Maierf45824a2019-08-14 14:44:10 +02003828 }
3829 [] BSSAP.receive {
3830 setverdict(fail, "Received unexpected message on A-Interface!");
3831 }
3832 [] T.timeout {
3833 setverdict(fail, "Received nothing on A-Interface!");
3834 }
3835 }
3836
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003837 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003838 f_shutdown_helper();
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003839}
3840
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003841/* Verify BSC can schedule N paging requests under one minute if BTS buffer is good enough */
3842function f_TC_paging_Nreq(integer num_subscribers, boolean send_pag_load_ind) runs on test_CT {
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003843 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003844 var Hexstrings imsis := {};
3845 var Booleans rx_paging_done := {};
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003846 var integer rx_paging_num := 0;
3847 var integer i;
3848 timer T_rx := 60.0;
3849 timer T_load_ind := 1.0;
3850
3851 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003852 imsis := imsis & {f_gen_imsi(i)};
3853 rx_paging_done := rx_paging_done & { false };
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003854 }
3855
3856 f_init(1, guard_timeout := 100.0);
3857
3858 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003859 IPA_RSL[0][0].clear;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003860 if (send_pag_load_ind) {
3861 /* Tell there's plenty of space at the BTS (UINT16_MAX): */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003862 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(65535));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003863 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003864
3865 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003866 /* Page on LAC-CI of BTS0: */
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003867 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 +02003868 ts_BSSMAP_Paging(imsis[i], valueof(ts_BSSMAP_CIL_LAC_CI({ts_BSSMAP_CI_LAC_CI(1, 0)})),
3869 omit, omit)));
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003870 }
3871
3872 T_rx.start;
3873 T_load_ind.start;
3874 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003875 [] 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 +02003876 var hexstring imsi := rx_rsl_ud.rsl.ies[2].body.ms_identity.mobileIdentityV.oddEvenInd_identity.imsi.digits;
3877 var hexstring imsi_suffix := substr(imsi, lengthof(imsi)-6, 6);
3878 var charstring imsi_str := hex2str(imsi_suffix);
3879 var integer imsi_idx := str2int(imsi_str);
3880 if (rx_paging_done[imsi_idx] == false) {
3881 rx_paging_done[imsi_idx] := true;
3882 rx_paging_num := rx_paging_num + 1;
Pau Espin Pedrolef7ef632022-04-25 13:34:57 +02003883 } else {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003884 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 +02003885 mtc.stop;
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003886 }
3887 if (rx_paging_num < num_subscribers) {
3888 repeat;
3889 }
3890 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003891 [] IPA_RSL[0][0].receive { repeat; }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003892 [] T_load_ind.timeout {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003893 log("[CCH Load Ind timer] received paging requests so far: ", rx_paging_num);
3894 if (send_pag_load_ind) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003895 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(40));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003896 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003897 T_load_ind.start;
3898 repeat;
3899 }
3900 [] T_rx.timeout {
3901 setverdict(fail, "Timeout expecting paging requests, so far ", rx_paging_num);
3902 mtc.stop;
3903 }
3904 }
3905
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003906 /* Drop OML connection to have all paging requests flushed: */
3907 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
3908
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003909 f_shutdown_helper();
3910}
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003911/* Verify BSC can schedule 500 paging requests under one minute if BTS buffer is good enough */
3912testcase TC_paging_500req() runs on test_CT {
3913 f_TC_paging_Nreq(500, true);
3914}
3915/* Same as TC_paging_500req, but without sending CCCH Load Indication, which
3916 * means BTS is always under CCH Load Threshold, aka capable of sending tons of requests.
3917 * Since No CCCH Load Ind, BSC uses a conservative estimation of BTS load, which
3918 * for current config yields ~8req/sec, so 480req/min maximum. */
3919testcase TC_paging_450req_no_paging_load_ind() runs on test_CT {
3920 f_TC_paging_Nreq(450, false);
3921}
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003922
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003923/* Test RSL link drop causes counter increment */
3924testcase TC_rsl_drop_counter() runs on test_CT {
3925 var integer rsl_fail;
3926
Harald Welte89d42e82017-12-17 16:42:41 +01003927 f_init(1);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003928
3929 rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
3930
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003931 f_ipa_rsl_stop(bts[0][0].rsl);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003932
3933 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
3934
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003935 f_shutdown_helper();
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003936}
3937
3938/* TODO: Test OML link drop causes counter increment */
3939
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003940/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
3941function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003942 var IPA_Client client;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003943 timer T := 10.0;
3944
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003945 client.id := "IPA-BTS0-TRX0-RSL";
3946 client.vc_IPA := IPA_Emulation_CT.create(client.id & "-IPA") alive;
3947 client.ccm_pars := c_IPA_default_ccm_pars;
3948 client.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
Vadim Yanitskiy7ed7bd62024-04-20 03:29:11 +07003949 client.ccm_pars.unit_id := enc_IpaUnitId({99, 0, 0}); /* value which is unknown at BTS */
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003950
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01003951 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003952
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003953 f_init_mgcp(0, "VirtMGW");
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003954
3955 /* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003956 map(client.vc_IPA:IPA_PORT, system:IPA);
3957 connect(client.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0][0]);
3958 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 +01003959
3960 /* wait for IPA OML link to connect and then disconnect */
3961 T.start;
3962 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003963 [] IPA_RSL[0][0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003964 T.stop;
3965 return true;
3966 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003967 [] IPA_RSL[0][0].receive { repeat }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003968 [] T.timeout {
Daniel Willmannafce8662018-07-06 23:11:32 +02003969 return false;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003970 }
3971 }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003972 return false;
3973}
3974
3975/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3976testcase TC_rsl_unknown_unit_id() runs on test_CT {
3977 if (f_ipa_unknown_unit_id(mp_bsc_rsl_port)) {
3978 setverdict(pass);
3979 } else {
3980 setverdict(fail, "Timeout RSL waiting for connection to close");
3981 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003982 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003983}
3984
3985
3986/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3987testcase TC_oml_unknown_unit_id() runs on test_CT {
3988 if (f_ipa_unknown_unit_id(mp_bsc_oml_port)) {
3989 setverdict(pass);
3990 } else {
3991 setverdict(fail, "Timeout OML waiting for connection to close");
3992 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003993 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003994}
3995
3996
Harald Weltec1a2fff2017-12-17 11:06:19 +01003997/***********************************************************************
Harald Welte6811d102019-04-14 22:23:14 +02003998 * "New world" test cases using RSL_Emulation + RAN_Emulation
Harald Weltec1a2fff2017-12-17 11:06:19 +01003999 ***********************************************************************/
4000
Harald Welte6811d102019-04-14 22:23:14 +02004001import from RAN_Emulation all;
Harald Welte47cd0e32020-08-21 12:39:11 +02004002import from BSSAP_LE_Emulation all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01004003import from RSL_Emulation all;
4004import from MSC_ConnectionHandler all;
4005
4006type function void_fn(charstring id) runs on MSC_ConnHdlr;
4007
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06004008/* helper function to create and connect a MSC_ConnHdlr component
4009 * TODO: allow connecting to TRX1..N, not only TRX0 */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004010private 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 +02004011 connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06004012 connect(vc_conn:RSL, bts[0][0].rsl.vc_RSL:CLIENT_PT);
4013 connect(vc_conn:RSL_PROC, bts[0][0].rsl.vc_RSL:RSL_PROC);
4014 if (isvalue(bts[1][0])) {
4015 connect(vc_conn:RSL1, bts[1][0].rsl.vc_RSL:CLIENT_PT);
4016 connect(vc_conn:RSL1_PROC, bts[1][0].rsl.vc_RSL:RSL_PROC);
Philipp Maier956a92f2018-02-16 10:58:07 +01004017 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06004018 if (isvalue(bts[2][0])) {
4019 connect(vc_conn:RSL2, bts[2][0].rsl.vc_RSL:CLIENT_PT);
4020 connect(vc_conn:RSL2_PROC, bts[2][0].rsl.vc_RSL:RSL_PROC);
Neels Hofmeyr91401012019-07-11 00:42:35 +02004021 }
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004022 connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02004023 if (mp_enable_lcs_tests) {
4024 connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
4025 connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
4026 }
Daniel Willmannebdecc02020-08-12 15:30:17 +02004027 connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004028 connect(vc_conn:MGCP_PROC, vc_MGCP[mgwpool_idx]:MGCP_PROC);
4029 connect(vc_conn:MGCP, vc_MGCP[mgwpool_idx]:MGCP_CLIENT);
4030 connect(vc_conn:MGCP_MULTI, vc_MGCP[mgwpool_idx]:MGCP_CLIENT_MULTI);
Harald Welte336820c2018-05-31 20:34:52 +02004031}
4032
Neels Hofmeyrda436782021-07-20 22:09:06 +02004033function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
Harald Welte336820c2018-05-31 20:34:52 +02004034runs on test_CT return MSC_ConnHdlr {
4035 var charstring id := testcasename();
4036 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004037 var integer bssap_idx := 0;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004038 var integer mgwpool_idx := 0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004039 if (isvalue(pars)) {
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004040 var TestHdlrParams pars_val := valueof(pars);
4041 bssap_idx := pars_val.mscpool.bssap_idx;
4042 mgwpool_idx := pars_val.mgwpool_idx;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004043 }
Harald Welte336820c2018-05-31 20:34:52 +02004044 vc_conn := MSC_ConnHdlr.create(id);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004045 f_connect_handler(vc_conn, bssap_idx, mgwpool_idx);
Neels Hofmeyrda436782021-07-20 22:09:06 +02004046 return vc_conn;
4047}
4048
4049function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
4050runs on test_CT return MSC_ConnHdlr {
4051 var charstring id := testcasename();
Harald Weltea0630032018-03-20 21:09:55 +01004052 vc_conn.start(f_handler_init(fn, id, pars));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004053 return vc_conn;
4054}
4055
Neels Hofmeyrda436782021-07-20 22:09:06 +02004056function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
4057runs on test_CT return MSC_ConnHdlr {
4058 return f_start_handler_run(f_start_handler_create(pars), fn, pars);
4059}
4060
Harald Weltea0630032018-03-20 21:09:55 +01004061/* first function inside ConnHdlr component; sets g_pars + starts function */
4062private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
4063runs on MSC_ConnHdlr {
4064 if (isvalue(pars)) {
4065 g_pars := valueof(pars);
4066 }
4067 fn.apply(id);
4068}
4069
Oliver Smith26a3db72021-07-09 13:51:29 +02004070private function f_vty_encryption_a5(charstring options) runs on test_CT {
4071 f_vty_transceive(BSCVTY, "configure terminal");
4072 f_vty_transceive(BSCVTY, "network");
4073 f_vty_transceive(BSCVTY, "encryption a5 " & options);
4074 f_vty_transceive(BSCVTY, "exit");
4075 f_vty_transceive(BSCVTY, "exit");
4076}
4077
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004078const charstring VTY_A5_DEFAULT := "0 1 3";
4079
Oliver Smith26a3db72021-07-09 13:51:29 +02004080private function f_vty_encryption_a5_reset() runs on test_CT {
4081 /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004082 f_vty_encryption_a5(VTY_A5_DEFAULT);
Oliver Smith26a3db72021-07-09 13:51:29 +02004083}
4084
Harald Welte3c86ea02018-05-10 22:28:05 +02004085/* Establish signalling channel (non-assignment case) followed by cipher mode */
4086private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004087 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4088 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte3c86ea02018-05-10 22:28:05 +02004089 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Philipp Maier23000732018-05-18 11:25:37 +02004090 ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode := omit;
4091 ass_cmd.pdu.bssmap.assignmentRequest.aoIPTransportLayer := omit;
4092 exp_compl.pdu.bssmap.assignmentComplete.circuitIdentityCode := omit;
4093 exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
Harald Welte3c86ea02018-05-10 22:28:05 +02004094
Philipp Maier23000732018-05-18 11:25:37 +02004095 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004096 f_perform_clear();
Harald Welte3c86ea02018-05-10 22:28:05 +02004097}
4098testcase TC_ciph_mode_a5_0() runs on test_CT {
4099 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004100 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004101 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
4102
4103 f_init(1, true);
4104 f_sleep(1.0);
4105 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4106 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004107 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004108}
4109testcase TC_ciph_mode_a5_1() runs on test_CT {
4110 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004111 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004112 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
4113
4114 f_init(1, true);
4115 f_sleep(1.0);
4116 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4117 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004118 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004119}
Oliver Smith50b98122021-07-09 15:00:28 +02004120/* OS#4975: verify that A5/2 is preferred over A5/0 */
4121testcase TC_ciph_mode_a5_2_0() runs on test_CT {
4122 var MSC_ConnHdlr vc_conn;
4123 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4124
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004125 pars.encr := f_encr_params('05'O, '04'O); /* A5/0 and A5/2 (0x01|0x04)*/
Oliver Smith50b98122021-07-09 15:00:28 +02004126
4127 f_init(1, true);
4128 f_vty_encryption_a5("0 1 2 3");
4129 f_sleep(1.0);
4130 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4131 vc_conn.done;
4132 f_vty_encryption_a5_reset();
4133 f_shutdown_helper();
4134}
Oliver Smith1dff88d2021-07-09 08:45:51 +02004135/* OS#4975: verify that A5/1 is preferred over A5/2 */
4136testcase TC_ciph_mode_a5_2_1() runs on test_CT {
4137 var MSC_ConnHdlr vc_conn;
4138 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4139
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004140 pars.encr := f_encr_params('06'O, '02'O); /* A5/1 and A5/2 (0x02|0x04)*/
Oliver Smith1dff88d2021-07-09 08:45:51 +02004141
4142 f_init(1, true);
4143 f_vty_encryption_a5("1 2");
4144 f_sleep(1.0);
4145 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4146 vc_conn.done;
4147 f_vty_encryption_a5_reset();
4148 f_shutdown_helper();
4149}
Harald Welte3c86ea02018-05-10 22:28:05 +02004150testcase TC_ciph_mode_a5_3() runs on test_CT {
4151 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004152 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004153 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
4154
4155 f_init(1, true);
4156 f_sleep(1.0);
4157 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4158 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004159 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004160}
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004161/* Establish a Signalling channel with A5/4 encryption. */
4162testcase TC_ciph_mode_a5_4() runs on test_CT {
4163 var MSC_ConnHdlr vc_conn;
4164 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4165 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Harald Welte3c86ea02018-05-10 22:28:05 +02004166
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004167 f_init(1, true);
Oliver Smith26a3db72021-07-09 13:51:29 +02004168 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004169 f_sleep(1.0);
4170 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4171 vc_conn.done;
Oliver Smith26a3db72021-07-09 13:51:29 +02004172 f_vty_encryption_a5_reset();
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004173 f_shutdown_helper();
4174}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004175/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
4176private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
4177 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4178 var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
4179 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4180 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4181
4182 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004183 f_perform_clear();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004184}
4185testcase TC_assignment_aoip_tla_v6() runs on test_CT {
4186 var MSC_ConnHdlr vc_conn;
4187 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4188
4189 f_init(1, true);
4190 f_sleep(1.0);
4191 vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
4192 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004193 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004194}
4195
Harald Welte3c86ea02018-05-10 22:28:05 +02004196
4197/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
Harald Welte651fcdc2018-05-10 20:23:16 +02004198private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004199 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4200 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004201
Harald Welte552620d2017-12-16 23:21:36 +01004202 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4203 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte73cd2712017-12-17 00:44:52 +01004204
Harald Weltea0630032018-03-20 21:09:55 +01004205 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004206 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004207}
Harald Welte552620d2017-12-16 23:21:36 +01004208testcase TC_assignment_fr_a5_0() runs on test_CT {
4209 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004210 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004211 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
Harald Welte552620d2017-12-16 23:21:36 +01004212
Harald Welte89d42e82017-12-17 16:42:41 +01004213 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004214 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004215 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004216 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004217 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004218}
Harald Welte552620d2017-12-16 23:21:36 +01004219testcase TC_assignment_fr_a5_1() runs on test_CT {
Harald Weltec1a2fff2017-12-17 11:06:19 +01004220 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004221 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004222 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004223
Harald Welte89d42e82017-12-17 16:42:41 +01004224 f_init(1, true);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004225 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004226 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4227 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004228 f_shutdown_helper();
Harald Welte651fcdc2018-05-10 20:23:16 +02004229}
4230testcase TC_assignment_fr_a5_3() runs on test_CT {
4231 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004232 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004233 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004234
Harald Welte651fcdc2018-05-10 20:23:16 +02004235 f_init(1, true);
4236 f_sleep(1.0);
4237 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004238 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004239 f_shutdown_helper();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004240}
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004241/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
4242testcase TC_assignment_fr_a5_4() runs on test_CT {
4243 var MSC_ConnHdlr vc_conn;
4244 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4245 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
4246
4247 f_init(1, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02004248 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004249 f_sleep(1.0);
4250 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4251 vc_conn.done;
Oliver Smith7eabd312021-07-12 14:18:56 +02004252 f_vty_encryption_a5_reset();
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004253 f_shutdown_helper();
4254}
Harald Weltec1a2fff2017-12-17 11:06:19 +01004255
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +02004256/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
4257testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
4258 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4259 var MSC_ConnHdlr vc_conn;
4260
4261 f_init(1, true);
4262 f_sleep(1.0);
4263
4264 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
4265 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
4266 vc_conn.done;
4267 f_shutdown_helper();
4268}
4269
Harald Welte552620d2017-12-16 23:21:36 +01004270/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
4271private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004272 g_pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004273 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02004274 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004275
4276 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02004277 /* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
4278
Harald Weltea0630032018-03-20 21:09:55 +01004279 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004280 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004281}
Harald Welte552620d2017-12-16 23:21:36 +01004282testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
4283 var MSC_ConnHdlr vc_conn;
4284
Harald Welte89d42e82017-12-17 16:42:41 +01004285 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004286 f_sleep(1.0);
4287
Harald Welte8863fa12018-05-10 20:15:27 +02004288 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
Harald Welte552620d2017-12-16 23:21:36 +01004289 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004290 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004291}
4292
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004293private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
4294 var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
4295 var PDU_BSSAP exp_ass_req := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004296
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004297 exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4298 exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4299
4300 /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
4301
4302 var BSSMAP_FIELD_CodecType codecType;
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004303
4304 codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
4305 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
4306
4307 f_create_chan_and_exp();
4308 /* we should now have a COMPL_L3 at the MSC */
4309
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004310 /* Start ciphering, expect Cipher Mode Reject */
Neels Hofmeyr6c388f22021-06-11 02:36:56 +02004311 f_cipher_mode(g_pars.encr, exp_fail := true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004312 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004313}
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004314testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
4315 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004316 var MSC_ConnHdlr vc_conn;
4317
Harald Welte89d42e82017-12-17 16:42:41 +01004318 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004319 f_sleep(1.0);
4320
Neels Hofmeyr0588cad2021-06-11 01:38:18 +02004321 pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004322 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004323 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004324 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004325}
4326
4327
Harald Welte4532e0a2017-12-23 02:05:44 +01004328private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004329 g_pars := f_gen_test_hdlr_pars();
Harald Welte4532e0a2017-12-23 02:05:44 +01004330 var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
Philipp Maier48604732018-10-09 15:00:37 +02004331 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte4532e0a2017-12-23 02:05:44 +01004332 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004333
4334 f_statsd_reset();
Harald Weltea0630032018-03-20 21:09:55 +01004335 f_establish_fully(ass_cmd, exp_compl);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004336
4337 var StatsDExpects expect := {
Daniel Willmannc5398f72020-09-21 10:41:35 +02004338 { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
4339 { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
Daniel Willmannebdecc02020-08-12 15:30:17 +02004340 { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
4341 { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
4342 };
4343 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004344 f_perform_clear();
Harald Welte4532e0a2017-12-23 02:05:44 +01004345}
4346
4347testcase TC_assignment_sign() runs on test_CT {
4348 var MSC_ConnHdlr vc_conn;
4349
4350 f_init(1, true);
4351 f_sleep(1.0);
4352
Harald Welte8863fa12018-05-10 20:15:27 +02004353 vc_conn := f_start_handler(refers(f_tc_assignment_sign));
Harald Welte4532e0a2017-12-23 02:05:44 +01004354 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004355 f_shutdown_helper();
Harald Welte4532e0a2017-12-23 02:05:44 +01004356}
4357
Harald Welte60aa5762018-03-21 19:33:13 +01004358/***********************************************************************
4359 * Codec (list) testing
4360 ***********************************************************************/
4361
4362/* check if the given rsl_mode is compatible with the a_elem */
4363private function f_match_codec(BSSMAP_FIELD_CodecElement a_elem, RSL_IE_ChannelMode rsl_mode)
4364return boolean {
4365 select (a_elem.codecType) {
4366 case (GSM_FR) {
4367 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1))) {
4368 return true;
4369 }
4370 }
4371 case (GSM_HR) {
4372 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1))) {
4373 return true;
4374 }
4375 }
4376 case (GSM_EFR) {
4377 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2))) {
4378 return true;
4379 }
4380 }
4381 case (FR_AMR) {
4382 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3))) {
4383 return true;
4384 }
4385 }
4386 case (HR_AMR) {
4387 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3))) {
4388 return true;
4389 }
4390 }
4391 case else { }
4392 }
4393 return false;
4394}
4395
4396/* check if the given rsl_mode is compatible with the a_list */
4397private function f_match_codecs(BSSMAP_IE_SpeechCodecList a_list, RSL_IE_ChannelMode rsl_mode)
4398return boolean {
4399 for (var integer i := 0; i < sizeof(a_list); i := i+1) {
4400 if (f_match_codec(a_list.codecElements[i], rsl_mode)) {
4401 return true;
4402 }
4403 }
4404 return false;
4405}
4406
4407/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
Philipp Maier61f6b572018-07-06 14:03:38 +02004408function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
Harald Welte60aa5762018-03-21 19:33:13 +01004409return BSSMAP_IE_ChannelType {
4410 /* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
4411 var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
4412 select (a_elem.codecType) {
4413 case (GSM_FR) {
4414 ret.channelRateAndType := ChRate_TCHF;
4415 ret.speechId_DataIndicator := Spdi_TCHF_FR;
4416 }
4417 case (GSM_HR) {
4418 ret.channelRateAndType := ChRate_TCHH;
4419 ret.speechId_DataIndicator := Spdi_TCHH_HR;
4420 }
4421 case (GSM_EFR) {
4422 ret.channelRateAndType := ChRate_TCHF;
4423 ret.speechId_DataIndicator := Spdi_TCHF_EFR;
4424 }
4425 case (FR_AMR) {
4426 ret.channelRateAndType := ChRate_TCHF;
4427 ret.speechId_DataIndicator := Spdi_TCHF_AMR;
4428 }
4429 case (HR_AMR) {
4430 ret.channelRateAndType := ChRate_TCHH;
4431 ret.speechId_DataIndicator := Spdi_TCHH_AMR;
4432 }
4433 case else {
4434 setverdict(fail, "Unsupported codec ", a_elem);
Daniel Willmannafce8662018-07-06 23:11:32 +02004435 mtc.stop;
Harald Welte60aa5762018-03-21 19:33:13 +01004436 }
4437 }
4438 return ret;
4439}
4440
Harald Weltea63b9102018-03-22 20:36:16 +01004441private function f_rsl_chmod_tmpl_from_codec(BSSMAP_FIELD_CodecElement a_elem)
4442return template RSL_IE_Body {
4443 var template RSL_IE_Body mode_ie := {
4444 chan_mode := {
4445 len := ?,
4446 reserved := ?,
4447 dtx_d := ?,
4448 dtx_u := ?,
4449 spd_ind := RSL_SPDI_SPEECH,
4450 ch_rate_type := -,
Oliver Smith0033b122023-02-28 13:30:53 +01004451 u := { speech := - }
Harald Weltea63b9102018-03-22 20:36:16 +01004452 }
4453 }
4454
4455 select (a_elem.codecType) {
4456 case (GSM_FR) {
4457 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004458 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004459 }
4460 case (GSM_HR) {
4461 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004462 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004463 }
4464 case (GSM_EFR) {
4465 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004466 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM2;
Harald Weltea63b9102018-03-22 20:36:16 +01004467 }
4468 case (FR_AMR) {
4469 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004470 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004471 }
4472 case (HR_AMR) {
4473 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004474 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004475 }
4476 }
4477 return mode_ie;
4478}
4479
Harald Welte60aa5762018-03-21 19:33:13 +01004480type record CodecListTest {
4481 BSSMAP_IE_SpeechCodecList codec_list,
4482 charstring id
4483}
4484type record of CodecListTest CodecListTests
4485
4486private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004487 f_assignment_codec(id);
4488}
4489
4490private function f_assignment_codec(charstring id, boolean do_perform_clear := true) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02004491 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02004492 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welte60aa5762018-03-21 19:33:13 +01004493
4494 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004495 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte79f3f542018-05-25 20:02:37 +02004496 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4497 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
4498 g_pars.ass_codec_list.codecElements[0];
Philipp Maierd0e64b02019-03-13 14:15:23 +01004499 if (isvalue(g_pars.expect_mr_s0_s7)) {
4500 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
4501 g_pars.expect_mr_s0_s7;
4502 }
Harald Welte79f3f542018-05-25 20:02:37 +02004503 }
Harald Welte60aa5762018-03-21 19:33:13 +01004504 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4505 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
Harald Welte60aa5762018-03-21 19:33:13 +01004506 log("expecting ASS COMPL like this: ", exp_compl);
4507
4508 f_establish_fully(ass_cmd, exp_compl);
Harald Weltea63b9102018-03-22 20:36:16 +01004509
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004510 if (not g_pars.expect_channel_mode_modify) {
4511 /* Verify that the RSL-side activation actually matches our expectations */
4512 var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
Harald Weltea63b9102018-03-22 20:36:16 +01004513
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004514 var RSL_IE_Body mode_ie;
4515 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
4516 setverdict(fail, "Couldn't find CHAN_MODE IE");
Daniel Willmannafce8662018-07-06 23:11:32 +02004517 mtc.stop;
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004518 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004519 var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
4520 if (not match(mode_ie, t_mode_ie)) {
4521 log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
4522 setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004523 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004524
4525 var RSL_IE_Body mr_conf;
4526 if (g_pars.expect_mr_conf_ie != omit) {
4527 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
4528 setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
4529 mtc.stop;
4530 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004531 log("found RSL MR CONFIG IE: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004532
4533 if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
Vadim Yanitskiy8b189372022-09-14 17:31:17 +07004534 setverdict(fail, "RSL MR CONFIG IE does not match expectation. ",
4535 "Expected: ", g_pars.expect_mr_conf_ie, ", got: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004536 }
4537 } else {
4538 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
4539 log("found RSL MR CONFIG IE: ", mr_conf);
4540 setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
4541 mtc.stop;
4542 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004543 }
4544 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004545
4546 if (do_perform_clear) {
4547 f_perform_clear();
4548 }
Harald Welte60aa5762018-03-21 19:33:13 +01004549}
4550
Philipp Maierd0e64b02019-03-13 14:15:23 +01004551private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
4552
4553 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4554 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4555
4556 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004557 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maierd0e64b02019-03-13 14:15:23 +01004558 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4559 }
4560 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4561 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
4562 log("expecting ASS FAIL like this: ", exp_fail);
4563
4564 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004565 f_perform_clear();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004566}
4567
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004568const CounterNameVals counternames_bsc_bts_assignment := {
4569 { "assignment:attempted", 0 },
4570 { "assignment:completed", 0 },
4571 { "assignment:stopped", 0 },
4572 { "assignment:no_channel", 0 },
4573 { "assignment:timeout", 0 },
4574 { "assignment:failed", 0 },
4575 { "assignment:error", 0 }
4576};
4577
4578const CounterNameVals counternames_bts_assignment := {
4579 { "assignment:attempted_sign", 0 },
4580 { "assignment:attempted_speech", 0 },
4581 { "assignment:completed_sign", 0 },
4582 { "assignment:completed_speech", 0 },
4583 { "assignment:stopped_sign", 0 },
4584 { "assignment:stopped_speech", 0 },
4585 { "assignment:no_channel_sign", 0 },
4586 { "assignment:no_channel_speech", 0 },
4587 { "assignment:timeout_sign", 0 },
4588 { "assignment:timeout_speech", 0 },
4589 { "assignment:failed_sign", 0 },
4590 { "assignment:failed_speech", 0 },
4591 { "assignment:error_sign", 0 },
4592 { "assignment:error_speech", 0 }
4593};
4594
4595function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
4596 var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
4597 f_ctrs_bts_init(bts_count, bts_names);
4598 f_ctrs_bsc_init(counternames_bsc_bts_assignment);
4599}
4600
Harald Welte60aa5762018-03-21 19:33:13 +01004601testcase TC_assignment_codec_fr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004602 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004603 var MSC_ConnHdlr vc_conn;
4604
4605 f_init(1, true);
4606 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004607 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004608
4609 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004610 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004611 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004612
4613 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4614 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4615 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4616 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4617 f_ctrs_bts_verify();
4618
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004619 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004620}
4621
4622testcase TC_assignment_codec_hr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004623 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004624 var MSC_ConnHdlr vc_conn;
4625
4626 f_init(1, true);
4627 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004628 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004629
4630 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004631 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004632 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004633
4634 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4635 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4636 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4637 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4638 f_ctrs_bts_verify();
4639
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004640 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004641}
4642
4643testcase TC_assignment_codec_efr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004644 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004645 var MSC_ConnHdlr vc_conn;
4646
4647 f_init(1, true);
4648 f_sleep(1.0);
4649
4650 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004651 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004652 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004653 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004654}
4655
Philipp Maierd0e64b02019-03-13 14:15:23 +01004656/* Allow 5,90k only (current default config) */
4657private function f_allow_amr_rate_5_90k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004658 f_vty_cfg_msc(BSCVTY, 0, {
4659 "amr-config 12_2k forbidden",
4660 "amr-config 10_2k forbidden",
4661 "amr-config 7_95k forbidden",
4662 "amr-config 7_40k forbidden",
4663 "amr-config 6_70k forbidden",
4664 "amr-config 5_90k allowed",
4665 "amr-config 5_15k forbidden",
4666 "amr-config 4_75k forbidden"
4667 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004668}
4669
4670/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
4671 * ("Config-NB-Code = 1") */
4672private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004673 f_vty_cfg_msc(BSCVTY, 0, {
4674 "amr-config 12_2k allowed",
4675 "amr-config 10_2k forbidden",
4676 "amr-config 7_95k forbidden",
4677 "amr-config 7_40k allowed",
4678 "amr-config 6_70k forbidden",
4679 "amr-config 5_90k allowed",
4680 "amr-config 5_15k forbidden",
4681 "amr-config 4_75k allowed"
4682 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004683}
4684
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004685private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
4686 var charstring tch;
4687 if (fr) {
4688 tch := "tch-f";
4689 } else {
4690 tch := "tch-h";
4691 }
4692 f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
4693}
4694
4695/* Set the AMR start-mode for this TCH back to the default configuration. */
4696private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
4697 f_vty_amr_start_mode_set(fr, "auto");
4698}
4699
Harald Welte60aa5762018-03-21 19:33:13 +01004700testcase TC_assignment_codec_amr_f() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004701 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004702 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004703
4704 /* Note: This setups the codec configuration. The parameter payload in
4705 * mr_conf must be consistant with the parameter codecElements in pars
4706 * and also must match the amr-config in osmo-bsc.cfg! */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004707 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004708 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004709 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004710 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004711
Harald Welte60aa5762018-03-21 19:33:13 +01004712 f_init(1, true);
4713 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004714 f_vty_amr_start_mode_set(true, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004715 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004716
Harald Welte8863fa12018-05-10 20:15:27 +02004717 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004718 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004719
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004720 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4721 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4722 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4723 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4724 f_ctrs_bts_verify();
4725
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004726 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004727 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004728}
4729
4730testcase TC_assignment_codec_amr_h() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004731 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004732 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004733
4734 /* See note above */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004735 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004736 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004737 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004738 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004739
Harald Welte60aa5762018-03-21 19:33:13 +01004740 f_init(1, true);
4741 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004742 f_vty_amr_start_mode_set(false, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004743 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004744
Harald Welte8863fa12018-05-10 20:15:27 +02004745 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004746 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004747
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004748 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4749 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4750 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4751 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4752 f_ctrs_bts_verify();
4753
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004754 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004755 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004756}
4757
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004758/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
4759testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
4760 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4761 var MSC_ConnHdlr vc_conn;
4762
4763 f_init(1, true);
4764 f_sleep(1.0);
4765
4766 /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
4767 * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
4768 * expecting a Channel Mode Modify if the channel type is compatible. */
4769 f_disable_all_sdcch();
4770 f_disable_all_tch_h();
4771
4772 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4773 pars.expect_channel_mode_modify := true;
4774 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4775 vc_conn.done;
4776
4777 f_enable_all_sdcch();
4778 f_enable_all_tch();
4779 f_shutdown_helper();
4780}
4781
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004782/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
4783testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
4784 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4785 var MSC_ConnHdlr vc_conn;
4786
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004787 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4788 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
4789 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy36fe9582022-09-14 15:25:04 +07004790 pars.expect_mr_conf_ie := c_mr_conf_5_90;
4791 pars.expect_mr_conf_ie.multirate_cfg.icmi := false; /* expect ICMI=0, smod=00: */
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004792
4793 f_init(1, true);
4794 f_sleep(1.0);
4795
4796 /* First set nonzero start mode bits */
4797 f_vty_amr_start_mode_set(true, "4");
4798 /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
4799 * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
4800 * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
4801 f_vty_amr_start_mode_set(true, "auto");
4802
4803 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4804 vc_conn.done;
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004805
4806 /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
4807 f_vty_amr_start_mode_set(true, "1");
4808 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004809 f_shutdown_helper();
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004810}
4811
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004812function f_TC_assignment_codec_amr(boolean fr, RSL_IE_MultirateCfg mr_cfg,
4813 bitstring s8_s0, bitstring exp_s8_s0,
4814 charstring start_mode := "1")
Philipp Maierd0e64b02019-03-13 14:15:23 +01004815runs on test_CT {
4816
4817 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4818 var MSC_ConnHdlr vc_conn;
4819
Philipp Maierd0e64b02019-03-13 14:15:23 +01004820 if (fr) {
4821 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4822 } else {
4823 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4824 }
4825 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4826 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004827 pars.expect_mr_conf_ie := { multirate_cfg := mr_cfg };
Philipp Maierd0e64b02019-03-13 14:15:23 +01004828 pars.expect_mr_s0_s7 := exp_s8_s0;
4829
4830 f_init(1, true);
4831 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004832 f_vty_amr_start_mode_set(fr, start_mode);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004833 f_sleep(1.0);
4834
4835 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4836 vc_conn.done;
4837 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004838 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004839}
4840
4841function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
4842runs on test_CT {
4843
4844 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4845 var MSC_ConnHdlr vc_conn;
4846
4847 if (fr) {
4848 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4849 } else {
4850 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4851 }
4852 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4853 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4854
4855 f_init(1, true);
4856 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004857 f_vty_amr_start_mode_set(fr, "1");
Philipp Maierd0e64b02019-03-13 14:15:23 +01004858 f_sleep(1.0);
4859
4860 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
4861 vc_conn.done;
4862 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004863 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004864}
4865
Philipp Maierd0e64b02019-03-13 14:15:23 +01004866/* Set S1, we expect an AMR multirate configuration IE with all four rates
4867 * set. */
4868testcase TC_assignment_codec_amr_f_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004869 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4870 params := '20882208'O));
4871 f_TC_assignment_codec_amr(true, mr_cfg, '00000011'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004872 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004873}
4874
4875/* Set S1, we expect an AMR multirate configuration IE with the lower three
4876 * rates set. */
4877testcase TC_assignment_codec_amr_h_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004878 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4879 params := '208820'O));
4880 f_TC_assignment_codec_amr(false, mr_cfg, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004881 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004882}
4883
4884/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4885 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4886testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004887 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4888 params := '20882208'O));
4889 f_TC_assignment_codec_amr(true, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004890 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004891}
4892
4893/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4894 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4895testcase TC_assignment_codec_amr_h_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004896 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4897 params := '208820'O));
4898 f_TC_assignment_codec_amr(false, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004899 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004900}
4901
4902/* The following block of tests selects more and more rates until all four
4903 * possible rates are in the active set (full rate) */
4904testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004905 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4906 f_TC_assignment_codec_amr(true, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004907 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004908}
4909
4910testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004911 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4912 params := '2080'O));
4913 f_TC_assignment_codec_amr(true, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004914 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004915}
4916
4917testcase TC_assignment_codec_amr_f_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004918 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4919 params := '208820'O));
4920 f_TC_assignment_codec_amr(true, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004921 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004922}
4923
4924testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004925 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4926 params := '20882208'O));
4927 f_TC_assignment_codec_amr(true, mr_cfg, '10010101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004928 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004929}
4930
4931/* The following block of tests selects more and more rates until all three
4932 * possible rates are in the active set (half rate) */
4933testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004934 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4935 f_TC_assignment_codec_amr(false, mr_cfg, '00000001'B, '00000001'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_h_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004940 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4941 params := '2080'O));
4942 f_TC_assignment_codec_amr(false, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004943 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004944}
4945
4946testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004947 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4948 params := '208820'O));
4949 f_TC_assignment_codec_amr(false, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004950 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004951}
4952
4953/* The following block tests what happens when the MSC does offer rate
4954 * configurations that are not supported by the BSC. Normally such situations
4955 * should not happen because the MSC gets informed by the BSC in advance via
4956 * the L3 COMPLETE message which rates are applicable. The MSC should not try
4957 * to offer rates that are not applicable anyway. */
4958
4959testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004960 /* Try to include 12,2k in into the active set even though the channel
4961 * is half rate only. The BSC is expected to remove the 12,0k */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004962 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4963 params := '208820'O));
4964 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004965 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004966}
4967
4968testcase TC_assignment_codec_amr_f_S01234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004969 /* See what happens when all rates are selected at once. Since then
4970 * Also S1 is selected, this setting will be prefered and we should
4971 * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004972 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4973 params := '20882208'O));
4974 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004975 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004976}
4977
4978testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004979 /* Same as above, but with S1 missing, the MSC is then expected to
4980 * select the currently supported rates, which are also 12.2k, 7,40k,
4981 * 5,90k, and 4,75k, into the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004982 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4983 params := '20882208'O));
4984 f_TC_assignment_codec_amr(true, mr_cfg, '11111101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004985 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004986}
4987
4988testcase TC_assignment_codec_amr_f_zero() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004989 /* Try to select no rates at all */
4990 f_TC_assignment_codec_amr_fail(true, '00000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004991 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004992}
4993
4994testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004995 /* Try to select only unsupported rates */
4996 f_TC_assignment_codec_amr_fail(true, '01101000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004997 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004998}
4999
5000testcase TC_assignment_codec_amr_h_S7() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02005001 /* Try to select 12,2k for half rate */
5002 f_TC_assignment_codec_amr_fail(false, '10000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005003 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01005004}
5005
Neels Hofmeyr21863562020-11-26 00:34:33 +00005006testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07005007 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
5008 codec_modes := '10010101'B,
5009 params := '20882208'O));
5010 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01005011 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00005012}
5013
5014testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07005015 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
5016 codec_modes := '00010101'B,
5017 params := '208820'O));
5018 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B,
Neels Hofmeyr21863562020-11-26 00:34:33 +00005019 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01005020 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00005021}
5022
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00005023testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01005024 /* "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 +07005025 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 3,
5026 codec_modes := '10010101'B,
5027 params := '20882208'O));
5028 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01005029 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00005030}
5031
5032testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01005033 /* "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 +07005034 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 2,
5035 codec_modes := '00010101'B,
5036 params := '208820'O));
5037 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01005038 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00005039}
5040
Philipp Maierac09bfc2019-01-08 13:41:39 +01005041private function f_disable_all_tch_f() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005042 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 borken");
5043 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 borken");
5044 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 borken");
5045 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005046}
5047
5048private function f_disable_all_tch_h() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005049 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 borken");
5050 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005051}
5052
5053private function f_enable_all_tch() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005054 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 unused");
5055 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 unused");
5056 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 unused");
5057 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 unused");
5058 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 unused");
5059 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005060}
5061
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02005062private function f_disable_all_sdcch() runs on test_CT {
5063 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
5064 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
5065 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
5066 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
5067}
5068
5069private function f_enable_all_sdcch() runs on test_CT {
5070 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
5071 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
5072 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
5073 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
5074}
5075
Philipp Maierac09bfc2019-01-08 13:41:39 +01005076/* Allow HR only */
5077private function f_TC_assignment_codec_xr_exhausted_req_hr(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_compl := f_gen_exp_compl();
5081 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5082 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5083 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5084 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5085 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005086 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005087}
5088
5089/* Allow FR only */
5090private function f_TC_assignment_codec_xr_exhausted_req_fr(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 := '08'O;
5096 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5097 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5098 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005099 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005100}
5101
5102/* Allow HR only (expect assignment failure) */
5103private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) runs on MSC_ConnHdlr {
5104 g_pars := f_gen_test_hdlr_pars();
5105 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5106 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5107 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5108 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5109 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5110 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5111 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005112 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005113}
5114
5115/* Allow FR only (expect assignment failure) */
5116private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) runs on MSC_ConnHdlr {
5117 g_pars := f_gen_test_hdlr_pars();
5118 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5119 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5120 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5121 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5122 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5123 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5124 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005125 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005126}
5127
5128/* Allow FR and HR, but prefer FR */
5129private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5130 g_pars := f_gen_test_hdlr_pars();
5131 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5132 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5133 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5134 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5135 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5136 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5137 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5138 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005139 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005140}
5141
5142/* Allow FR and HR, but prefer HR */
5143private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5144 g_pars := f_gen_test_hdlr_pars();
5145 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5146 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5147 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5148 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5149 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5150 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5151 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5152 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005153 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005154}
5155
5156/* Allow FR and HR, but prefer FR */
5157private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5158 g_pars := f_gen_test_hdlr_pars();
5159 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5160 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5161 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5162 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5163 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5164 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5165 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5166 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005167 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005168}
5169
5170/* Allow FR and HR, but prefer HR */
5171private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5172 g_pars := f_gen_test_hdlr_pars();
5173 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5174 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5175 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5176 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5177 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5178 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5179 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5180 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005181 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005182}
5183
5184/* Request a HR channel while all FR channels are exhausted, this is expected
5185 * to work without conflicts */
5186testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
5187 var MSC_ConnHdlr vc_conn;
5188 f_init(1, true);
5189 f_sleep(1.0);
5190 f_enable_all_tch();
5191 f_disable_all_tch_f();
5192 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
5193 vc_conn.done;
5194 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005195 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005196}
5197
5198/* Request a FR channel while all FR channels are exhausted, this is expected
5199 * to fail. */
5200testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
5201 var MSC_ConnHdlr vc_conn;
5202 f_init(1, true);
5203 f_sleep(1.0);
5204 f_enable_all_tch();
5205 f_disable_all_tch_f();
5206 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
5207 vc_conn.done;
5208 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005209 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005210}
5211
5212/* Request a FR (prefered) or alternatively a HR channel while all FR channels
5213 * are exhausted, this is expected to be resolved by selecting a HR channel. */
5214testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
5215 var MSC_ConnHdlr vc_conn;
5216 f_init(1, true);
5217 f_sleep(1.0);
5218 f_enable_all_tch();
5219 f_disable_all_tch_f();
5220 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
5221 vc_conn.done;
5222 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005223 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005224}
5225
5226/* Request a HR (prefered) or alternatively a FR channel while all FR channels
5227 * are exhausted, this is expected to work without conflicts. */
5228testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
5229 var MSC_ConnHdlr vc_conn;
5230 f_init(1, true);
5231 f_sleep(1.0);
5232 f_enable_all_tch();
5233 f_disable_all_tch_f();
5234 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
5235 vc_conn.done;
5236 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005237 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005238}
5239
5240/* Request a FR channel while all HR channels are exhausted, this is expected
5241 * to work without conflicts */
5242testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
5243 var MSC_ConnHdlr vc_conn;
5244 f_init(1, true);
5245 f_sleep(1.0);
5246 f_enable_all_tch();
5247 f_disable_all_tch_h();
5248 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
5249 vc_conn.done;
5250 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005251 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005252}
5253
5254/* Request a HR channel while all HR channels are exhausted, this is expected
5255 * to fail. */
5256testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
5257 var MSC_ConnHdlr vc_conn;
5258 f_init(1, true);
5259 f_sleep(1.0);
5260 f_enable_all_tch();
5261 f_disable_all_tch_h();
5262 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
5263 vc_conn.done;
5264 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005265 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005266}
5267
5268/* Request a HR (prefered) or alternatively a FR channel while all HR channels
5269 * are exhausted, this is expected to be resolved by selecting a FR channel. */
5270testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
5271 var MSC_ConnHdlr vc_conn;
5272 f_init(1, true);
5273 f_sleep(1.0);
5274 f_enable_all_tch();
5275 f_disable_all_tch_h();
5276 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
5277 vc_conn.done;
5278 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005279 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005280}
5281
5282/* Request a FR (prefered) or alternatively a HR channel while all HR channels
5283 * are exhausted, this is expected to work without conflicts. */
5284testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
5285 var MSC_ConnHdlr vc_conn;
5286 f_init(1, true);
5287 f_sleep(1.0);
5288 f_enable_all_tch();
5289 f_disable_all_tch_h();
5290 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
5291 vc_conn.done;
5292 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005293 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005294}
5295
5296/* Allow FR and HR, but prefer HR */
5297private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5298 g_pars := f_gen_test_hdlr_pars();
5299 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5300 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5301 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5302 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5303 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5304 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5305 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5306 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005307 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005308}
5309
5310/* Allow FR and HR, but prefer FR */
5311private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5312 g_pars := f_gen_test_hdlr_pars();
5313 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5314 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5315 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5316 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5317 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5318 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5319 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5320 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005321 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005322}
5323
5324/* Request a HR (prefered) or alternatively a FR channel, it is expected that
5325 * HR, which is the prefered type, is selected. */
5326testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
5327 var MSC_ConnHdlr vc_conn;
5328 f_init(1, true);
5329 f_sleep(1.0);
5330 f_enable_all_tch();
5331 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
5332 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005333 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005334}
5335
5336/* Request a FR (prefered) or alternatively a HR channel, it is expected that
5337 * FR, which is the prefered type, is selected. */
5338testcase TC_assignment_codec_req_fr_hr() runs on test_CT {
5339 var MSC_ConnHdlr vc_conn;
5340 f_init(1, true);
5341 f_sleep(1.0);
5342 f_enable_all_tch();
5343 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_fr_hr));
5344 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005345 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005346}
5347
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005348/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
5349private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
5350 g_pars := f_gen_test_hdlr_pars();
5351 g_pars.ra := '02'O; /* RA containing reason=LU */
5352
5353 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5354 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5355 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5356 var template uint3_t tsc := ?;
5357
5358 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5359 f_create_bssmap_exp(l3_enc);
5360 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5361 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5362
5363 /* we should now have a COMPL_L3 at the MSC */
5364 timer T := 10.0;
5365 T.start;
5366 alt {
5367 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5368 [] T.timeout {
5369 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5370 }
5371 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005372
5373 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005374}
5375testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
5376 var MSC_ConnHdlr vc_conn;
5377 f_init(1, true);
5378 f_sleep(1.0);
5379 f_disable_all_sdcch();
5380 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
5381 vc_conn.done;
5382 f_enable_all_sdcch();
5383 f_shutdown_helper();
5384}
5385
5386/* Request a signalling channel with all SDCCH exhausted, it is
5387 expected that no TCH will be selected for signalling and assigment will fail
5388 because it's dictated by VTY config */
5389testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
5390 var RSL_Message rsl_unused, rsl_msg;
5391 var GsmRrMessage rr;
5392 f_init(1, false);
5393 f_sleep(1.0);
5394 f_vty_allow_tch_for_signalling(false, 0);
5395 f_disable_all_sdcch();
5396
5397 /* RA containing reason=LU */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005398 f_ipa_tx(ts_RSL_CHAN_RQD('02'O, 2342));
5399 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005400 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
5401 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
5402 setverdict(fail, "Expected reject");
5403 }
5404
5405 f_vty_allow_tch_for_signalling(true, 0);
5406 f_enable_all_sdcch();
5407 f_shutdown_helper();
5408}
5409
5410/* Request a voice channel with all SDCCH exhausted, it is
5411 * expected that TCH channel will be allocated since the VTY option is only
5412 * aimed at signalling requests */
5413private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
5414 g_pars := f_gen_test_hdlr_pars();
5415 g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
5416
5417 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5418 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5419 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5420 var template uint3_t tsc := ?;
5421
5422 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5423 f_create_bssmap_exp(l3_enc);
5424 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5425 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5426
5427 /* we should now have a COMPL_L3 at the MSC */
5428 timer T := 10.0;
5429 T.start;
5430 alt {
5431 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5432 [] T.timeout {
5433 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5434 }
5435 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005436 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005437}
5438testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
5439 var MSC_ConnHdlr vc_conn;
5440 f_init(1, true);
5441 f_sleep(1.0);
5442 f_vty_allow_tch_for_signalling(false, 0);
5443 f_disable_all_sdcch();
5444
5445 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
5446 vc_conn.done;
5447
5448 f_vty_allow_tch_for_signalling(true, 0);
5449 f_enable_all_sdcch();
5450 f_shutdown_helper();
5451}
5452
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005453/* Test Osmux setup BSC<->MSC */
5454testcase TC_assignment_osmux_cn() runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005455 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5456 var MSC_ConnHdlr vc_conn;
5457
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005458 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5459 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5460 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiyb9bf00f2022-09-14 15:35:37 +07005461 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02005462 pars.use_osmux_cn := true;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005463
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02005464 g_osmux_enabled_cn := true;
5465 f_init(1, true);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005466 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005467 f_vty_amr_start_mode_set(false, "1");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005468
5469 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5470 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005471
5472 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01005473 f_shutdown_helper();
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005474}
5475
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005476/* Test Osmux setup BTS<->BSC */
5477testcase TC_assignment_osmux_bts() runs on test_CT {
5478 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5479 var MSC_ConnHdlr vc_conn;
5480
5481 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5482 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5483 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005484 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005485 pars.use_osmux_bts := true;
5486
5487 g_osmux_enabled_bts := true;
5488 f_init(1, true);
5489 f_sleep(1.0);
5490 f_vty_amr_start_mode_set(false, "1");
5491
5492 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5493 vc_conn.done;
5494
5495 f_vty_amr_start_mode_restore(false);
5496 f_shutdown_helper();
5497}
5498
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +02005499/* Test non-AMR codecs still work fine as RTP when Osmux is enabled BTS<->BSC<->MSC */
5500testcase TC_assignment_codec_hr_osmux_on() runs on test_CT {
5501 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5502 var MSC_ConnHdlr vc_conn;
5503
5504 g_osmux_enabled_cn := true;
5505 g_osmux_enabled_bts := true;
5506 f_init(1, true);
5507 f_sleep(1.0);
5508 f_ctrs_bsc_and_bts_assignment_init(1);
5509
5510 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5511 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5512 vc_conn.done;
5513
5514 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
5515 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
5516 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
5517 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
5518 f_ctrs_bts_verify();
5519
5520 f_shutdown_helper();
5521}
5522
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005523/* Test Osmux setup BTS<->BSC<->MSC */
5524testcase TC_assignment_osmux() runs on test_CT {
5525 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5526 var MSC_ConnHdlr vc_conn;
5527
5528 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5529 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5530 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005531 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005532 pars.use_osmux_cn := true;
5533 pars.use_osmux_bts := true;
5534
5535 g_osmux_enabled_cn := true;
5536 g_osmux_enabled_bts := true;
5537 f_init(1, true);
5538 f_sleep(1.0);
5539 f_vty_amr_start_mode_set(false, "1");
5540
5541 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5542 vc_conn.done;
5543
5544 f_vty_amr_start_mode_restore(false);
5545 f_shutdown_helper();
5546}
5547
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005548/* test the procedure of the MSC requesting a Classmark Update:
5549 * a) BSSMAP Classmark Request should result in RR CLASSMARK ENQUIRY,
5550 * b) L3 RR CLASSMARK CHANGE should result in BSSMAP CLASSMARK UPDATE */
Harald Welte898113b2018-01-31 18:32:21 +01005551private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005552 g_pars := f_gen_test_hdlr_pars();
5553
Harald Weltea0630032018-03-20 21:09:55 +01005554 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005555 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005556
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005557 BSSAP.send(ts_BSSMAP_ClassmarkRequest);
5558 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
5559
Harald Welte898113b2018-01-31 18:32:21 +01005560 f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
5561 BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
5562 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005563
5564 f_perform_clear();
Harald Welte898113b2018-01-31 18:32:21 +01005565}
5566testcase TC_classmark() runs on test_CT {
5567 var MSC_ConnHdlr vc_conn;
5568 f_init(1, true);
5569 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005570 vc_conn := f_start_handler(refers(f_tc_classmark));
Harald Welte898113b2018-01-31 18:32:21 +01005571 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005572 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005573}
5574
Harald Welteeddf0e92020-06-21 19:42:15 +02005575/* Send a CommonID from the simulated MSC and verify that the information is used to
5576 * fill BSC-internal data structures (specifically, bsc_subscr associated with subscr_conn) */
5577private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
5578 g_pars := f_gen_test_hdlr_pars();
5579 f_MscConnHdlr_init_vty();
5580
5581 f_create_chan_and_exp();
5582 /* we should now have a COMPL_L3 at the MSC */
Harald Welteeddf0e92020-06-21 19:42:15 +02005583
5584 /* Send CommonID */
5585 BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
5586
5587 /* Use VTY to verify that the IMSI of the subscr_conn is set */
5588 var charstring regex := "*(IMSI: " & hex2str(g_pars.imsi) & ")*";
5589 f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
5590
5591 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005592
5593 f_perform_clear();
Harald Welteeddf0e92020-06-21 19:42:15 +02005594}
5595testcase TC_common_id() runs on test_CT {
5596 var MSC_ConnHdlr vc_conn;
5597 f_init(1, true);
5598 f_sleep(1.0);
5599 vc_conn := f_start_handler(refers(f_tc_common_id));
5600 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005601 f_shutdown_helper();
Harald Welteeddf0e92020-06-21 19:42:15 +02005602}
5603
Harald Weltee3bd6582018-01-31 22:51:25 +01005604private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005605 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005606 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005607 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005608
Harald Weltee3bd6582018-01-31 22:51:25 +01005609 /* send the single message we want to send */
5610 f_rsl_send_l3(l3);
5611}
5612
5613private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr {
5614 timer T := sec;
5615 var PDU_BSSAP bssap;
Harald Welte898113b2018-01-31 18:32:21 +01005616 T.start;
5617 alt {
Harald Weltee3bd6582018-01-31 22:51:25 +01005618 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap {
5619 setverdict(fail, "Unexpected BSSMAP ", bssap);
Daniel Willmannafce8662018-07-06 23:11:32 +02005620 mtc.stop;
Harald Welte898113b2018-01-31 18:32:21 +01005621 }
5622 [] T.timeout {
5623 setverdict(pass);
5624 }
5625 }
5626}
5627
Harald Weltee3bd6582018-01-31 22:51:25 +01005628/* unsolicited ASSIGNMENT FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5629private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
5630 f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
5631 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005632 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005633}
Harald Welte898113b2018-01-31 18:32:21 +01005634testcase TC_unsol_ass_fail() runs on test_CT {
5635 var MSC_ConnHdlr vc_conn;
5636 f_init(1, true);
5637 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005638 vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
Harald Welte898113b2018-01-31 18:32:21 +01005639 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005640 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005641}
Harald Welte552620d2017-12-16 23:21:36 +01005642
Harald Welteea99a002018-01-31 20:46:43 +01005643
5644/* unsolicited ASSIGNMENT COMPLETE (without ASSIGN) from MS shouldn't bring BSC down */
5645private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005646 f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
5647 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005648 f_perform_clear();
Harald Welteea99a002018-01-31 20:46:43 +01005649}
5650testcase TC_unsol_ass_compl() runs on test_CT {
5651 var MSC_ConnHdlr vc_conn;
5652 f_init(1, true);
5653 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005654 vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
Harald Welteea99a002018-01-31 20:46:43 +01005655 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005656 f_shutdown_helper();
Harald Welteea99a002018-01-31 20:46:43 +01005657}
5658
5659
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005660/* unsolicited HANDOVER FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5661private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005662 f_est_single_l3(ts_RRM_HandoverFailure('00'O));
5663 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005664 f_perform_clear();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005665}
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005666testcase TC_unsol_ho_fail() runs on test_CT {
5667 var MSC_ConnHdlr vc_conn;
5668 f_init(1, true);
5669 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005670 vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005671 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005672 f_shutdown_helper();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005673}
5674
5675
Harald Weltee3bd6582018-01-31 22:51:25 +01005676/* short message from MS should be ignored */
5677private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005678 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005679 f_create_chan_and_exp();
Harald Weltee3bd6582018-01-31 22:51:25 +01005680 /* we should now have a COMPL_L3 at the MSC */
Harald Weltee3bd6582018-01-31 22:51:25 +01005681
5682 /* send short message */
5683 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
5684 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005685 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005686}
5687testcase TC_err_82_short_msg() runs on test_CT {
5688 var MSC_ConnHdlr vc_conn;
5689 f_init(1, true);
5690 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005691 vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
Harald Weltee3bd6582018-01-31 22:51:25 +01005692 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005693 f_shutdown_helper();
Harald Weltee3bd6582018-01-31 22:51:25 +01005694}
5695
Harald Weltee9e02e42018-01-31 23:36:25 +01005696/* 24.008 8.4 Unknown message must trigger RR STATUS */
5697private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
Andreas Eversberg9ff96e62023-07-25 12:37:42 +02005698 f_est_single_l3(ts_RRM_DTM_ASS_FAIL('00'O));
Harald Weltee9e02e42018-01-31 23:36:25 +01005699 timer T := 3.0
5700 alt {
5701 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
5702 setverdict(pass);
5703 }
5704 [] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
Harald Welte458fd372018-03-21 11:26:23 +01005705 [] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
Harald Weltee9e02e42018-01-31 23:36:25 +01005706 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005707 f_perform_clear();
Harald Weltee9e02e42018-01-31 23:36:25 +01005708}
5709testcase TC_err_84_unknown_msg() runs on test_CT {
5710 var MSC_ConnHdlr vc_conn;
5711 f_init(1, true);
5712 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005713 vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
Harald Weltee9e02e42018-01-31 23:36:25 +01005714 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005715 f_shutdown_helper();
Harald Weltee9e02e42018-01-31 23:36:25 +01005716}
5717
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005718/***********************************************************************
5719 * Handover
5720 ***********************************************************************/
5721
Harald Welte94e0c342018-04-07 11:33:23 +02005722/* execute a "bts <0-255> trx <0-255> timeslot <0-7> " command on given Dchan */
5723private function f_vty_ts_action(charstring suffix, integer bts_nr, integer trx_nr, integer ts_nr)
5724runs on test_CT {
5725 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5726 " timeslot "&int2str(ts_nr)&" ";
5727 f_vty_transceive(BSCVTY, cmd & suffix);
5728}
5729
Harald Welte261af4b2018-02-12 21:20:39 +01005730/* 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 +07005731private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
5732 uint8_t bts_nr, uint8_t trx_nr,
5733 in RslChannelNr chan_nr)
5734{
Harald Welte261af4b2018-02-12 21:20:39 +01005735 /* FIXME: resolve those from component-global state */
5736 var integer ts_nr := chan_nr.tn;
5737 var integer ss_nr;
5738 if (ischosen(chan_nr.u.ch0)) {
5739 ss_nr := 0;
5740 } else if (ischosen(chan_nr.u.lm)) {
5741 ss_nr := chan_nr.u.lm.sub_chan;
5742 } else if (ischosen(chan_nr.u.sdcch4)) {
5743 ss_nr := chan_nr.u.sdcch4.sub_chan;
5744 } else if (ischosen(chan_nr.u.sdcch8)) {
5745 ss_nr := chan_nr.u.sdcch8.sub_chan;
5746 } else {
5747 setverdict(fail, "Invalid ChanNr ", chan_nr);
Daniel Willmannafce8662018-07-06 23:11:32 +02005748 mtc.stop;
Harald Welte261af4b2018-02-12 21:20:39 +01005749 }
5750
5751 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5752 " timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005753 f_vty_transceive(pt, cmd & suffix);
Harald Welte261af4b2018-02-12 21:20:39 +01005754}
5755
Neels Hofmeyr91401012019-07-11 00:42:35 +02005756/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
5757 * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor
5758 * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
5759 * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
5760 * pair, not really to a specific BTS number. */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005761private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
5762 in RslChannelNr chan_nr, uint8_t new_bts_nr)
5763{
5764 f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
Harald Welte261af4b2018-02-12 21:20:39 +01005765}
5766
5767/* intra-BSC hand-over between BTS0 and BTS1 */
5768private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02005769 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5770 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte261af4b2018-02-12 21:20:39 +01005771
5772 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5773 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5774
Harald Weltea0630032018-03-20 21:09:55 +01005775 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005776 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Harald Welte261af4b2018-02-12 21:20:39 +01005777
5778 var HandoverState hs := {
5779 rr_ho_cmpl_seen := false,
5780 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005781 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005782 expect_target_tsc := c_BtsParams[1].tsc
Harald Welte261af4b2018-02-12 21:20:39 +01005783 };
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005784 /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005785 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
Harald Welte261af4b2018-02-12 21:20:39 +01005786 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5787 f_rslem_suspend(RSL1_PROC);
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005788
5789 /* From the MGW perspective, a handover is is characterized by
5790 * performing one MDCX operation with the MGW. So we expect to see
5791 * one more MDCX during handover. */
5792 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5793
Harald Welte261af4b2018-02-12 21:20:39 +01005794 alt {
5795 [] as_handover(hs);
Harald Welte261af4b2018-02-12 21:20:39 +01005796 }
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005797
Philipp Maier4dae0652018-11-12 12:03:26 +01005798 /* Since this is an internal handover we expect the BSC to inform the
5799 * MSC about the event */
5800 BSSAP.receive(tr_BSSMAP_HandoverPerformed);
5801
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005802 /* Check the amount of MGCP transactions is still consistant with the
5803 * test expectation */
5804 f_check_mgcp_expectations()
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005805
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005806 var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
5807
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005808 /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
5809 * 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 +02005810 f_verify_encr_info(chan_act);
5811
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005812 f_chan_act_verify_tsc(chan_act, c_BtsParams[1].tsc);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005813
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005814 f_perform_clear(RSL1, RSL1_PROC);
5815
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005816 f_sleep(0.5);
Harald Welte261af4b2018-02-12 21:20:39 +01005817}
5818
5819testcase TC_ho_int() runs on test_CT {
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005820 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte261af4b2018-02-12 21:20:39 +01005821 var MSC_ConnHdlr vc_conn;
5822 f_init(2, true);
5823 f_sleep(1.0);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005824
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005825 pars.expect_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005826
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005827 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005828
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005829 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
Harald Welte261af4b2018-02-12 21:20:39 +01005830 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005831
5832 /* from f_establish_fully() */
5833 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5834 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5835 /* from handover */
5836 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5837 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5838 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5839 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005840 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5841 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005842 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005843 f_shutdown_helper(ho := true);
Harald Welte261af4b2018-02-12 21:20:39 +01005844}
Harald Weltee9e02e42018-01-31 23:36:25 +01005845
Oliver Smith7eabd312021-07-12 14:18:56 +02005846function 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 +02005847 var MSC_ConnHdlr vc_conn;
5848 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5849 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
5850
5851 f_init(2, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02005852 f_vty_encryption_a5(enc_a5);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005853 f_sleep(1.0);
5854
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005855 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005856
5857 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
5858 vc_conn.done;
5859
5860 /* from f_establish_fully() */
5861 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5862 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5863 /* from handover */
5864 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5865 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5866 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5867 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005868 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5869 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005870 f_ctrs_bsc_and_bts_verify();
Oliver Smith7eabd312021-07-12 14:18:56 +02005871 f_vty_encryption_a5_reset();
Oliver Smith39f53072022-10-27 14:44:04 +02005872 f_shutdown_helper(ho := true);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005873}
5874
5875testcase TC_ho_int_a5_0() runs on test_CT {
5876 f_tc_ho_int_a5('01'O);
5877}
5878
5879testcase TC_ho_int_a5_1() runs on test_CT {
5880 f_tc_ho_int_a5('02'O);
5881}
5882
5883testcase TC_ho_int_a5_3() runs on test_CT {
5884 f_tc_ho_int_a5('08'O);
5885}
5886
5887testcase TC_ho_int_a5_4() runs on test_CT {
Oliver Smith7eabd312021-07-12 14:18:56 +02005888 f_tc_ho_int_a5('10'O, "0 1 3 4");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005889}
5890
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005891/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
5892private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
5893 g_pars := f_gen_test_hdlr_pars();
5894 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5895 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005896
5897 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5898 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5899
5900 f_establish_fully(ass_cmd, exp_compl);
5901 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
5902
5903 var HandoverState hs := {
5904 rr_ho_cmpl_seen := false,
5905 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005906 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005907 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005908 };
5909 /* issue hand-over command on VTY */
5910 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
5911 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5912 f_rslem_suspend(RSL1_PROC);
5913
5914 /* From the MGW perspective, a handover is is characterized by
5915 * performing one MDCX operation with the MGW. So we expect to see
5916 * one more MDCX during handover. */
5917 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5918
5919 var RSL_Message rsl;
5920 var PDU_ML3_NW_MS l3;
5921 var RslChannelNr new_chan_nr;
5922 var GsmArfcn arfcn;
5923 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
5924 l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
5925 if (not ischosen(l3.msgs.rrm.handoverCommand)) {
5926 setverdict(fail, "Expected handoverCommand");
5927 mtc.stop;
5928 }
5929 }
5930 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
5931 new_chan_nr, arfcn);
5932
5933 f_rslem_register(0, new_chan_nr, RSL1_PROC);
5934
5935 /* resume processing of RSL DChan messages, which was temporarily suspended
5936 * before performing a hand-over */
5937 f_rslem_resume(RSL1_PROC);
5938 RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
5939
5940 f_sleep(1.0);
5941
5942 /* Handover fails because no HANDO DET appears on the new lchan,
5943 * and the old lchan reports a Radio Link Failure. */
5944 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
5945
5946 var PDU_BSSAP rx_clear_request;
5947 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5948 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5949 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5950
5951 var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
5952
5953 var MgcpCommand mgcp;
5954 interleave {
5955 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
5956 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005957 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005958 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005959 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005960 }
5961 [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005962 [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005963 RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005964 f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005965 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005966 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5967 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5968 }
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005969 }
5970
5971 f_sleep(0.5);
5972 setverdict(pass);
5973}
5974testcase TC_ho_int_radio_link_failure() runs on test_CT {
5975 var MSC_ConnHdlr vc_conn;
5976 f_init(2, true);
5977 f_sleep(1.0);
5978
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005979 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005980
5981 vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
5982 vc_conn.done;
5983
5984 /* from f_establish_fully() */
5985 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5986 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5987 /* from handover */
5988 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5989 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
5990 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5991 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005992 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5993 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005994 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005995 f_shutdown_helper(ho := true);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005996}
5997
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005998/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005999private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006000 var MgcpCommand mgcp;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02006001 var template MgcpResponse mgcp_resp;
6002 var MGCP_RecvFrom mrf;
6003 var template MgcpMessage msg_resp;
6004 var template MgcpMessage msg_dlcx := {
6005 command := tr_DLCX()
6006 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006007
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02006008 if (g_pars.aoip) {
6009 MGCP.receive(tr_DLCX()) -> value mgcp {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006010 log("Got first DLCX: ", mgcp);
6011 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02006012 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006013
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006014 MGCP.receive(tr_DLCX()) -> value mgcp {
6015 log("Got second DLCX: ", mgcp);
6016 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
6017 };
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02006018 } else {
6019 /* For SCCPLite, BSC doesn't handle the MSC-side */
6020 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
6021 log("Got first DLCX: ", mrf.msg.command);
6022 msg_resp := {
6023 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
6024 }
6025 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
6026 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006027 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006028}
6029
Oliver Smithc9a5f532022-10-21 11:32:23 +02006030private function f_ho_out_of_this_bsc(template (omit) BSSMAP_oldToNewBSSIEs exp_oldToNewBSSIEs := omit,
6031 boolean skip_meas_rep := false) runs on MSC_ConnHdlr {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006032
Oliver Smithc9a5f532022-10-21 11:32:23 +02006033 if (not skip_meas_rep) {
6034 var NcellReports neighbor_rep := {
6035 { rxlev := 20, bcch_freq := 0, bsic := 11 }
6036 };
6037 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
6038 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
6039 l3_mr, 0));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006040
Oliver Smithc9a5f532022-10-21 11:32:23 +02006041 BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
6042 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006043
6044 f_sleep(0.5);
6045 /* The MSC negotiates Handover Request and Handover Request Ack with
6046 * the other BSS and comes back with a BSSMAP Handover Command
6047 * containing an RR Handover Command coming from the target BSS... */
6048
6049 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6050 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6051 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6052 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6053 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6054
6055 /* expect the Handover Command to go out on RR */
6056 var RSL_Message rsl_ho_cmd
6057 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6058 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6059 var RSL_IE_Body rsl_ho_cmd_l3;
6060 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6061 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6062 setverdict(fail);
6063 } else {
6064 log("Found L3 Info: ", rsl_ho_cmd_l3);
6065 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6066 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6067 setverdict(fail);
6068 } else {
6069 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6070 setverdict(pass);
6071 }
6072 }
6073
6074 /* When the other BSS has reported a completed handover, this side is
6075 * torn down. */
6076
6077 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_HANDOVER_SUCCESSFUL;
6078 var BssmapCause cause := enum2int(cause_val);
6079 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6080
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006081 f_expect_dlcx_conns();
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006082
6083 interleave {
6084 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
6085 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
6086 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006087 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
6088 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
6089 }
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006090 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006091 setverdict(pass);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006092}
6093
6094private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
6095 g_pars := f_gen_test_hdlr_pars();
6096 var PDU_BSSAP ass_req := f_gen_ass_req();
6097 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6098 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6099 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6100 f_establish_fully(ass_req, exp_compl);
6101
6102 f_ho_out_of_this_bsc();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006103}
6104testcase TC_ho_out_of_this_bsc() runs on test_CT {
6105 var MSC_ConnHdlr vc_conn;
6106
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006107 f_init_vty();
6108 f_bts_0_cfg(BSCVTY,
6109 {"neighbor-list mode automatic",
6110 "handover 1",
6111 "handover algorithm 2",
6112 "handover2 window rxlev averaging 1",
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006113 "no neighbors",
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006114 "neighbor lac 99 arfcn 123 bsic any"});
6115 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6116
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006117 f_init(1, true);
6118 f_sleep(1.0);
6119
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006120 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006121
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006122 vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
6123 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006124
6125 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6126 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6127 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6128 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6129 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6130 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
6131 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006132 f_shutdown_helper(ho := true);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006133}
6134
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006135private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6136 template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
Vadim Yanitskiy2ef6a2f2020-10-08 23:17:32 +07006137 template (present) OCT1 dlci := ?,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006138 octetstring l3 := '0123456789'O)
6139runs on MSC_ConnHdlr {
Neels Hofmeyr43654812020-09-25 01:35:35 +02006140 /* The old lchan and conn should still be active. See that arbitrary L3
6141 * is still going through. */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006142 rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
Neels Hofmeyr43654812020-09-25 01:35:35 +02006143 var template PDU_BSSAP exp_data := {
6144 discriminator := '1'B,
6145 spare := '0000000'B,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006146 dlci := dlci,
6147 lengthIndicator := lengthof(l3),
Neels Hofmeyr43654812020-09-25 01:35:35 +02006148 pdu := {
6149 dtap := l3
6150 }
6151 };
6152 BSSAP.receive(exp_data);
6153 setverdict(pass);
6154}
6155
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006156private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6157 template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006158 template (value) OCT1 dlci := '00'O,
6159 octetstring l3 := '0123456789'O)
6160runs on MSC_ConnHdlr {
6161 BSSAP.send(PDU_BSSAP:{
6162 discriminator := '1'B,
6163 spare := '0000000'B,
6164 dlci := dlci,
6165 lengthIndicator := lengthof(l3),
6166 pdu := {
6167 dtap := l3
6168 }
6169 });
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006170 rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006171 setverdict(pass);
6172}
6173
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006174/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
6175 * simply never sends a BSSMAP Handover Command. */
6176private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006177 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006178
6179 var PDU_BSSAP ass_req := f_gen_ass_req();
6180 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6181 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6182 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6183 f_establish_fully(ass_req, exp_compl);
6184
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006185 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006186 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6187
6188 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6189
6190 /* osmo-bsc should time out 10 seconds after the handover started.
6191 * Let's give it a bit extra. */
6192 f_sleep(15.0);
6193
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006194 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006195 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006196 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006197}
6198testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
6199 var MSC_ConnHdlr vc_conn;
6200
6201 f_init(1, true);
6202 f_sleep(1.0);
6203
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006204 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006205
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006206 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
6207 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006208
6209 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6210 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6211 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6212 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6213 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6214 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6215 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006216 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006217}
6218
6219/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
6220 * RR Handover Failure. */
6221private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006222 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006223
6224 var PDU_BSSAP ass_req := f_gen_ass_req();
6225 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6226 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6227 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6228 f_establish_fully(ass_req, exp_compl);
6229
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006230 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006231 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6232
6233 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6234
6235 f_sleep(0.5);
6236 /* The MSC negotiates Handover Request and Handover Request Ack with
6237 * the other BSS and comes back with a BSSMAP Handover Command
6238 * containing an RR Handover Command coming from the target BSS... */
6239
6240 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6241 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6242 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6243 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6244 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6245
6246 /* expect the Handover Command to go out on RR */
6247 var RSL_Message rsl_ho_cmd
6248 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6249 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6250 var RSL_IE_Body rsl_ho_cmd_l3;
6251 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6252 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6253 setverdict(fail);
6254 } else {
6255 log("Found L3 Info: ", rsl_ho_cmd_l3);
6256 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6257 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6258 setverdict(fail);
6259 } else {
6260 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6261 setverdict(pass);
6262 }
6263 }
6264
6265 f_sleep(0.2);
6266 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
6267
6268 /* Should tell the MSC about the failure */
6269 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6270
6271 f_sleep(1.0);
6272
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006273 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006274 f_sleep(1.0);
6275
6276 setverdict(pass);
6277 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006278 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006279}
6280testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
6281 var MSC_ConnHdlr vc_conn;
6282
6283 f_init(1, true);
6284 f_sleep(1.0);
6285
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006286 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006287
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006288 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
6289 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006290
6291 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6292 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6293 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6294 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6295 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6296 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
6297 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006298 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006299}
6300
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006301/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
6302 * (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 +02006303 * and the lchan is released. */
6304private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006305 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006306
6307 var PDU_BSSAP ass_req := f_gen_ass_req();
6308 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6309 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6310 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6311 f_establish_fully(ass_req, exp_compl);
6312
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006313 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006314 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6315
6316 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6317
6318 f_sleep(0.5);
6319 /* The MSC negotiates Handover Request and Handover Request Ack with
6320 * the other BSS and comes back with a BSSMAP Handover Command
6321 * containing an RR Handover Command coming from the target BSS... */
6322
6323 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6324 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6325 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6326 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6327 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6328
6329 /* expect the Handover Command to go out on RR */
6330 var RSL_Message rsl_ho_cmd
6331 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6332 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6333 var RSL_IE_Body rsl_ho_cmd_l3;
6334 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6335 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6336 setverdict(fail);
6337 } else {
6338 log("Found L3 Info: ", rsl_ho_cmd_l3);
6339 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6340 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6341 setverdict(fail);
6342 } else {
6343 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6344 setverdict(pass);
6345 }
6346 }
6347
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006348 /* We get neither success nor failure report from the remote BSS. Eventually T8 times out and we run into 3GPP
6349 * TS 48.008 3.1.5.3.3 "Abnormal Conditions": Clear Request should go to the MSC, and RR should be released
6350 * after Clear Command */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006351
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006352 var PDU_BSSAP rx_clear_request;
Neels Hofmeyre1797aa2019-07-09 19:34:04 +02006353 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
6354 log("Got BSSMAP Clear Request");
6355 /* Instruct BSC to clear channel */
6356 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6357 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6358
6359 var MgcpCommand mgcp;
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006360 interleave {
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01006361 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
6362 log("Got Deact SACCH");
6363 }
Harald Welte924b6ea2019-02-04 01:05:34 +01006364 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
Neels Hofmeyr211169d2018-11-07 00:37:29 +01006365 log("Got RR Release");
6366 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02006367 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006368 log("Got RF Chan Rel");
6369 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02006370 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006371 }
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006372 }
6373
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006374 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006375 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006376 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006377
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006378 setverdict(pass);
6379 f_sleep(1.0);
6380}
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006381testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006382 var MSC_ConnHdlr vc_conn;
6383
6384 f_init(1, true);
6385 f_sleep(1.0);
6386
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006387 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006388
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006389 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006390 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006391
6392 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6393 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6394 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6395 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6396 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6397 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6398 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006399 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006400}
6401
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006402private 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 +01006403 var PDU_BSSAP rx_bssap;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006404 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6405 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6406 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6407 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6408 * before we get started. */
6409 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6410 f_rslem_register(0, new_chan_nr);
6411 g_chan_nr := new_chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06006412 var uint3_t expect_target_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006413 f_sleep(1.0);
6414
6415 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6416 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006417 var default as_media := activate(as_Media());
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006418
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01006419 var PDU_BSSAP ho_req := f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
6420 cell_id_source := g_pars.cell_id_source,
6421 oldToNewBSSIEs := oldToNewBSSIEs,
6422 enc := g_pars.encr);
6423 if (g_pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr) {
6424 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, ho_req));
6425 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6426 } else {
6427 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, omit));
6428 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6429 BSSAP.send(ho_req);
6430 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006431
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006432 alt {
6433 [] BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap {
6434 if (g_pars.expect_ho_fail) {
6435 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6436 "Expected Handover Request to fail, but got Handover Request Ack")
6437 }
6438 }
6439 [] BSSAP.receive(tr_BSSMAP_HandoverFailure) -> value rx_bssap {
6440 if (not g_pars.expect_ho_fail) {
6441 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6442 "Expected Handover Request to succeed, but got Handover Failure")
6443 }
6444 // TODO: evaluate correct cause value. But osmo-bsc doesn't seem to send meaningful causes yet!
6445 // For now just accept any cause.
6446 BSSAP.receive(tr_BSSMAP_ClearRequest);
6447 setverdict(pass);
6448 return;
6449 }
6450 }
6451
Oliver Smith7a8594a2023-02-13 14:30:49 +01006452 if (g_pars.expect_ho_fail_lchan_est) {
6453 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6454 setverdict(pass);
Oliver Smitha1cbec52023-02-21 12:44:12 +01006455
6456 /* When we let MGCP MDCX run into a timeout, it's still in the
6457 * queue and additionally after BSSAP HandoverFailure, two DLCX
Oliver Smith30eb8822023-03-06 12:31:53 +01006458 * get sent (for AoIP, for SCCPlite one DLCX). */
Oliver Smitha1cbec52023-02-21 12:44:12 +01006459 if (g_pars.ignore_mgw_mdcx) {
Oliver Smith30eb8822023-03-06 12:31:53 +01006460 if (g_pars.aoip) {
6461 MGCP.receive(tr_MDCX);
6462 MGCP.receive(tr_DLCX);
6463 MGCP.receive(tr_DLCX);
6464 } else {
6465 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_MDCX}));
6466 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_DLCX}));
6467 }
Oliver Smitha1cbec52023-02-21 12:44:12 +01006468 }
Oliver Smith7a8594a2023-02-13 14:30:49 +01006469 return;
6470 }
6471
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006472 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6473
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006474 /* we're sure that the channel activation is done now, verify the parameters in it */
6475 var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
6476 f_verify_encr_info(chan_act);
6477 f_chan_act_verify_tsc(chan_act, expect_target_tsc);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006478
Neels Hofmeyr46e16e52022-02-23 17:04:00 +01006479 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.codecList)) {
6480 if (not g_pars.aoip) {
6481 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6482 "handoverRequestAck: Expected no Speech Codec List (BSS Supported), because this is not AoIP");
6483 }
6484 /* TODO: check actual codecs? */
6485 } else {
6486 if (g_pars.aoip) {
6487 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6488 "handoverRequestAck: Expected Speech Codec List (BSS Supported), but none found");
6489 }
6490 }
6491
6492 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.speechCodec)) {
6493 if (not g_pars.aoip) {
6494 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6495 "handoverRequestAck: Expected no Speech Codec (Chosen), because this is not AoIP");
6496 }
6497 /* TODO: check actual codec? */
6498 } else {
6499 if (g_pars.aoip) {
6500 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6501 "handoverRequestAck: Expected Speech Codec (Chosen), but none found");
6502 }
6503 }
6504
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006505 var octetstring ho_command_str;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006506 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6507 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6508 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6509 log("L3 Info in HO Request Ack is ", ho_command);
6510
6511 var GsmArfcn arfcn;
6512 var RslChannelNr actual_new_chan_nr;
6513 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6514 actual_new_chan_nr, arfcn);
6515
6516 if (actual_new_chan_nr != new_chan_nr) {
6517 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6518 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6519 setverdict(fail);
6520 return;
6521 }
6522 log("Handover Command chan_nr is", actual_new_chan_nr);
6523
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006524 var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
6525 if (not match(got_tsc, expect_target_tsc)) {
6526 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6527 expect_target_tsc, " got ", got_tsc);
6528 mtc.stop;
6529 } else {
6530 log("handoverCommand: verified TSC = ", got_tsc);
6531 }
6532
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006533 /* Check the Cipher Mode Setting IE (shall be present during inter-RAT handover) */
6534 if (ispresent(ho_command.msgs.rrm.handoverCommand.cipherModeSetting)) {
6535 var CipherModeSetting_TV cms := ho_command.msgs.rrm.handoverCommand.cipherModeSetting;
6536 var template (present) CipherModeSetting_TV tr_cms := {
6537 sC := '0'B, /* no ciphering by default */
6538 algorithmIdentifier := '000'B,
6539 elementIdentifier := ?
6540 };
6541 if (ispresent(g_pars.encr) and g_pars.encr.enc_alg_expect != '01'O) { /* A5/N */
6542 tr_cms.algorithmIdentifier := f_cipher_mode_bssmap_to_rr(g_pars.encr.enc_alg_expect);
6543 tr_cms.sC := '1'B;
6544 }
6545 if (not match(cms, tr_cms)) {
6546 setverdict(fail, "RR Handover Command: unexpected Cipher Mode Setting IE: ",
6547 cms, ", expected: ", tr_cms);
6548 }
6549 } else {
6550 setverdict(fail, "RR Handover Command: Cipher Mode Setting IE is not present");
6551 }
6552
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006553 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6554 * tells the MS to handover to the new lchan. Here comes the new MS on
6555 * the new lchan with a Handover RACH: */
6556
6557 /* send handover detect */
6558
6559 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6560
6561 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6562
6563 /* send handover complete over the new channel */
6564
6565 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_HandoverComplete('00'O));
6566 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
6567 enc_PDU_ML3_MS_NW(l3_tx)));
6568
6569 BSSAP.receive(tr_BSSMAP_HandoverComplete);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006570 deactivate(as_media);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006571 setverdict(pass);
6572}
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006573
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006574private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006575 var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006576 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
6577 if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
6578 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006579 }
6580 if (g_pars.exp_fast_return) {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006581 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006582 } else {
6583 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006584 }
6585 f_ho_into_this_bsc(id, oldToNewBSSIEs);
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006586 if (g_pars.expect_ho_fail) {
6587 f_perform_clear_no_lchan();
Oliver Smith7a8594a2023-02-13 14:30:49 +01006588 } else if (g_pars.expect_ho_fail_lchan_est) {
6589 BSSAP.receive(tr_BSSMAP_ClearRequest);
6590 f_perform_clear_no_lchan();
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006591 } else {
6592 f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
6593 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006594 setverdict(pass);
6595}
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006596function 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 +01006597 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006598
6599 f_init(1, true);
6600 f_sleep(1.0);
6601
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006602 f_vty_encryption_a5(vty_a5_cfg);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006603 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006604
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006605 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6606 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006607
6608 vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
6609 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006610
6611 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006612 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006613 if (pars.expect_ho_fail) {
6614 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6615 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:failed");
Oliver Smith7a8594a2023-02-13 14:30:49 +01006616 } else if (pars.expect_ho_fail_lchan_est) {
6617 f_ctrs_bsc_and_bts_add(0, "handover:error");
6618 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006619 } else {
6620 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6621 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
6622 }
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006623 f_ctrs_bsc_and_bts_verify();
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006624
6625 f_vty_encryption_a5_reset();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006626}
6627
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006628testcase TC_ho_into_this_bsc() runs on test_CT {
6629 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6630 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006631 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006632}
6633
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006634function f_tc_ho_into_this_bsc_a5(TestHdlrEncrParams encr, charstring vty_a5_cfg := VTY_A5_DEFAULT,
6635 boolean expect_fail := false) runs on test_CT {
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006636 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006637 pars.encr := encr;
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006638 pars.expect_ho_fail := expect_fail;
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006639 f_tc_ho_into_this_bsc_main(pars, vty_a5_cfg);
Oliver Smith39f53072022-10-27 14:44:04 +02006640 f_shutdown_helper(ho := true);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006641}
6642
6643testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006644 f_tc_ho_into_this_bsc_a5(f_encr_params('01'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006645}
6646
6647testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006648 f_tc_ho_into_this_bsc_a5(f_encr_params('02'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006649}
6650
6651testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006652 f_tc_ho_into_this_bsc_a5(f_encr_params('08'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006653}
6654
6655testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006656 f_tc_ho_into_this_bsc_a5(f_encr_params('10'O, kc128 := true), "3 4");
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006657}
6658
Neels Hofmeyr1951be22022-02-16 16:21:07 +01006659/* Report: in inter-BSC incoming handover, when the MSC omits the Chosen Encryption Algorithm IE in the Handover Request
6660 * message, then osmo-bsc starts an unencrypted lchan even if A5/0 is not permitted.
6661 *
6662 * This test verifies that the Encryption Information is present in the Channel Activation when the Chosen Enc Alg is
6663 * omitted.
6664 *
6665 * Related: SYS#5839
6666 */
6667testcase TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() runs on test_CT {
6668 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O, alg_chosen := omit));
6669}
6670
6671testcase TC_ho_into_this_bsc_a5_1_3() runs on test_CT {
6672 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O));
6673}
6674
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006675/* Send a permitted algo mask that does not intersect with osmo-bsc.cfg */
6676testcase TC_ho_into_this_bsc_a5_mismatch() runs on test_CT {
6677 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '18'O, alg_expect := '10'O), "0 1",
6678 expect_fail := true); // 0x18 = A5/3 and A5/4
6679}
6680
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006681testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
6682 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6683 pars.host_aoip_tla := "::6";
6684 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006685 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006686}
6687
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006688/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006689 to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006690 channel is later released (RR CHannel Release), should trigger inclusion of
6691 IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
6692 neighbors. */
6693testcase TC_srvcc_eutran_to_geran() runs on test_CT {
6694 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6695 pars.last_used_eutran_plmn := '323454'O;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006696 pars.exp_fast_return := true;
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006697 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006698
6699 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6700 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6701 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006702 f_shutdown_helper(ho := true);
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006703}
6704
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006705/* Same as TC_srvcc_eutran_to_geran, but enables ciphering on the target channel. */
6706testcase TC_srvcc_eutran_to_geran_a5_3() runs on test_CT {
6707 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6708 pars.encr := f_encr_params('08'O); /* only A5/3 */
6709 pars.last_used_eutran_plmn := '323454'O;
6710 pars.exp_fast_return := true;
6711 f_tc_ho_into_this_bsc_main(pars);
6712
6713 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6714 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6715 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006716 f_shutdown_helper(ho := true);
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006717}
6718
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006719/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
6720 on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
6721 list when the channel is released. */
6722testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
6723 f_init_vty();
6724 f_vty_allow_srvcc_fast_return(true, 0)
6725
6726 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6727 pars.last_used_eutran_plmn := '323454'O;
6728 pars.exp_fast_return := false;
6729 f_tc_ho_into_this_bsc_main(pars);
6730 f_vty_allow_srvcc_fast_return(false, 0);
6731 f_shutdown_helper();
6732}
6733
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01006734/* Same as TC_srvcc_eutran_to_geran, but using SAI as serving Cell Identifier. SYS#5838 */
6735testcase TC_srvcc_eutran_to_geran_src_sai() runs on test_CT {
6736 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6737 pars.last_used_eutran_plmn := '323454'O;
6738 pars.cell_id_source := valueof(ts_CellID_SAI('123456'O, 300, 444));
6739 f_tc_ho_into_this_bsc_main(pars);
6740
6741 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6742 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6743 f_ctrs_bsc_and_bts_verify();
6744 f_shutdown_helper();
6745}
6746
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006747private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
6748 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
6749 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
6750 f_ho_into_this_bsc(id, oldToNewBSSIEs);
6751 f_ho_out_of_this_bsc(oldToNewBSSIEs);
6752 setverdict(pass);
6753}
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006754
6755private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
6756 runs on test_CT {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006757 var MSC_ConnHdlr vc_conn;
6758 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6759
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006760 f_init_vty();
6761 f_bts_0_cfg(BSCVTY,
6762 {"neighbor-list mode automatic",
6763 "handover 1",
6764 "handover algorithm 2",
6765 "handover2 window rxlev averaging 1",
6766 "no neighbors",
6767 "neighbor lac 99 arfcn 123 bsic any"});
6768 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6769
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006770 f_init(1, true);
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006771 if (disable_fast_return) {
6772 f_vty_allow_srvcc_fast_return(true, 0);
6773 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006774 f_sleep(1.0);
6775
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006776 f_ctrs_bsc_and_bts_handover_init();
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006777
6778 pars.last_used_eutran_plmn := '323454'O;
6779 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6780 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
6781
6782 vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
6783 vc_conn.done;
6784
6785 f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
6786 f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
6787 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
6788 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
6789 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
6790 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006791
6792 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
6793 f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006794 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006795
6796 if (disable_fast_return) {
6797 f_vty_allow_srvcc_fast_return(false, 0);
6798 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006799 f_shutdown_helper();
6800}
6801
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006802/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
6803 BSS Information" IE with "Last Used E-UTRAN PLMN Id".
6804 Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
6805 IE with "Last Used E-UTRAN PLMN Id" from first step. */
6806testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
6807 f_tc_srvcc_eutran_to_geran_ho_out_main(false);
6808}
6809/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
6810 * independently of fast-reture allowed/forbidden in local BTS */
6811testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
6812 f_tc_srvcc_eutran_to_geran_ho_out_main(true);
6813}
6814
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006815private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
6816 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6817 f_rslem_register(0, new_chan_nr);
6818 g_chan_nr := new_chan_nr;
6819 f_sleep(1.0);
6820
6821 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6822 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6823 activate(as_Media());
6824
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006825 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006826 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006827 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006828
6829 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6830
6831 var PDU_BSSAP rx_bssap;
6832 var octetstring ho_command_str;
6833
6834 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6835
6836 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6837 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6838 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6839 log("L3 Info in HO Request Ack is ", ho_command);
6840
6841 var GsmArfcn arfcn;
6842 var RslChannelNr actual_new_chan_nr;
6843 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6844 actual_new_chan_nr, arfcn);
6845
6846 if (actual_new_chan_nr != new_chan_nr) {
6847 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6848 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6849 setverdict(fail);
6850 return;
6851 }
6852 log("Handover Command chan_nr is", actual_new_chan_nr);
6853
Neels Hofmeyr61ca08d2019-05-06 23:52:22 +02006854 /* For deterministic test results, give some time for the MGW endpoint to be configured */
6855 f_sleep(1.0);
6856
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006857 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6858 * tells the MS to handover to the new lchan. In this case, the MS
6859 * reports a Handover Failure to the old BSS, which forwards a BSSMAP
6860 * Handover Failure to the MSC. The procedure according to 3GPP TS
6861 * 48.008 3.1.5.3.2 "Handover Failure" is then that the MSC sends a
6862 * BSSMAP Clear Command: */
6863
6864 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6865 var BssmapCause cause := enum2int(cause_val);
6866 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6867
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006868 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006869 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006870 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006871
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006872 setverdict(pass);
6873 f_sleep(1.0);
6874
6875 setverdict(pass);
6876}
6877testcase TC_ho_in_fail_msc_clears() runs on test_CT {
6878 var MSC_ConnHdlr vc_conn;
6879 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6880
6881 f_init(1, true);
6882 f_sleep(1.0);
6883
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006884 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006885
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006886 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6887 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006888
6889 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
6890 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006891
6892 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6893 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6894 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6895 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6896 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006897 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006898}
6899
6900private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
6901 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6902 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6903 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6904 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6905 * before we get started. */
6906 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6907 f_rslem_register(0, new_chan_nr);
6908 g_chan_nr := new_chan_nr;
6909 f_sleep(1.0);
6910
6911 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6912 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6913 activate(as_Media());
6914
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006915 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006916 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006917 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006918
6919 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6920
6921 var PDU_BSSAP rx_bssap;
6922 var octetstring ho_command_str;
6923
6924 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6925
6926 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6927 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6928 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6929 log("L3 Info in HO Request Ack is ", ho_command);
6930
6931 var GsmArfcn arfcn;
6932 var RslChannelNr actual_new_chan_nr;
6933 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6934 actual_new_chan_nr, arfcn);
6935
6936 if (actual_new_chan_nr != new_chan_nr) {
6937 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6938 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6939 setverdict(fail);
6940 return;
6941 }
6942 log("Handover Command chan_nr is", actual_new_chan_nr);
6943
6944 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6945 * tells the MS to handover to the new lchan. Here comes the new MS on
6946 * the new lchan with a Handover RACH: */
6947
6948 /* send handover detect */
6949
6950 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6951
6952 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6953
6954 /* The MSC chooses to clear the connection now, maybe we got the
6955 * Handover RACH on the new cell but the MS still signaled Handover
6956 * Failure to the old BSS? */
6957
6958 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6959 var BssmapCause cause := enum2int(cause_val);
6960 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6961
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006962 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006963 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006964 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006965
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006966 f_sleep(1.0);
6967}
6968testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
6969 var MSC_ConnHdlr vc_conn;
6970 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6971
6972 f_init(1, true);
6973 f_sleep(1.0);
6974
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006975 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006976
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006977 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6978 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006979
6980 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
6981 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006982
6983 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6984 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6985 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6986 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6987 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006988 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006989}
6990
6991/* The new BSS's lchan times out before the MSC decides that handover failed. */
6992private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
6993 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6994 f_rslem_register(0, new_chan_nr);
6995 g_chan_nr := new_chan_nr;
6996 f_sleep(1.0);
6997
6998 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6999 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01007000 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007001
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007002 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007003 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02007004 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007005
7006 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
7007
7008 var PDU_BSSAP rx_bssap;
7009 var octetstring ho_command_str;
7010
7011 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
7012
7013 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
7014 log("Received L3 Info in HO Request Ack: ", ho_command_str);
7015 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
7016 log("L3 Info in HO Request Ack is ", ho_command);
7017
7018 var GsmArfcn arfcn;
7019 var RslChannelNr actual_new_chan_nr;
7020 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
7021 actual_new_chan_nr, arfcn);
7022
7023 if (actual_new_chan_nr != new_chan_nr) {
7024 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
7025 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
7026 setverdict(fail);
7027 return;
7028 }
7029 log("Handover Command chan_nr is", actual_new_chan_nr);
7030
7031 /* Now the MSC forwards the RR Handover Command to the other BSC, which
7032 * tells the MS to handover to the new lchan. But the MS never shows up
7033 * on the new lchan. */
7034
7035 BSSAP.receive(tr_BSSMAP_HandoverFailure);
7036
7037 /* Did osmo-bsc also send a Clear Request? */
7038 timer T := 0.5;
7039 T.start;
7040 alt {
7041 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
7042 [] T.timeout { }
7043 }
7044
7045 /* MSC plays along with a Clear Command (no matter whether osmo-bsc
7046 * asked for it, this is a Handover Failure after all). */
7047
7048 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
7049 var BssmapCause cause := enum2int(cause_val);
7050 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7051
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007052 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007053 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007054 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007055
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007056 f_sleep(1.0);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007057}
7058testcase TC_ho_in_fail_no_detect() runs on test_CT {
7059 var MSC_ConnHdlr vc_conn;
7060 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7061
Oliver Smithd49f46d2023-03-08 12:23:13 +01007062 pars.fail_on_dlcx := false;
7063
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007064 f_init(1, true);
7065 f_sleep(1.0);
7066
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007067 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007068
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007069 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7070 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007071
7072 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect), pars);
7073 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007074
7075 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7076 f_ctrs_bsc_and_bts_add(0, "handover:error");
7077 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7078 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7079 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007080 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007081}
7082
7083/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
7084private function f_tc_ho_in_fail_no_detect2(charstring id) runs on MSC_ConnHdlr {
7085 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
7086 f_rslem_register(0, new_chan_nr);
7087 g_chan_nr := new_chan_nr;
7088 f_sleep(1.0);
7089
7090 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
7091 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01007092 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007093
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007094 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007095 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02007096 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007097
7098 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
7099
7100 var PDU_BSSAP rx_bssap;
7101 var octetstring ho_command_str;
7102
7103 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
7104
7105 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
7106 log("Received L3 Info in HO Request Ack: ", ho_command_str);
7107 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
7108 log("L3 Info in HO Request Ack is ", ho_command);
7109
7110 var GsmArfcn arfcn;
7111 var RslChannelNr actual_new_chan_nr;
7112 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
7113 actual_new_chan_nr, arfcn);
7114
7115 if (actual_new_chan_nr != new_chan_nr) {
7116 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
7117 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
7118 setverdict(fail);
7119 return;
7120 }
7121 log("Handover Command chan_nr is", actual_new_chan_nr);
7122
7123 /* Now the MSC forwards the RR Handover Command to the other BSC, which
7124 * tells the MS to handover to the new lchan. But the MS never shows up
7125 * on the new lchan. */
7126
7127 BSSAP.receive(tr_BSSMAP_HandoverFailure);
7128
7129 /* MSC plays dumb and sends no Clear Command */
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007130 var PDU_BSSAP rx_clear_request;
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02007131
7132 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request {
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007133 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
7134 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7135 };
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007136 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007137 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007138 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007139
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007140 f_sleep(1.0);
7141}
7142testcase TC_ho_in_fail_no_detect2() runs on test_CT {
7143 var MSC_ConnHdlr vc_conn;
7144 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7145
Oliver Smith735b47c2023-02-15 16:03:54 +01007146 pars.fail_on_dlcx := false;
7147
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007148 f_init(1, true);
7149 f_sleep(1.0);
7150
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007151 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007152
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007153 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7154 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007155
7156 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
7157 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007158
7159 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7160 f_ctrs_bsc_and_bts_add(0, "handover:error");
7161 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7162 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7163 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007164 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007165}
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01007166
Oliver Smith7a8594a2023-02-13 14:30:49 +01007167testcase TC_ho_in_fail_mgw_mdcx_timeout() runs on test_CT {
7168 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7169
7170 pars.ignore_mgw_mdcx := true;
7171 pars.expect_ho_fail_lchan_est := true;
7172
7173 f_tc_ho_into_this_bsc_main(pars);
7174 f_shutdown_helper(ho := true);
7175}
7176
Oliver Smith4eed06f2023-02-15 15:43:19 +01007177testcase TC_ho_in_fail_ipa_crcx_timeout() runs on test_CT {
7178 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7179
7180 pars.ignore_ipa_media := true;
7181 pars.expect_ho_fail_lchan_est := true;
7182 pars.fail_on_dlcx := false;
7183
7184 f_tc_ho_into_this_bsc_main(pars);
7185 f_shutdown_helper(ho := true);
7186}
7187
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007188/* An incoming inter-BSC HO can either issue the Handover Request message attached to the initial SCCP N-Connect (as in
7189 * the other tests we have so far), or the first CR can be "empty" with the BSSAP request following later. Test the
7190 * empty N-Connect case. */
7191testcase TC_ho_into_this_bsc_sccp_cr_without_bssap() runs on test_CT {
7192 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7193 pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr := false;
7194 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02007195 f_shutdown_helper(ho := true);
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007196}
7197
Neels Hofmeyr91401012019-07-11 00:42:35 +02007198type record of charstring Commands;
7199
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007200private function f_bts_0_cfg(TELNETasp_PT pt, Commands cmds := {})
Neels Hofmeyr91401012019-07-11 00:42:35 +02007201{
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007202 f_vty_enter_cfg_bts(pt, 0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007203 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007204 f_vty_transceive(pt, cmds[i]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007205 }
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007206 f_vty_transceive(pt, "end");
Neels Hofmeyr91401012019-07-11 00:42:35 +02007207}
7208
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01007209private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
7210{
7211 f_vty_enter_cfg_cs7_inst(pt, 0);
7212 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
7213 f_vty_transceive(pt, cmds[i]);
7214 }
7215 f_vty_transceive(pt, "end");
7216}
7217
Neels Hofmeyr91401012019-07-11 00:42:35 +02007218private function f_probe_for_handover(charstring log_label,
7219 charstring log_descr,
7220 charstring handover_vty_cmd,
7221 boolean expect_handover,
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007222 boolean is_inter_bsc_handover := false,
7223 template uint3_t expect_target_tsc := ?)
Neels Hofmeyr91401012019-07-11 00:42:35 +02007224runs on MSC_ConnHdlr
7225{
Neels Hofmeyrb3fc8982020-05-11 00:16:42 +02007226 /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
7227 * lchans to be established on bts 1 or bts 2. */
7228 f_rslem_suspend(RSL1_PROC);
7229 f_rslem_suspend(RSL2_PROC);
7230
Neels Hofmeyr91401012019-07-11 00:42:35 +02007231 var RSL_Message rsl;
7232
7233 var charstring log_msg := " (expecting handover)"
7234 if (not expect_handover) {
7235 log_msg := " (expecting NO handover)";
7236 }
7237 log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg);
7238 f_vty_transceive(BSCVTY, handover_vty_cmd);
7239
Neels Hofmeyr91401012019-07-11 00:42:35 +02007240 timer T := 2.0;
7241 T.start;
7242
7243 alt {
7244 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
7245 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
7246 log("Rx L3 from net: ", l3);
7247 if (ischosen(l3.msgs.rrm.handoverCommand)) {
7248 var RslChannelNr new_chan_nr;
7249 var GsmArfcn arfcn;
7250 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
7251 new_chan_nr, arfcn);
7252 log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
7253 log(l3.msgs.rrm.handoverCommand);
7254
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007255 /* Verify correct TSC in handoverCommand */
7256 var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
7257 if (not match(got_tsc, expect_target_tsc)) {
7258 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
7259 expect_target_tsc, " got ", got_tsc);
7260 mtc.stop;
7261 } else {
7262 log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
7263 expect_target_tsc, ")");
7264 }
7265
Neels Hofmeyr91401012019-07-11 00:42:35 +02007266 /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
7267 * matter on which BTS it really is, we're not going to follow through an entire handover
7268 * anyway. */
7269 f_rslem_register(0, new_chan_nr, RSL1_PROC);
7270 f_rslem_resume(RSL1_PROC);
7271 f_rslem_register(0, new_chan_nr, RSL2_PROC);
7272 f_rslem_resume(RSL2_PROC);
7273
7274 if (expect_handover and not is_inter_bsc_handover) {
7275 setverdict(pass);
7276 log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected.");
7277 } else {
7278 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. "
7279 & log_label & ": " & log_descr);
7280 }
7281
7282 log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
7283 /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with
7284 * Handover Failure. */
7285 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
7286
7287 /* target BTS is told to release lchan again; don't care which BTS nor what messages. */
7288 f_sleep(0.5);
7289 RSL1.clear;
7290 RSL2.clear;
7291 log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)");
7292 break;
7293 } else {
7294 repeat;
7295 }
7296 }
7297 [] BSSAP.receive(tr_BSSMAP_HandoverRequired) {
7298 if (expect_handover and is_inter_bsc_handover) {
7299 setverdict(pass);
7300 log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected.");
7301 } else {
7302 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. "
7303 & log_label & ": " & log_descr);
7304 }
7305
7306 log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)");
7307
7308 /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to
7309 * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required,
7310 * setting a short timeout and waiting is the only way. */
7311 log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out...");
7312 f_sleep(1.5);
7313 log("f_probe_for_handover(" & log_label & "): ...done");
7314
7315 break;
7316 }
7317 [] T.timeout {
7318 if (expect_handover) {
7319 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. "
7320 & log_label & ": " & log_descr);
7321 } else {
7322 setverdict(pass);
7323 log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected.");
7324 }
7325 log("f_probe_for_handover(" & log_label & "): done (got no Handover)");
7326 break;
7327 }
7328 }
7329
7330 f_rslem_resume(RSL1_PROC);
7331 f_rslem_resume(RSL2_PROC);
7332 f_sleep(3.0);
7333 RSL.clear;
7334
7335 log("f_probe_for_handover(" & log_label & "): done clearing");
7336}
7337
7338/* Test the effect of various neighbor configuration scenarios:
7339 *
7340 * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0.
7341 * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO.
7342 */
7343private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
7344 g_pars := f_gen_test_hdlr_pars();
7345 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
7346 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007347
7348 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
7349 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
7350
7351 /* Establish lchan at bts 0 */
7352 f_establish_fully(ass_cmd, exp_compl);
7353
7354 /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */
7355 f_vty_enter_cfg_network(BSCVTY);
7356 f_vty_transceive(BSCVTY, "timer T7 1");
7357 f_vty_transceive(BSCVTY, "end");
7358}
7359
7360private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
7361 f_tc_ho_neighbor_config_start();
7362
7363 /*
7364 * bts 0 ARFCN 871 BSIC 10
7365 * bts 1 ARFCN 871 BSIC 11
7366 * bts 2 ARFCN 871 BSIC 12
7367 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7368 */
7369
7370 log("f_tc_ho_neighbor_config: 1. No 'neighbor' config");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007371 f_bts_0_cfg(BSCVTY, {"no neighbors"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007372 f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
7373 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007374 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007375
7376 f_probe_for_handover("1.b", "HO to unknown cell does not start",
7377 "handover any to arfcn 13 bsic 39",
7378 false);
7379
7380 f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error",
7381 "handover any to arfcn 871 bsic 12",
7382 false);
7383
7384 f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
7385 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007386 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007387
7388 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007389}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007390testcase TC_ho_neighbor_config_1() runs on test_CT {
7391 var MSC_ConnHdlr vc_conn;
7392 f_init(3, true, guard_timeout := 60.0);
7393 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007394 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007395 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
7396 vc_conn.done;
7397
7398 /* f_tc_ho_neighbor_config_start() */
7399 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7400 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7401
7402 /* 1.a */
7403 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7404 * handover quickly by sending a Handover Failure message. */
7405 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7406 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7407 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7408 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007409 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7410 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007411
7412 /* 1.b */
7413 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7414 f_ctrs_bsc_and_bts_add(0, "handover:error");
7415
7416 /* 1.c */
7417 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7418 f_ctrs_bsc_and_bts_add(0, "handover:error");
7419
7420 /* 1.d */
7421 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7422 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7423 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7424 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007425 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7426 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007427
7428 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007429 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007430}
7431
Neels Hofmeyr91401012019-07-11 00:42:35 +02007432private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
7433 f_tc_ho_neighbor_config_start();
7434
7435 /*
7436 * bts 0 ARFCN 871 BSIC 10
7437 * bts 1 ARFCN 871 BSIC 11
7438 * bts 2 ARFCN 871 BSIC 12
7439 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7440 */
7441
7442 log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007443 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007444 f_sleep(0.5);
7445
7446 f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
7447 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007448 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007449
7450 f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
7451 "handover any to arfcn 871 bsic 12",
7452 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007453 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007454}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007455testcase TC_ho_neighbor_config_2() runs on test_CT {
7456 var MSC_ConnHdlr vc_conn;
7457 f_init(3, true, guard_timeout := 50.0);
7458 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007459 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007460 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
7461 vc_conn.done;
7462
7463 /* f_tc_ho_neighbor_config_start() */
7464 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7465 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7466
7467 /* 2.a */
7468 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7469 * handover quickly by sending a Handover Failure message. */
7470 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7471 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7472 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7473 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007474 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7475 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007476
7477 /* 2.b */
7478 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7479 f_ctrs_bsc_and_bts_add(0, "handover:error");
7480
7481 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007482 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007483}
7484
Neels Hofmeyr91401012019-07-11 00:42:35 +02007485private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
7486 f_tc_ho_neighbor_config_start();
7487
7488 /*
7489 * bts 0 ARFCN 871 BSIC 10
7490 * bts 1 ARFCN 871 BSIC 11
7491 * bts 2 ARFCN 871 BSIC 12
7492 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7493 */
7494
7495 log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007496 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007497 f_sleep(0.5);
7498
7499 f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor",
7500 "handover any to arfcn 871 bsic 11",
7501 false);
7502 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",
7503 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007504 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007505 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007506}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007507testcase TC_ho_neighbor_config_3() runs on test_CT {
7508 var MSC_ConnHdlr vc_conn;
7509 f_init(3, true, guard_timeout := 50.0);
7510 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007511 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007512 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
7513 vc_conn.done;
7514
7515 /* f_tc_ho_neighbor_config_start() */
7516 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7517 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7518
7519 /* 3.a */
7520 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7521 f_ctrs_bsc_and_bts_add(0, "handover:error");
7522
7523 /* 3.b */
7524 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7525 * handover quickly by sending a Handover Failure message. */
7526 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7527 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7528 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7529 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007530 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7531 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007532
7533 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007534 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007535}
7536
Neels Hofmeyr91401012019-07-11 00:42:35 +02007537private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
7538 f_tc_ho_neighbor_config_start();
7539
7540 /*
7541 * bts 0 ARFCN 871 BSIC 10
7542 * bts 1 ARFCN 871 BSIC 11
7543 * bts 2 ARFCN 871 BSIC 12
7544 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7545 */
7546
7547 log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007548 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007549 f_sleep(0.5);
7550
7551 f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor",
7552 "handover any to arfcn 871 bsic 11",
7553 false);
7554 f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor",
7555 "handover any to arfcn 871 bsic 12",
7556 false);
7557 f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
7558 "handover any to arfcn 123 bsic 45",
7559 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007560 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007561}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007562testcase TC_ho_neighbor_config_4() runs on test_CT {
7563 var MSC_ConnHdlr vc_conn;
7564 f_init(3, true, guard_timeout := 50.0);
7565 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007566 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007567 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
7568 vc_conn.done;
7569
7570 /* f_tc_ho_neighbor_config_start() */
7571 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7572 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7573
7574 /* 4.a */
7575 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7576 f_ctrs_bsc_and_bts_add(0, "handover:error");
7577
7578 /* 4.b */
7579 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7580 f_ctrs_bsc_and_bts_add(0, "handover:error");
7581
7582 /* 4.c */
7583 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7584 * handover quickly by timing out after the Handover Required message */
7585 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7586 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7587 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7588 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7589
7590 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007591 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007592}
7593
Neels Hofmeyr91401012019-07-11 00:42:35 +02007594private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
7595 f_tc_ho_neighbor_config_start();
7596
7597 /*
7598 * bts 0 ARFCN 871 BSIC 10
7599 * bts 1 ARFCN 871 BSIC 11
7600 * bts 2 ARFCN 871 BSIC 12
7601 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7602 */
7603
7604 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 +02007605 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007606 f_sleep(0.5);
7607
7608 f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
7609 "handover any to arfcn 871 bsic 12",
7610 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007611 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007612}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007613testcase TC_ho_neighbor_config_5() runs on test_CT {
7614 var MSC_ConnHdlr vc_conn;
7615 f_init(3, true);
7616 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007617 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007618 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
7619 vc_conn.done;
7620
7621 /* f_tc_ho_neighbor_config_start() */
7622 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7623 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7624
7625 /* 5 */
7626 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7627 * handover quickly by timing out after the Handover Required message */
7628 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7629 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7630 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7631 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7632
7633 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007634 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007635}
7636
Neels Hofmeyr91401012019-07-11 00:42:35 +02007637private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
7638 f_tc_ho_neighbor_config_start();
7639
7640 /*
7641 * bts 0 ARFCN 871 BSIC 10
7642 * bts 1 ARFCN 871 BSIC 11
7643 * bts 2 ARFCN 871 BSIC 12
7644 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7645 */
7646
7647 log("f_tc_ho_neighbor_config: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:"
7648 & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007649 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007650 f_sleep(0.5);
7651
7652 f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
7653 "handover any to arfcn 871 bsic 12",
7654 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007655 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007656}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007657testcase TC_ho_neighbor_config_6() runs on test_CT {
7658 var MSC_ConnHdlr vc_conn;
7659 f_init(3, true);
7660 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007661 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007662 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
7663 vc_conn.done;
7664
7665 /* f_tc_ho_neighbor_config_start() */
7666 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7667 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7668
7669 /* 6.a */
7670 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7671 * handover quickly by timing out after the Handover Required message */
7672 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7673 f_ctrs_bsc_and_bts_add(0, "handover:error");
7674
7675 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007676 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007677}
7678
Neels Hofmeyr91401012019-07-11 00:42:35 +02007679private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
7680 f_tc_ho_neighbor_config_start();
7681
7682 /*
7683 * bts 0 ARFCN 871 BSIC 10
7684 * bts 1 ARFCN 871 BSIC 11
7685 * bts 2 ARFCN 871 BSIC 12
7686 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7687 */
7688
7689 log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:"
7690 & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007691 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007692 f_sleep(0.5);
7693
7694 f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
7695 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007696 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007697 f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
7698 "handover any to arfcn 123 bsic 45",
7699 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007700 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007701}
Neels Hofmeyr91401012019-07-11 00:42:35 +02007702testcase TC_ho_neighbor_config_7() runs on test_CT {
7703 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf2b88032020-06-16 00:35:04 +02007704 f_init(3, true, guard_timeout := 50.0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007705 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007706 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007707 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
7708 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007709
7710 /* f_tc_ho_neighbor_config_start() */
7711 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7712 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7713
7714 /* 7.a */
7715 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7716 * handover quickly by sending a Handover Failure message. */
7717 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7718 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7719 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7720 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007721 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7722 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007723
7724 /* 7.b */
7725 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7726 * handover quickly by timing out after the Handover Required message */
7727 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7728 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7729 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7730 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7731
7732 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007733 f_shutdown_helper(ho := true);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007734}
7735
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007736/* OS#3041: Open and close N connections in a normal fashion, and expect no
7737 * BSSMAP Reset just because of that. */
7738testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
7739 var default d;
7740 var integer i;
7741 var DchanTuple dt;
7742
7743 f_init();
7744
7745 /* Wait for initial BSSMAP Reset to pass */
7746 f_sleep(4.0);
7747
7748 d := activate(no_bssmap_reset());
7749
7750 /* Setup up a number of connections and RLSD them again from the MSC
7751 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7752 * Let's do it some more times for good measure. */
Harald Weltec3260d92018-06-11 17:48:16 +02007753 for (i := 0; i < 4; i := i+1) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007754 /* Since we're doing a lot of runs, give each one a fresh
7755 * T_guard from the top. */
7756 T_guard.start;
7757
7758 /* Setup a BSSAP connection and clear it right away. This is
7759 * the MSC telling the BSC about a planned release, it's not an
7760 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007761 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007762
7763 /* MSC disconnects (RLSD). */
7764 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
7765 }
7766
7767 /* In the buggy behavior, a timeout of 2 seconds happens between above
7768 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7769 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7770 f_sleep(4.0);
7771
7772 deactivate(d);
7773 f_shutdown_helper();
7774}
Harald Welte552620d2017-12-16 23:21:36 +01007775
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007776/* OS#3041: Open and close N connections in a normal fashion, and expect no
7777 * BSSMAP Reset just because of that. Invoke the release by a BSSMAP Clear from
7778 * the MSC. */
7779testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
7780 var default d;
7781 var integer i;
7782 var DchanTuple dt;
7783 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007784 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
7785 var BssmapCause cause := enum2int(cause_val);
7786
7787 f_init();
7788
7789 /* Wait for initial BSSMAP Reset to pass */
7790 f_sleep(4.0);
7791
7792 d := activate(no_bssmap_reset());
7793
7794 /* Setup up a number of connections and RLSD them again from the MSC
7795 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7796 * Let's do it some more times for good measure. */
7797 for (i := 0; i < 8; i := i+1) {
7798 /* Since we're doing a lot of runs, give each one a fresh
7799 * T_guard from the top. */
7800 T_guard.start;
7801
7802 /* Setup a BSSAP connection and clear it right away. This is
7803 * the MSC telling the BSC about a planned release, it's not an
7804 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007805 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007806
7807 /* Instruct BSC to clear channel */
7808 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7809
7810 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007811 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007812 }
7813
7814 /* In the buggy behavior, a timeout of 2 seconds happens between above
7815 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7816 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7817 f_sleep(4.0);
7818
7819 deactivate(d);
7820 f_shutdown_helper();
7821}
7822
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007823/* OS#3041: Open and close N connections in a normal fashion, and expect no
7824 * BSSMAP Reset just because of that. Close connections from the MS side with a
7825 * Release Ind on RSL. */
7826testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
7827 var default d;
7828 var integer i;
7829 var DchanTuple dt;
7830 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007831 var integer j;
7832
7833 f_init();
7834
7835 /* Wait for initial BSSMAP Reset to pass */
7836 f_sleep(4.0);
7837
7838 d := activate(no_bssmap_reset());
7839
7840 /* Setup up a number of connections and RLSD them again from the MSC
7841 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7842 * Let's do it some more times for good measure. */
7843 for (i := 0; i < 8; i := i+1) {
7844 /* Since we're doing a lot of runs, give each one a fresh
7845 * T_guard from the top. */
7846 T_guard.start;
7847
7848 /* Setup a BSSAP connection and clear it right away. This is
7849 * the MSC telling the BSC about a planned release, it's not an
7850 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007851 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007852
7853 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007854 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007855
7856 /* expect Clear Request on MSC side */
7857 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
7858
7859 /* Instruct BSC to clear channel */
7860 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
7861 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7862
7863 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007864 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007865 }
7866
7867 /* In the buggy behavior, a timeout of 2 seconds happens between above
7868 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7869 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7870 f_sleep(4.0);
7871
7872 deactivate(d);
7873 f_shutdown_helper();
7874}
7875
Harald Welte94e0c342018-04-07 11:33:23 +02007876/***********************************************************************
7877 * IPA style dynamic PDCH
7878 ***********************************************************************/
7879
7880private function f_dyn_ipa_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7881 template (omit) RSL_Cause nack := omit)
7882runs on test_CT {
7883 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7884 var RSL_Message rsl_unused;
7885 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7886 f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
7887 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007888 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007889 if (istemplatekind(nack, "omit")) {
7890 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007891 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007892 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007893 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007894 }
7895}
7896
7897private function f_dyn_ipa_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7898 template (omit) RSL_Cause nack := omit)
7899runs on test_CT {
7900 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7901 var RSL_Message rsl_unused;
7902 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7903 f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
7904 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007905 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_DEACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007906 if (istemplatekind(nack, "omit")) {
7907 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007908 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007909 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007910 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007911 }
7912}
7913
7914private function f_ts_dyn_mode_get(integer bts_nr, integer trx_nr, integer ts_nr)
7915runs on test_CT return charstring {
7916 var charstring cmd, resp;
7917 cmd := "show timeslot "&int2str(bts_nr)&" "&int2str(trx_nr)&" "&int2str(ts_nr);
Stefan Sperlingcff13562018-11-13 15:24:06 +01007918 return f_vty_transceive_match_regexp_retry(BSCVTY, cmd, "*\((*)\)*", 0, 4, 1.0);
Harald Welte94e0c342018-04-07 11:33:23 +02007919}
7920
7921private function f_ts_dyn_mode_assert(integer bts_nr, integer trx_nr, integer ts_nr,
7922 template charstring exp)
7923runs on test_CT {
7924 var charstring mode := f_ts_dyn_mode_get(bts_nr, trx_nr, ts_nr);
7925 if (not match(mode, exp)) {
7926 setverdict(fail, "Unexpected TS Mode: ", mode);
Daniel Willmannafce8662018-07-06 23:11:32 +02007927 mtc.stop;
Harald Welte94e0c342018-04-07 11:33:23 +02007928 }
7929}
7930
7931private function f_ts_set_chcomb(integer bts_nr, integer trx_nr, integer ts_nr, charstring chcomb)
7932runs on test_CT {
7933 f_vty_enter_cfg_ts(BSCVTY, bts_nr, trx_nr, ts_nr);
7934 f_vty_transceive(BSCVTY, "phys_chan_config " & chcomb);
7935 f_vty_transceive(BSCVTY, "end");
7936}
7937
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007938
7939private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
7940 var integer i;
7941 for (i := 0; i < 8; i := i + 1) {
7942 f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
7943 }
7944}
7945
Harald Welte94e0c342018-04-07 11:33:23 +02007946private const charstring TCHF_MODE := "TCH/F mode";
7947private const charstring TCHH_MODE := "TCH/H mode";
7948private const charstring PDCH_MODE := "PDCH mode";
7949private const charstring NONE_MODE := "NONE mode";
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007950private const charstring SDCCH8_MODE := "SDCCH8 mode";
Harald Welte94e0c342018-04-07 11:33:23 +02007951
7952/* Test IPA PDCH activation / deactivation triggered by VTY */
7953testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
7954 var RSL_Message rsl_unused;
7955
7956 /* change Timeslot 6 before f_init() starts RSL */
7957 f_init_vty();
7958 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7959 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7960
7961 f_init(1, false);
7962 f_sleep(1.0);
7963
7964 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7965
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007966 log("TCH/F_PDCH pchan starts out in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007967 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7968 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007969 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7970 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007971 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007972 log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007973 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7974
7975 /* De-activate it via VTY */
7976 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7977 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007978 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007979 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7980
7981 /* re-activate it via VTY */
7982 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn);
7983 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007984 log("TCH/F_PDCH pchan, PDCH ACT via VTY, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007985 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7986
7987 /* and finally de-activate it again */
7988 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7989 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007990 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007991 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7992
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007993 /* clean up config */
7994 f_ts_set_chcomb(0, 0, 6, "PDCH");
7995
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007996 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007997}
7998
7999/* Test IPA PDCH activation NACK */
8000testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
8001 var RSL_Message rsl_unused;
8002
8003 /* change Timeslot 6 before f_init() starts RSL */
8004 f_init_vty();
8005 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
8006 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8007
8008 f_init(1, false);
8009 f_sleep(1.0);
8010
8011 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
8012
8013 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
8014 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008015 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
8016 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02008017 f_sleep(1.0);
8018 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
8019
8020 /* De-activate it via VTY */
8021 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
8022 f_sleep(1.0);
8023 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
8024
8025 /* re-activate it via VTY, but fail that; check BSC still assumes TCH/F mode */
8026 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn, RSL_ERR_EQUIPMENT_FAIL);
8027 f_sleep(1.0);
8028 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
8029
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008030 /* clean up config */
8031 f_ts_set_chcomb(0, 0, 6, "PDCH");
8032
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008033 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008034}
8035
8036
8037/***********************************************************************
8038 * Osmocom style dynamic PDCH
8039 ***********************************************************************/
8040
8041private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
8042 template (omit) RSL_Cause nack := omit)
8043runs on test_CT {
8044 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
8045 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02008046 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02008047 /* FIXME: no VTY command to activate Osmocom PDCH !! */
8048 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008049 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT(chan_nr, ?));
Harald Welte94e0c342018-04-07 11:33:23 +02008050 if (istemplatekind(nack, "omit")) {
8051 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008052 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02008053 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008054 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02008055 }
8056}
8057
8058private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
8059 template (omit) RSL_Cause nack := omit)
8060runs on test_CT {
8061 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
8062 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02008063 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02008064 /* FIXME: no VTY command to activate Osmocom PDCH !! */
8065 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008066 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008067 if (istemplatekind(nack, "omit")) {
8068 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008069 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008070 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008071 //f_ipa_tx(ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02008072 }
8073}
8074
8075/* Test Osmocom dyn PDCH activation / deactivation triggered by VTY */
8076testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
8077 var RSL_Message rsl_unused;
8078
8079 /* change Timeslot 6 before f_init() starts RSL */
8080 f_init_vty();
8081 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8082 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8083
8084 f_init(1, false);
8085 f_sleep(1.0);
8086
8087 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8088
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008089 log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02008090 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8091 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008092 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008093
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008094 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02008095 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008096 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 +02008097 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
8098
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008099 /* clean up config */
8100 f_ts_set_chcomb(0, 0, 6, "PDCH");
8101
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008102 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008103}
8104
8105/* Test Osmocom dyn PDCH activation NACK behavior */
8106testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
8107 var RSL_Message rsl_unused;
8108
8109 /* change Timeslot 6 before f_init() starts RSL */
8110 f_init_vty();
8111 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8112 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8113
8114 f_init(1, false);
8115 f_sleep(1.0);
8116
8117 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8118
8119 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8120 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008121 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008122
8123 /* NACK this activation and expect the "show timeslot" mode still to be NONE */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008124 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte94e0c342018-04-07 11:33:23 +02008125 f_sleep(1.0);
8126 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8127
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008128 /* clean up config */
8129 f_ts_set_chcomb(0, 0, 6, "PDCH");
8130
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008131 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008132}
8133
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008134/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
8135testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
8136 var RSL_Message rsl_unused, rsl_msg;
8137 var DchanTuple dt;
8138 var BSSAP_N_CONNECT_ind rx_c_ind;
8139
8140 /* change Timeslot 6 before f_init() starts RSL */
8141 f_init_vty();
8142 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8143 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8144
8145 f_init(1, false);
8146 f_sleep(1.0);
8147
8148 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8149
8150 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8151 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8152 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008153 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008154
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008155 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008156 f_sleep(1.0);
8157 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8158 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8159
8160 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8161 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008162 var DchanTuples sdcch_cleanup := {};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008163 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008164 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008165 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008166 sdcch_cleanup := sdcch_cleanup & { dt };
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008167 }
8168
8169 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008170 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8171 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8172 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008173
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008174 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008175 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008176 dt.idx := {0, 0};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008177
8178 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008179 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8180 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008181 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
8182
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008183 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 +02008184 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8185 dt.sccp_conn_id := rx_c_ind.connectionId;
8186 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8187
8188 /* Instruct BSC to clear channel */
8189 var BssmapCause cause := 0;
8190 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008191 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008192
8193 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008194 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8195 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008196 f_sleep(1.0);
8197 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8198
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008199 /* Clean up SDCCH lchans */
8200 for (i := 0; i < lengthof(sdcch_cleanup); i := i + 1) {
8201 f_perform_clear_test_ct(sdcch_cleanup[i]);
8202 }
8203
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008204 /* clean up config */
8205 f_ts_set_chcomb(0, 0, 6, "PDCH");
8206
8207 f_shutdown_helper();
8208}
8209
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008210/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
8211testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
8212 var ASP_RSL_Unitdata rsl_ud;
8213 var integer i;
8214 var integer chreq_total, chreq_nochan;
8215
8216 f_init_vty();
8217 for (i := 1; i < 8; i := i + 1) {
8218 if (i == 2) {
8219 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8220 } else {
8221 f_ts_set_chcomb(0, 0, i, "PDCH");
8222 }
8223 }
8224 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8225
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008226 f_init(1, guard_timeout := 60.0);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008227
8228 /* The dyn TS want to activate PDCH mode, ACK that. */
8229 var RslChannelNr chan_nr;
8230 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008231 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
8232 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008233
8234 f_sleep(1.0);
8235
8236 /* Exhaust all dedicated SDCCH lchans.
8237 /* GSM 44.018 Table 9.1.8.2:
8238 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
8239 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008240 var DchanTuples chan_cleanup := {};
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008241 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008242 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 +02008243 }
8244
8245 /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008246 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 +02008247 /* Also occupy the seven other SDCCH of the dyn TS */
8248 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008249 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 +01008250 }
8251
8252 /* Clean up SDCCH lchans */
8253 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8254 f_perform_clear_test_ct(chan_cleanup[i]);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008255 }
8256
8257 /* clean up config */
8258 f_ts_reset_chcomb(0);
8259
8260 f_shutdown_helper();
8261}
8262
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008263/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
8264 SDCCH8 would end up in having no free TCH, then BSC should decide to activate
8265 it as TCH directly instead. SYS#5309. */
8266testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
8267 var RSL_Message rsl_unused, rsl_msg;
8268 var DchanTuple dt;
8269 var BSSAP_N_CONNECT_ind rx_c_ind;
8270 var integer i;
8271
8272 /* change Timeslot 6 before f_init() starts RSL */
8273 f_init_vty();
8274 for (i := 1; i < 8; i := i + 1) {
8275 if (i == 6) {
8276 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8277 } else {
8278 f_ts_set_chcomb(0, 0, i, "PDCH");
8279 }
8280 }
8281 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8282
8283 f_init(1, false);
8284 f_sleep(1.0);
8285
8286 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8287
8288 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8289 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8290 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008291 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008292
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008293 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008294 f_sleep(1.0);
8295 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8296 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8297
8298 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8299 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008300 var DchanTuples chan_cleanup := {};
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02008301 var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008302 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008303 dt := f_est_dchan(ra, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008304 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008305 }
8306
8307 /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008308 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
8309 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8310 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008311
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008312 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008313 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008314 dt.idx := {0, 0};
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008315
8316 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008317 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8318 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008319 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
8320
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008321 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 +02008322 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8323 dt.sccp_conn_id := rx_c_ind.connectionId;
8324 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8325
8326 /* Instruct BSC to clear channel */
8327 var BssmapCause cause := 0;
8328 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008329 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008330
8331 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008332 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8333 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008334 f_sleep(1.0);
8335 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8336
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008337 /* Clean up SDCCH lchans */
8338 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8339 f_perform_clear_test_ct(chan_cleanup[i]);
8340 }
8341
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008342 /* clean up config */
8343 f_ts_reset_chcomb(0);
8344 /* TODO: clean up other channels? */
8345
8346 f_shutdown_helper();
8347}
8348
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008349/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
8350testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
8351 var RSL_Message rsl_unused, rsl_msg;
8352 var DchanTuple dt;
8353 var BSSAP_N_CONNECT_ind rx_c_ind;
8354 var GsmRrMessage rr;
8355
8356 /* change Timeslot 6 before f_init() starts RSL */
8357 f_init_vty();
8358 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8359 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8360
8361 f_init(1, false);
8362 f_sleep(1.0);
8363
8364 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8365
8366 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8367 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8368 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008369 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008370
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008371 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008372 f_sleep(1.0);
8373 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8374 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8375
8376 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8377 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008378 var DchanTuples chan_cleanup := {};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008379 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008380 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008381 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008382 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008383 }
8384
8385 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008386 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8387 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8388 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008389
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008390 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008391 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008392 dt.idx := {0, 0};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008393
8394 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008395 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
8396 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008397 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
8398 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
8399 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
8400 }
8401
8402 /* FIXME? Currently the TS stays in state BORKEN: */
8403
8404 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008405 /* rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8406 * f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008407 * f_sleep(1.0);
8408 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
8409 */
8410
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008411 /* Clean up SDCCH lchans */
8412 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8413 f_perform_clear_test_ct(chan_cleanup[i]);
8414 }
8415
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008416 /* clean up config */
8417 f_ts_set_chcomb(0, 0, 6, "PDCH");
8418
8419 f_shutdown_helper();
8420}
8421
Stefan Sperling0796a822018-10-05 13:01:39 +02008422testcase TC_chopped_ipa_ping() runs on test_CT {
Stefan Sperling554123f2018-10-09 14:12:30 +02008423 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port, mp_bsc_ctrl_port};
Stefan Sperling0796a822018-10-05 13:01:39 +02008424 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8425 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8426 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008427 f_shutdown_helper();
Stefan Sperling0796a822018-10-05 13:01:39 +02008428}
8429
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008430testcase TC_chopped_ipa_payload() runs on test_CT {
8431 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port
8432 /* TODO: mp_bsc_ctrl_port does not work yet */};
8433 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8434 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8435 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008436 f_shutdown_helper();
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008437}
8438
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008439/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
8440 the BTS does autonomous MS power control loop */
8441testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
8442 var MSC_ConnHdlr vc_conn;
8443 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8444 //pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
8445 pars.exp_ms_power_params := true;
8446
8447 f_init(1, true);
8448 f_sleep(1.0);
8449 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
8450 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008451 f_shutdown_helper();
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008452}
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008453
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008454/* Verify activation and deactivation of the BCCH carrier power reduction mode */
8455testcase TC_c0_power_red_mode() runs on test_CT {
8456 f_init(1);
8457
8458 for (var integer red := 6; red >= 0; red := red - 2) {
8459 /* Configure BCCH carrier power reduction mode via the VTY */
8460 f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
8461
8462 /* Expect Osmocom specific BS Power Control message on the RSL */
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03008463 var template (present) RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008464 chan_nr := t_RslChanNr_BCCH(0),
8465 bs_power := tr_RSL_IE_BS_Power(red / 2));
8466 tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008467 var RSL_Message unused := f_exp_ipa_rx(tr_rsl_pdu);
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008468
8469 /* Additionally verify the applied value over the CTRL interface */
8470 var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
8471 if (cred != int2str(red)) {
8472 setverdict(fail, "Unexpected BCCH carrier power reduction value ",
8473 cred, " (expected ", red, ")");
8474 }
8475 }
8476
8477 f_shutdown_helper();
8478}
8479
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008480/***********************************************************************
8481 * MSC Pooling
8482 ***********************************************************************/
8483
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008484template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
Harald Weltebf397612021-01-14 20:39:46 +01008485 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 +02008486
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008487private 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 +02008488runs on MSC_ConnHdlr {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008489 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008490 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008491 f_logp(BSCVTY, "Got RSL RR Release");
8492 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008493 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008494 f_logp(BSCVTY, "Got RSL Deact SACCH");
8495 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008496 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008497 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008498 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8499 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008500 break;
8501 }
8502 }
8503}
8504
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008505private altstep as_mgcp_ack_all_dlcx() runs on MSC_ConnHdlr {
8506 var MgcpCommand mgcp_cmd;
Oliver Smithab7354b2023-05-08 11:34:30 +02008507 var template MgcpMessage msg_dlcx := {
8508 command := tr_DLCX
8509 }
8510 var MGCP_RecvFrom mrf;
8511
8512 [g_pars.aoip] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008513 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
8514 repeat;
8515 }
Oliver Smithab7354b2023-05-08 11:34:30 +02008516
8517 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
8518 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
8519 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
8520 }));
8521 repeat;
8522 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008523}
8524
8525private altstep as_rsl_ack_all_rel_req() runs on MSC_ConnHdlr {
8526 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
8527 [] RSL.receive(tr_RSL_REL_REQ(g_chan_nr, ?)) {
8528 RSL.send(ts_RSL_REL_CONF(g_chan_nr, main_dcch));
8529 repeat;
8530 }
8531}
8532
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008533friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
Neels Hofmeyr8f4db542023-11-22 04:15:10 +01008534 template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE,
8535 boolean send_rel_ack := true)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02008536runs on MSC_ConnHdlr {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008537 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8538 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008539 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008540 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8541 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008542 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008543 f_logp(BSCVTY, "Got RSL RR Release");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008544 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008545 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008546 f_logp(BSCVTY, "Got RSL Deact SACCH");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008547 }
8548 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008549 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008550 /* Also drop the SCCP connection */
8551 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8552 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008553 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008554 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr8f4db542023-11-22 04:15:10 +01008555 if (send_rel_ack) {
8556 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8557 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
8558 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008559 }
8560 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008561 deactivate(ack_dlcx);
8562 deactivate(ack_rel_req);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008563}
8564
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01008565friend function f_perform_clear_no_rr_rel(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC)
8566runs on MSC_ConnHdlr {
8567 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8568 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
8569 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8570 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8571 interleave {
8572 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
8573 f_logp(BSCVTY, "Got RSL Deact SACCH");
8574 }
8575 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
8576 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8577 /* Also drop the SCCP connection */
8578 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8579 }
8580 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
8581 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
8582 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8583 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
8584 }
8585 }
8586 deactivate(ack_dlcx);
8587 deactivate(ack_rel_req);
8588}
8589
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01008590friend function f_perform_clear_no_lchan()
8591runs on MSC_ConnHdlr {
8592 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8593 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8594 BSSAP.receive(tr_BSSMAP_ClearComplete);
8595 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8596 /* Also drop the SCCP connection */
8597 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8598}
8599
Vadim Yanitskiy65d879d2022-06-23 18:15:39 +07008600friend function f_perform_clear_test_ct(DchanTuple dt)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008601 runs on test_CT
8602{
8603 /* Instruct BSC to clear channel */
8604 var BssmapCause cause := 0;
8605 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008606 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008607}
8608
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008609private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
8610 template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008611runs on MSC_ConnHdlr {
8612 timer T := 10.0;
8613 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
8614
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008615 f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008616 f_create_bssmap_exp(l3_enc);
8617
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008618 /* RSL_Emulation.f_chan_est() on rsl_pt:
8619 * This is basically code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008620 * RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
8621 */
8622 var RSL_Message rx_rsl;
8623 var GsmRrMessage rr;
8624
8625 /* request a channel to be established */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008626 rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008627 /* expect immediate assignment.
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008628 * Code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008629 * rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
8630 */
8631 timer Tt := 10.0;
8632
8633 /* request a channel to be established */
8634 Tt.start;
8635 alt {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008636 [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008637 Tt.stop;
8638 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008639 [] rsl_pt.receive {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008640 setverdict(fail, "Unexpected RSL message on DCHAN");
8641 mtc.stop;
8642 }
8643 [] Tt.timeout {
8644 setverdict(fail, "Timeout waiting for RSL on DCHAN");
8645 mtc.stop;
8646 }
8647 }
8648 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
8649 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008650 rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008651
8652
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008653 if (expect_bssmap_l3) {
8654 f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
8655 var template PDU_BSSAP exp_l3_compl;
8656 exp_l3_compl := tr_BSSMAP_ComplL3()
8657 if (g_pars.aoip == false) {
8658 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
8659 } else {
8660 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
8661 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008662
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008663 var PDU_BSSAP bssap;
8664 T.start;
8665 alt {
8666 [] BSSAP.receive(exp_l3_compl) -> value bssap {
8667 f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
8668 log("rx exp_l3_compl = ", bssap);
8669 }
8670 [] BSSAP.receive(tr_BSSMAP_ComplL3) {
8671 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
8672 }
8673 [] T.timeout {
8674 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
8675 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008676 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008677
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008678 /* start ciphering, if requested */
8679 if (ispresent(g_pars.encr)) {
8680 f_logp(BSCVTY, "start ciphering");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008681 f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008682 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008683 }
8684
8685 if (do_clear) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008686 f_perform_clear(rsl_pt, rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008687 }
8688 setverdict(pass);
8689 f_sleep(1.0);
8690}
8691
8692private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
8693 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8694 if (g_pars.mscpool.rsl_idx == 0) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008695 f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008696 } else if (g_pars.mscpool.rsl_idx == 1) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008697 f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008698 } else if (g_pars.mscpool.rsl_idx == 2) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008699 f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008700 }
8701}
8702
8703/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
8704private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
8705 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008706 f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
8707 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 +02008708 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)) );
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008709 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 +02008710}
8711testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
8712
8713 f_init(1, true);
8714 f_sleep(1.0);
8715 var MSC_ConnHdlr vc_conn;
8716 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008717
8718 f_ctrs_msc_init();
8719
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008720 vc_conn := f_start_handler(refers(f_tc_mscpool_L3Compl_on_1_msc), pars);
8721 vc_conn.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008722
8723 f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008724 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008725}
8726
8727/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
8728/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8729 * just as well using only RSL. */
8730testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
8731
8732 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8733 f_sleep(1.0);
8734
8735 /* Control which MSC gets chosen next by the round-robin, otherwise
8736 * would be randomly affected by which other tests ran before this. */
8737 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8738
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008739 f_ctrs_msc_init();
8740
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008741 var MSC_ConnHdlr vc_conn1;
8742 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8743 pars1.mscpool.rsl_idx := 0;
8744 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8745 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8746 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008747 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008748
8749 var MSC_ConnHdlr vc_conn2;
8750 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8751 pars2.mscpool.rsl_idx := 1;
8752 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8753 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8754 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008755 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008756
8757 /* Test round-robin wrap to the first MSC */
8758 var MSC_ConnHdlr vc_conn3;
8759 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8760 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008761 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008762 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8763 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008764 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008765 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008766}
8767
8768/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 0
8769 * (configured in osmo-bsc.cfg). */
8770/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8771 * just as well using only RSL. */
8772testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
8773
8774 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8775 f_sleep(1.0);
8776
8777 /* Control which MSC gets chosen next by the round-robin, otherwise
8778 * would be randomly affected by which other tests ran before this. */
8779 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8780
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008781 f_ctrs_msc_init();
8782
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008783 var MSC_ConnHdlr vc_conn1;
8784 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8785 pars1.mscpool.rsl_idx := 0;
8786 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8787 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8788 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008789 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008790
8791 var MSC_ConnHdlr vc_conn2;
8792 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8793 pars2.mscpool.rsl_idx := 1;
8794 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8795 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8796 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008797 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008798
8799 /* Test round-robin wrap to the first MSC */
8800 var MSC_ConnHdlr vc_conn3;
8801 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8802 pars3.mscpool.rsl_idx := 2;
8803 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8804 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8805 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008806 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008807 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008808}
8809
8810/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
8811 * (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
8812 * NULL-NRI setting is stronger than that. */
8813/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8814 * just as well using only RSL. */
8815testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
8816
8817 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8818 f_sleep(1.0);
8819
8820 /* Control which MSC gets chosen next by the round-robin, otherwise
8821 * would be randomly affected by which other tests ran before this. */
8822 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8823
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008824 f_ctrs_msc_init();
8825
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008826 var MSC_ConnHdlr vc_conn1;
8827 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8828 pars1.mscpool.rsl_idx := 0;
8829 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8830 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8831 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008832 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008833
8834 var MSC_ConnHdlr vc_conn2;
8835 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8836 pars2.mscpool.rsl_idx := 1;
8837 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8838 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8839 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008840 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008841
8842 /* Test round-robin wrap to the first MSC */
8843 var MSC_ConnHdlr vc_conn3;
8844 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8845 pars3.mscpool.rsl_idx := 2;
8846 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8847 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8848 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008849 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008850 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008851}
8852
8853/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
8854 * assigned to any MSC (configured in osmo-bsc.cfg). */
8855/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8856 * just as well using only RSL. */
8857testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test_CT {
8858
8859 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8860 f_sleep(1.0);
8861
8862 /* Control which MSC gets chosen next by the round-robin, otherwise
8863 * would be randomly affected by which other tests ran before this. */
8864 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8865
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008866 f_ctrs_msc_init();
8867
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008868 var MSC_ConnHdlr vc_conn1;
8869 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8870 pars1.mscpool.rsl_idx := 0;
8871 /* An NRI that is not assigned to any MSC */
8872 pars1.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(1023))));
8873 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8874 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008875 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008876
8877 var MSC_ConnHdlr vc_conn2;
8878 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8879 pars2.mscpool.rsl_idx := 1;
8880 /* An NRI that is not assigned to any MSC */
8881 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(768)), '00F110'O));
8882 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8883 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008884 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008885
8886 /* Test round-robin wrap to the first MSC */
8887 var MSC_ConnHdlr vc_conn3;
8888 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8889 pars3.mscpool.rsl_idx := 2;
8890 /* An NRI that is not assigned to any MSC */
8891 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, valueof(ts_MI_TMSI_NRI_LV(819))));
8892 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8893 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008894 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008895 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008896}
8897
8898/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
8899 * assigned to an MSC that is currently not connected (configured in osmo-bsc.cfg). */
8900/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8901 * just as well using only RSL. */
8902testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
8903
8904 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8905 f_sleep(1.0);
8906
8907 /* Control which MSC gets chosen next by the round-robin, otherwise
8908 * would be randomly affected by which other tests ran before this. */
8909 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8910
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008911 f_ctrs_msc_init();
8912
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008913 var MSC_ConnHdlr vc_conn1;
8914 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8915 pars1.mscpool.rsl_idx := 0;
8916 /* An NRI that is assigned to an unconnected MSC */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008917 pars1.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(512)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008918 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8919 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008920 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8921 f_ctrs_msc_add(0, "mscpool:subscr:new");
8922 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008923
8924 var MSC_ConnHdlr vc_conn2;
8925 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8926 pars2.mscpool.rsl_idx := 1;
8927 /* An NRI that is assigned to an unconnected MSC */
8928 pars2.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(767))));
8929 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8930 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008931 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8932 f_ctrs_msc_add(1, "mscpool:subscr:new");
8933 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008934
8935 /* Test round-robin wrap to the first MSC */
8936 var MSC_ConnHdlr vc_conn3;
8937 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8938 pars3.mscpool.rsl_idx := 2;
8939 /* An NRI that is assigned to an unconnected MSC */
8940 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(750)), '00F110'O));
8941 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8942 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008943 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8944 f_ctrs_msc_add(0, "mscpool:subscr:new");
8945 f_ctrs_msc_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008946 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008947}
8948
8949/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
8950 * osmo-bsc.cfg). */
8951/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8952 * just as well using only RSL. */
8953testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
8954
8955 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8956 f_sleep(1.0);
8957
8958 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
8959 * this is not using round-robin. */
8960 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8961
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008962 f_ctrs_msc_init();
8963
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008964 var MSC_ConnHdlr vc_conn1;
8965 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8966 pars1.mscpool.rsl_idx := 0;
8967 /* An NRI of the second MSC's range (256-511) */
8968 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(256))));
8969 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8970 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008971 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008972
8973 var MSC_ConnHdlr vc_conn2;
8974 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8975 pars2.mscpool.rsl_idx := 1;
8976 /* An NRI of the second MSC's range (256-511) */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008977 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(260)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008978 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8979 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008980 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008981
8982 var MSC_ConnHdlr vc_conn3;
8983 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8984 pars3.mscpool.rsl_idx := 2;
8985 /* An NRI of the second MSC's range (256-511) */
8986 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(511)), '00F110'O));
8987 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8988 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008989 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008990 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008991}
8992
8993/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
8994 * while a round-robin remains unaffected by that. */
8995/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8996 * just as well using only RSL. */
8997testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
8998
8999 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9000 f_sleep(1.0);
9001
9002 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
9003 * this is not using round-robin. */
9004 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
9005
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009006 f_ctrs_msc_init();
9007
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009008 var MSC_ConnHdlr vc_conn1;
9009 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 2);
9010 pars1.mscpool.rsl_idx := 0;
9011 /* An NRI of the third MSC's range (512-767) */
9012 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(512))));
9013 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9014 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009015 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009016
9017 var MSC_ConnHdlr vc_conn2;
9018 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9019 pars2.mscpool.rsl_idx := 1;
9020 /* An NRI of the third MSC's range (512-767) */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009021 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(678)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009022 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9023 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009024 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009025
9026 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
9027 var MSC_ConnHdlr vc_conn3;
9028 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
9029 pars3.mscpool.rsl_idx := 2;
9030 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000013'H)), '00F110'O));
9031 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9032 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009033 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009034 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009035}
9036
9037/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
9038/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
9039 * just as well using only RSL. */
9040testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
9041
9042 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9043 f_sleep(1.0);
9044
9045 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
9046 * instead, and hits msc 0. */
9047 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9048
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009049 f_ctrs_msc_init();
9050
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009051 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-bsc.cfg */
9052 var MSC_ConnHdlr vc_conn1;
9053 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9054 pars1.mscpool.rsl_idx := 0;
9055 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(260)), '99F999'O));
9056 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9057 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009058 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009059
9060 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
9061 var MSC_ConnHdlr vc_conn2;
9062 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9063 pars2.mscpool.rsl_idx := 1;
9064 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(555)), '00F110'O));
9065 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9066 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009067 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009068 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009069}
9070
9071/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
9072 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9073private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
9074 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9075 //cid_list := { cIl_allInBSS := ''O };
9076 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9077 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9078 var BSSAP_N_UNITDATA_req paging;
9079 var hexstring imsi := '001010000000123'H;
9080
9081 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9082
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009083 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009084 valueof(ts_BSSMAP_Paging(imsi, cid_list, omit, bssmap_chneed))));
9085 BSSAP.send(paging);
9086
9087 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9088 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9089 * channel number is picked here. */
9090 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9091 f_rslem_register(0, new_chan_nr);
9092 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(imsi)));
9093 f_rslem_unregister(0, new_chan_nr);
9094
9095 /* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
9096 * causes this Paging Response to go to the first MSC (bssap_idx := 0). */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009097 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV(imsi)) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009098 f_sleep(1.0);
9099}
9100testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
9101 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9102 f_sleep(1.0);
9103
9104 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9105 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9106 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
9107
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009108 f_ctrs_msc_init();
9109
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009110 var MSC_ConnHdlr vc_conn1;
9111 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9112 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009113 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9114 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009115 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
9116 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009117 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009118 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009119}
9120
9121/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
9122 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9123private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
9124 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9125 //cid_list := { cIl_allInBSS := ''O };
9126 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9127 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9128 var integer nri_v := 300; /* <-- second MSC's NRI */
Harald Weltebf397612021-01-14 20:39:46 +01009129 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009130 var BSSAP_N_UNITDATA_req paging;
9131
9132 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9133
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009134 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009135 valueof(ts_BSSMAP_Paging('001010000000011'H, cid_list, tmsi, bssmap_chneed))));
9136 BSSAP.send(paging);
9137
9138 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9139 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9140 * channel number is picked here. */
9141 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9142 f_rslem_register(0, new_chan_nr);
9143 RSL.receive(tr_RSL_PAGING_CMD(t_MI_TMSI(tmsi)));
9144 f_rslem_unregister(0, new_chan_nr);
9145
9146 /* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
9147 * third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
9148 * the first MSC (bssap_idx := 0). */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009149 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_TMSI_NRI_LV(nri_v)) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009150 f_sleep(1.0);
9151}
9152testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
9153 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9154 f_sleep(1.0);
9155
9156 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9157 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9158 f_vty_transceive(BSCVTY, "mscpool roundrobin next 2");
9159
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009160 f_ctrs_msc_init();
9161
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009162 var MSC_ConnHdlr vc_conn1;
9163 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9164 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009165 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9166 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009167 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
9168 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009169 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009170 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009171}
9172
9173/* For round-robin, skip an MSC that has 'no allow-attach' set. */
9174/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
9175 * just as well using only RSL. */
9176testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
9177
9178 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9179 f_sleep(1.0);
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009180 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9181 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009182
9183 /* Control which MSC gets chosen next by the round-robin, otherwise
9184 * would be randomly affected by which other tests ran before this. */
9185 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9186
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009187 f_ctrs_msc_init();
9188
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009189 var MSC_ConnHdlr vc_conn1;
9190 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9191 pars1.mscpool.rsl_idx := 0;
9192 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9193 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9194 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009195 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009196
9197 var MSC_ConnHdlr vc_conn2;
9198 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9199 pars2.mscpool.rsl_idx := 1;
9200 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9201 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9202 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009203 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009204
9205 var MSC_ConnHdlr vc_conn3;
9206 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
9207 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009208 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009209 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9210 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009211 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009212 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009213}
9214
9215/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
9216 * TMSI NRI. */
9217testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
9218
9219 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9220 f_sleep(1.0);
9221
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009222 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9223 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
9224
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009225 /* Control which MSC gets chosen next by the round-robin, otherwise
9226 * would be randomly affected by which other tests ran before this. */
9227 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9228
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009229 f_ctrs_msc_init();
9230
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009231 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
9232 var MSC_ConnHdlr vc_conn1;
9233 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
9234 pars1.mscpool.rsl_idx := 0;
9235 /* An NRI of the second MSC's range (256-511) */
9236 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_TMSI_NRI_LV(260))));
9237 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9238 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009239 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009240
9241 var MSC_ConnHdlr vc_conn2;
9242 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9243 pars2.mscpool.rsl_idx := 1;
9244 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9245 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9246 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009247 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009248
9249 var MSC_ConnHdlr vc_conn3;
9250 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 2);
9251 pars3.mscpool.rsl_idx := 2;
9252 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000003'H))));
9253 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9254 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009255 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009256 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009257}
9258
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009259/* When an MSC point-code gets an SCCP N-PCSTATE saying it is unreachable, immediately mark the MSC as unusable. */
9260testcase TC_mscpool_sccp_n_pcstate_detaches_msc() runs on test_CT {
9261
9262 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
9263 f_sleep(1.0);
9264
9265 /* Control which MSC gets chosen next by the round-robin, otherwise
9266 * would be randomly affected by which other tests ran before this. */
9267 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9268
9269 f_ctrs_msc_init();
9270
9271 var MSC_ConnHdlr vc_conn1;
9272 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9273 pars1.mscpool.rsl_idx := 0;
9274 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9275 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9276 vc_conn1.done;
9277 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9278
9279 var MSC_ConnHdlr vc_conn2;
9280 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
9281 pars2.mscpool.rsl_idx := 1;
9282 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9283 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9284 vc_conn2.done;
9285 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9286
9287 f_logp(BSCVTY, "disconnecting msc0");
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009288 f_bssap_idx_disconnect(0);
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009289
9290 /* Now round-robin would wrap to the first MSC, but since the first MSC is disconnected, it wraps around to msc
9291 * 2 again. */
9292 var MSC_ConnHdlr vc_conn3;
9293 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
9294 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009295 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009296 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9297 vc_conn3.done;
9298 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9299 f_shutdown_helper();
9300}
9301
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009302/* When an MSC point-code gets an SCCP N-PCSTATE saying it is now reachable, immediately trigger RESET and bring up the
9303 * MSC. */
9304testcase TC_mscpool_sccp_n_pcstate_attaches_msc() runs on test_CT {
9305
9306 f_init(nr_bts := 3, handler_mode := true, nr_msc := 1);
9307 f_sleep(1.0);
9308
9309 /* Control which MSC gets chosen next by the round-robin, otherwise
9310 * would be randomly affected by which other tests ran before this. */
9311 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9312
9313 f_ctrs_msc_init();
9314
9315 /* There is only one MSC, round robin stays on msc0 */
9316 var MSC_ConnHdlr vc_conn1;
9317 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9318 pars1.mscpool.rsl_idx := 0;
9319 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('0010100230000001'H)), '00F110'O));
9320 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9321 vc_conn1.done;
9322 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9323
9324 var MSC_ConnHdlr vc_conn2;
9325 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9326 pars2.mscpool.rsl_idx := 1;
9327 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010023000002'H))));
9328 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9329 vc_conn2.done;
9330 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9331
9332 f_logp(BSCVTY, "connecting msc1");
9333 f_vty_msc_allow_attach(BSCVTY, { true, true });
9334 f_bssap_idx_init(1);
9335 f_sleep(1.0);
9336
9337 /* This time round-robin wraps to the second MSC, because it is now online. */
9338 var MSC_ConnHdlr vc_conn4;
9339 var TestHdlrParams pars4 := f_gen_test_hdlr_pars(bssap_idx := 1);
9340 pars4.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009341 pars4.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010023000003'H)));
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009342 vc_conn4 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars4);
9343 vc_conn4.done;
9344 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9345
9346 f_shutdown_helper();
9347}
9348
Philipp Maier783681c2020-07-16 16:47:06 +02009349/* Allow/Deny emergency calls globally via VTY */
9350private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
9351 f_vty_enter_cfg_msc(BSCVTY, 0);
9352 if (allow) {
9353 f_vty_transceive(BSCVTY, "allow-emergency allow");
9354 } else {
9355 f_vty_transceive(BSCVTY, "allow-emergency deny");
9356 }
9357 f_vty_transceive(BSCVTY, "exit");
9358 f_vty_transceive(BSCVTY, "exit");
9359}
9360
9361/* Allow/Deny emergency calls per BTS via VTY */
9362private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
9363 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9364 if (allow) {
9365 f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
9366 } else {
9367 f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
9368 }
9369 f_vty_transceive(BSCVTY, "exit");
9370 f_vty_transceive(BSCVTY, "exit");
Neels Hofmeyrb6ed80c2020-10-12 22:52:39 +00009371 f_vty_transceive(BSCVTY, "exit");
Philipp Maier783681c2020-07-16 16:47:06 +02009372}
9373
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02009374/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
9375private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
9376 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9377 if (allow) {
9378 f_vty_transceive(BSCVTY, "srvcc fast-return allow");
9379 } else {
9380 f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
9381 }
9382 f_vty_transceive(BSCVTY, "exit");
9383 f_vty_transceive(BSCVTY, "exit");
9384 f_vty_transceive(BSCVTY, "exit");
9385}
9386
Pau Espin Pedrol14475352021-07-22 15:48:16 +02009387/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
9388private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
9389 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9390 if (allow) {
9391 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
9392 } else {
9393 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
9394 }
9395 f_vty_transceive(BSCVTY, "exit");
9396 f_vty_transceive(BSCVTY, "exit");
9397 f_vty_transceive(BSCVTY, "exit");
9398}
9399
Pau Espin Pedrol35609792023-01-03 16:56:59 +01009400/* Begin assignment procedure and send an EMERGENCY SETUP (RR) */
Philipp Maier783681c2020-07-16 16:47:06 +02009401private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
9402 var PDU_ML3_MS_NW emerg_setup;
9403 var octetstring emerg_setup_enc;
9404 var RSL_Message emerg_setup_data_ind;
9405
9406 f_establish_fully(omit, omit);
9407
9408 emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
9409 emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
9410 emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
9411
9412 RSL.send(emerg_setup_data_ind);
9413}
9414
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009415/* expect EmergencySetup on BSSAP after calling f_assignment_emerg_setup() */
9416private function f_assignment_emerg_setup_exp_bssap()
9417runs on MSC_ConnHdlr {
Philipp Maier783681c2020-07-16 16:47:06 +02009418 var PDU_BSSAP emerg_setup_data_ind_bssap;
9419 var PDU_ML3_MS_NW emerg_setup;
9420 timer T := 3.0;
9421
Philipp Maier783681c2020-07-16 16:47:06 +02009422 T.start;
9423 alt {
9424 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
9425 emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
9426 if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
9427 setverdict(fail, "no emergency setup");
9428 }
9429 }
9430 [] BSSAP.receive {
9431 setverdict(fail, "unexpected BSSAP message!");
9432 }
9433 [] T.timeout {
9434 setverdict(fail, "timout waiting for EMERGENCY SETUP!");
9435 }
9436 }
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009437}
9438
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009439private function f_assignment_emerg_setup_voice()
9440runs on MSC_ConnHdlr {
9441 /* Go on with voice call assignment */
9442 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
9443 var PDU_BSSAP ass_cmd := f_gen_ass_req();
9444
9445 /* Below speechOrDataIndicator and codecList are copied from an emergency call captured during tests.
9446 * They seem a bit weird (AMR-WB, and the order differ between speechId_DataIndicator and the codecList), but
9447 * seems a good idea to see how osmo-bsc reacts to this. */
9448 ass_cmd.pdu.bssmap.assignmentRequest.channelType := {
9449 elementIdentifier := '0B'O, /* overwritten */
9450 lengthIndicator := 0, /* overwritten */
9451 speechOrDataIndicator := '0001'B, /* speech */
9452 spare1_4 := '0000'B,
9453 channelRateAndType := ChRate_TCHForH_Fpref,
9454 speechId_DataIndicator := 'c2918105'O
9455 };
9456 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({
9457 ts_CodecHR, ts_CodecAMR_WB, ts_CodecEFR, ts_CodecFR}));
9458
9459 f_rslem_dchan_queue_enable();
9460
9461 var ExpectCriteria mgcpcrit := {
9462 connid := omit,
9463 endpoint := omit,
9464 transid := omit
9465 };
9466 f_create_mgcp_expect(mgcpcrit);
9467
9468 BSSAP.send(ass_cmd);
9469
9470 var AssignmentState st := valueof(ts_AssignmentStateInit);
Oliver Smithce2dd692023-04-17 10:25:50 +02009471 st.rtp_stream := true;
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009472 st.is_assignment := false;
9473 alt {
9474 [] as_modify(st);
9475 [] as_Media();
9476 [st.modify_done] BSSAP.receive(exp_compl) {
9477 setverdict(pass);
9478 }
9479 }
9480
9481 /* Voice call carries on ... */
9482 f_sleep(2.0);
9483}
9484
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009485/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
9486 * CALLS are permitted by the BSC config. */
9487private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
9488
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009489 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
9490 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
9491 * another lchan. */
9492 g_pars.ra := f_rnd_ra_emerg();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009493 f_assignment_emerg_setup();
9494 f_assignment_emerg_setup_exp_bssap();
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009495 f_assignment_emerg_setup_voice();
Philipp Maier783681c2020-07-16 16:47:06 +02009496
9497 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009498 f_perform_clear();
Philipp Maier783681c2020-07-16 16:47:06 +02009499}
9500
9501/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
9502 * forbidden by the BSC config. */
9503private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
9504 var PDU_BSSAP emerg_setup_data_ind_bssap;
9505 timer T := 3.0;
9506
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009507 f_assignment_emerg_setup();
Philipp Maier783681c2020-07-16 16:47:06 +02009508
9509 T.start;
9510 alt {
9511 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
9512 setverdict(pass);
9513 }
9514 [] RSL.receive {
9515 setverdict(fail, "unexpected RSL message!");
9516 }
9517 [] T.timeout {
9518 setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
9519 }
9520 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009521 BSSAP.receive(tr_BSSMAP_ClearRequest);
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01009522 f_perform_clear_no_rr_rel();
Philipp Maier783681c2020-07-16 16:47:06 +02009523}
9524
9525/* EMERGENCY CALL situation #1, allowed globally and by BTS */
9526testcase TC_assignment_emerg_setup_allow() runs on test_CT {
9527 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9528 var MSC_ConnHdlr vc_conn;
9529
9530 f_init(1, true);
9531 f_sleep(1.0);
9532
9533 f_vty_allow_emerg_msc(true);
9534 f_vty_allow_emerg_bts(true, 0);
9535 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9536 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009537 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009538}
9539
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +01009540/* Test MO emergency call using MobileIdentity=IMEI (possible for emergency
9541 * calls from phones without SIM card).
9542 * 3GPP TS 24.008 section 10.5.1.4, OS#5849 */
9543testcase TC_assignment_emerg_setup_allow_imei() runs on test_CT {
9544 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9545 var MSC_ConnHdlr vc_conn;
9546
9547 /* Remove IMSI set by f_gen_test_hdlr_pars(), then IMEI will be used to place the call */
9548 pars.imsi := omit;
9549
9550 f_init(1, true);
9551 f_sleep(1.0);
9552
9553 f_vty_allow_emerg_msc(true);
9554 f_vty_allow_emerg_bts(true, 0);
9555 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9556 vc_conn.done;
9557 f_shutdown_helper();
9558}
9559
Philipp Maier783681c2020-07-16 16:47:06 +02009560/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
9561testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
9562 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9563 var MSC_ConnHdlr vc_conn;
9564
9565 f_init(1, true);
9566 f_sleep(1.0);
9567
9568 f_vty_allow_emerg_msc(false);
9569 f_vty_allow_emerg_bts(true, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009570 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx): */
9571 pars.ra := f_rnd_ra_emerg();
Philipp Maier783681c2020-07-16 16:47:06 +02009572 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9573 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009574 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009575}
9576
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009577/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS.
9578 * The RACH req (and hence CHAN RQD) indicate other than emergency call.
9579 * Hence BSC only learns about it being an emergency call later during call setup.
9580 * If interested in the ra="emergency call" + deny bts policy case,
9581 * see TC_chan_rqd_emerg_deny.
9582 */
Philipp Maier783681c2020-07-16 16:47:06 +02009583testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
9584 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9585 var MSC_ConnHdlr vc_conn;
9586
9587 /* Note: This simulates a spec violation by the MS, correct MS
9588 * implementations would not try to establish an emergency call because
9589 * the system information tells in advance that emergency calls are
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009590 * not allowed */
Philipp Maier783681c2020-07-16 16:47:06 +02009591
9592 f_init(1, true);
9593 f_sleep(1.0);
9594
9595 f_vty_allow_emerg_msc(true);
9596 f_vty_allow_emerg_bts(false, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009597 /* Note: Here we implicitly leave default g_pars.ra which is different than "emergency call" */
Philipp Maier783681c2020-07-16 16:47:06 +02009598 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9599 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009600 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009601}
9602
Philipp Maier82812002020-08-13 18:48:27 +02009603/* Test what happens when an emergency call arrives while all TCH channels are
9604 * busy, the BSC is expected to terminate one call in favor of the incoming
9605 * emergency call */
9606testcase TC_emerg_premption() runs on test_CT {
9607 var ASP_RSL_Unitdata rsl_ud;
9608 var integer i;
9609 var integer chreq_total, chreq_nochan;
9610 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009611 var octetstring l3_payload := gen_l3_valid_payload();
Philipp Maier82812002020-08-13 18:48:27 +02009612
9613 f_init(1);
9614 f_sleep(1.0);
9615
9616 f_vty_allow_emerg_msc(true);
9617 f_vty_allow_emerg_bts(true, 0);
9618
9619 /* Fill up all channels on the BTS */
9620 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
9621 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
9622 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 +02009623 f_chreq_act_ack('33'O, i);
Philipp Maier82812002020-08-13 18:48:27 +02009624 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009625 IPA_RSL[0][0].clear;
Philipp Maier82812002020-08-13 18:48:27 +02009626 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
9627 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
9628
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009629 /* Send EST IND for the first TCH, so we get to test the RR release cause */
9630 var RslChannelNr first_tch := valueof(t_RslChanNr_Bm(1));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009631 f_ipa_tx(ts_RSL_EST_IND(first_tch, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009632
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009633 /* Accept BSSAP conn, so we get to test the Clear Request cause */
9634 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009635 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009636 var integer sccp_conn_id := rx_c_ind.connectionId;
9637 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
9638
Philipp Maier82812002020-08-13 18:48:27 +02009639 /* Send Channel request for emegergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009640 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier82812002020-08-13 18:48:27 +02009641
9642 /* Expect the BSC to release one (the first) TCH/F on the BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009643 f_expect_chan_rel(first_tch, expect_rr_chan_rel := true, expect_rll_rel_req := false,
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009644 expect_rr_cause := GSM48_RR_CAUSE_PREMPTIVE_REL);
Philipp Maier82812002020-08-13 18:48:27 +02009645
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009646 /* Also expect a BSSMAP Clear Request with PREEMPTION */
9647 var BSSAP_N_DATA_ind rx_clear_req;
9648 const myBSSMAP_Cause preemption := GSM0808_CAUSE_PREEMPTION;
9649 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_clear_req;
9650 log("XXX ", rx_clear_req);
9651 if (rx_clear_req.userData.pdu.bssmap.clearRequest.cause.causeValue != int2bit(enum2int(preemption), 7)) {
9652 setverdict(fail, "BSSMAP Clear Request: expected cause PREEMPTION");
9653 }
9654
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009655 /* Expect the BSC to send activate/assign the channel for the emergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009656 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009657 if (first_tch != rx_rsl.ies[0].body.chan_nr) {
9658 setverdict(fail, "different TCH lchan activated than expected");
9659 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009660 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(first_tch, 33));
9661 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Philipp Maier104f4c02020-09-11 18:12:18 +02009662
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009663 /* complete the BSSMAP Clear to satisfy the conn leak check */
9664 BSSAP.send(ts_BSSAP_DATA_req(sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(preemption))));
9665 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearComplete)) {
9666 BSSAP.send(ts_BSSAP_DISC_req(sccp_conn_id, 0));
9667 }
9668
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009669 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009670}
9671
9672/* Hopping parameters per a timeslot */
Vadim Yanitskiybc6654a2020-09-13 01:27:40 +07009673private type record length(0..64) of GsmArfcn ArfcnList;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009674private type record FHParamsTs {
9675 boolean enabled,
9676 uint6_t hsn,
9677 uint6_t maio,
9678 ArfcnList ma
9679};
9680
9681/* Hopping parameters per a transceiver */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009682private type record FHParamsTrx {
Philipp Maier798d8952021-10-19 14:43:19 +02009683 GsmBandArfcn arfcn,
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009684 FHParamsTs ts[8]
9685};
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009686
9687/* Randomly generate the hopping parameters for the given timeslot numbers */
9688private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
9689runs on test_CT return FHParamsTrx {
9690 var FHParamsTrx fhp;
9691
Philipp Maier798d8952021-10-19 14:43:19 +02009692 /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
9693 * fall in the GSM900 band. */
9694 fhp.arfcn.arfcn := f_rnd_int(3);
9695 fhp.arfcn.pcs := false;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009696
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009697 for (var integer tn := 0; tn < 8; tn := tn + 1) {
9698 if (not match(tn, tr_tn)) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009699 fhp.ts[tn].enabled := false;
9700 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009701 continue;
9702 }
9703
9704 /* Random HSN / MAIO values: 0..63 */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009705 fhp.ts[tn].hsn := f_rnd_int(64);
9706 fhp.ts[tn].maio := f_rnd_int(64);
9707 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009708
9709 /* Random Mobile Allocation (hopping channels) */
9710 var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
9711 var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
9712 for (var integer i := 1; i <= ma_len; i := i + 1) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009713 fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009714 }
9715
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009716 fhp.ts[tn].enabled := true;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009717 }
9718
9719 log("f_TC_fh_params_gen(): ", fhp);
9720 return fhp;
9721}
9722
9723/* Make sure that the given Channel Description IE matches the hopping configuration */
9724private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
9725{
9726 var template (present) ChannelDescription tr_cd;
9727 var template (present) MaioHsn tr_maio_hsn;
9728 var uint3_t tn := cd.chan_nr.tn;
9729
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009730 if (fhp.ts[tn].enabled) {
9731 tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009732 tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
9733 } else {
Philipp Maier798d8952021-10-19 14:43:19 +02009734 tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009735 }
9736
9737 if (not match(cd, tr_cd)) {
9738 setverdict(fail, "Channel Description IE does not match: ",
9739 cd, " vs expected ", tr_cd);
9740 }
9741}
9742
9743/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
9744private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
9745 in MobileAllocationLV ma)
9746{
9747 var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
9748
9749 if (not match(ma, tr_ma)) {
9750 setverdict(fail, "Mobile Allocation IE does not match (tn := ",
9751 tn, "): ", ma, " vs expected: ", tr_ma);
9752 } else {
9753 setverdict(pass);
9754 }
9755}
9756
9757private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
9758 in MobileAllocationLV ma)
9759return template MobileAllocationLV {
9760 /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009761 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009762 return { len := 0, ma := ''B };
9763 }
9764
9765 var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
9766 var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
9767 var bitstring ma_mask := ''B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009768
9769 /* Compose the full bit-mask (all channels, up to 1024 entries) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009770 for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
9771 for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
9772 if (full_mask[fhp.ts[i].ma[j]] == '1'B)
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009773 { continue; }
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009774 full_mask[fhp.ts[i].ma[j]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009775 }
9776 }
9777
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009778 /* Take ARFCN of the TRX itself into account */
Philipp Maier798d8952021-10-19 14:43:19 +02009779 full_mask[fhp.arfcn.arfcn] := '1'B;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009780
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009781 /* Compose a bit-mask for the given timeslot number */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009782 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9783 slot_mask[fhp.ts[tn].ma[i]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009784 }
9785
9786 /* Finally, compose the Mobile Allocation bit-mask */
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009787 for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009788 if (full_mask[i] != '1'B)
9789 { continue; }
9790
9791 /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
9792 if (slot_mask[i] == '1'B) {
9793 ma_mask := ma_mask & '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009794 } else {
9795 ma_mask := ma_mask & '0'B;
9796 }
9797 }
9798
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009799 /* ARFCN 0 (if present) goes to the last position of the bit-mask */
9800 if (full_mask[0] == '1'B) {
9801 /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
9802 if (slot_mask[0] == '1'B) {
9803 ma_mask := ma_mask & '1'B;
9804 } else {
9805 ma_mask := ma_mask & '0'B;
9806 }
9807 }
9808
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009809 /* Ensure that ma_mask is octet-aligned */
Vadim Yanitskiy2aa02522020-09-06 14:05:23 +07009810 var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009811 ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
9812
9813 return { len := ma_mask_len, ma := ma_mask };
9814}
9815
Philipp Maier798d8952021-10-19 14:43:19 +02009816/* Configure the appropriate band for a given arfcn, exc */
9817private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
9818{
9819 var charstring band;
9820 var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
9821
9822 select (arfcn_) {
9823 case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
9824 case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
9825 case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
9826 case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
9827 case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
9828 case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
9829 case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
9830 case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
9831 case else { return; }
9832 }
9833
9834 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9835 f_vty_transceive(BSCVTY, "band " & band);
9836 f_vty_transceive(BSCVTY, "end");
9837}
9838
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009839/* Configure the hopping parameters in accordance with the given record */
9840private function f_TC_fh_params_set(in FHParamsTrx fhp,
9841 uint8_t bts_nr := 0,
9842 uint8_t trx_nr := 0)
9843runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009844
9845 f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
9846
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009847 /* Enter the configuration node for the given BTS/TRX numbers */
9848 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9849
Philipp Maier798d8952021-10-19 14:43:19 +02009850 f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009851
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009852 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009853 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9854
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009855 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009856 f_vty_transceive(BSCVTY, "hopping enabled 0");
9857 f_vty_transceive(BSCVTY, "exit"); /* go back */
9858 continue;
9859 }
9860
9861 /* Configure HSN / MAIO values */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009862 f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
9863 f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009864
9865 /* Configure the Mobile Allocation (hopping channels) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009866 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9867 f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009868 }
9869
9870 f_vty_transceive(BSCVTY, "hopping enabled 1");
9871 f_vty_transceive(BSCVTY, "exit"); /* go back */
9872 }
9873
9874 f_vty_transceive(BSCVTY, "end");
9875}
9876
9877/* Disable frequency hopping on all timeslots */
9878private function f_TC_fh_params_unset(in FHParamsTrx fhp,
9879 uint8_t bts_nr := 0,
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009880 uint8_t trx_nr := 0,
Philipp Maier798d8952021-10-19 14:43:19 +02009881 GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009882runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009883
9884 f_TC_set_band_by_arfcn(bts_nr, arfcn);
9885
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009886 /* Enter the configuration node for the given BTS/TRX numbers */
9887 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9888
Philipp Maier798d8952021-10-19 14:43:19 +02009889 f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009890
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009891 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009892 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9893
9894 /* Delete all ARFCNs from the Mobile Allocation (if any) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009895 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9896 f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009897 }
9898
9899 f_vty_transceive(BSCVTY, "hopping enabled 0");
9900 f_vty_transceive(BSCVTY, "exit"); /* go back */
9901 }
9902
9903 f_vty_transceive(BSCVTY, "end");
9904 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9905}
9906
9907/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
9908 * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
9909testcase TC_fh_params_chan_activ() runs on test_CT {
9910 var FHParamsTrx fhp := f_TC_fh_params_gen();
9911 var RSL_Message rsl_msg;
9912 var RSL_IE_Body ie;
9913
9914 f_init_vty();
9915
9916 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9917 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9918
9919 f_init(1);
9920
9921 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9922 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009923 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9924 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009925
9926 /* Make sure that Channel Identification IE is present */
9927 if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
9928 setverdict(fail, "RSL Channel Identification IE is absent");
9929 continue;
9930 }
9931
9932 /* Make sure that hopping parameters (HSN/MAIO) match */
9933 f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
9934
9935 /* "Mobile Allocation shall be included but empty" - let's check this */
9936 if (ie.chan_ident.ma.v.len != 0) {
9937 setverdict(fail, "Mobile Allocation IE is not empty: ",
9938 ie.chan_ident.ma, ", despite it shall be");
9939 continue;
9940 }
9941 }
9942
9943 /* Disable frequency hopping */
9944 f_TC_fh_params_unset(fhp);
9945
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009946 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009947}
9948
9949/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
9950testcase TC_fh_params_imm_ass() runs on test_CT {
9951 var FHParamsTrx fhp := f_TC_fh_params_gen();
9952 var RSL_Message rsl_msg;
9953 var RSL_IE_Body ie;
9954
9955 f_init_vty();
9956
9957 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9958 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9959
9960 f_init(1);
9961
9962 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9963 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009964 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9965 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009966
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009967 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9968 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009969
9970 /* Make sure that Full Immediate Assign Info IE is present */
9971 if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
9972 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
9973 continue;
9974 }
9975
9976 /* Decode the actual Immediate Assignment message */
9977 var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
9978 if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
9979 setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
9980 continue;
9981 }
9982
9983 /* Make sure that hopping parameters (HSN/MAIO) match */
9984 f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
9985
9986 /* Make sure that the Mobile Allocation IE matches */
9987 f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
9988 rr_msg.payload.imm_ass.mobile_allocation);
9989 }
9990
9991 /* Disable frequency hopping */
9992 f_TC_fh_params_unset(fhp);
Philipp Maier82812002020-08-13 18:48:27 +02009993
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009994 f_shutdown_helper();
Philipp Maier82812002020-08-13 18:48:27 +02009995}
9996
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009997/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
9998testcase TC_fh_params_assignment_cmd() runs on test_CT {
9999 var FHParamsTrx fhp := f_TC_fh_params_gen();
10000 var RSL_Message rsl_msg;
10001 var RSL_IE_Body ie;
10002
10003 f_init_vty();
10004
10005 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
10006 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10007
10008 f_init(1);
10009
10010 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020010011 vc_MGCP[0].stop;
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010012
10013 var template PDU_BSSAP ass_cmd := f_gen_ass_req();
10014 ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
10015
10016 /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
10017 * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
10018 for (var integer i := 0; i < 3; i := i + 1) {
10019 /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010010020 var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010021
10022 /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
10023 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010024 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010025
10026 /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010027 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
10028 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010029
10030 /* Make sure that L3 Information IE is present */
10031 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
10032 setverdict(fail, "RSL L3 Information IE is absent");
10033 continue;
10034 }
10035
10036 /* Decode the L3 message and make sure it is (RR) Assignment Command */
10037 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
10038 if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
10039 setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
10040 continue;
10041 }
10042
10043 /* Make sure that hopping parameters (HSN/MAIO) match */
10044 var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
10045 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10046
10047 /* Make sure that Cell Channel Description IE is present if FH is enabled */
10048 if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
Vadim Yanitskiy38d069d2020-09-02 17:18:57 +070010049 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010050 continue;
10051 }
10052
10053 /* Make sure that the Mobile Allocation IE matches (if present) */
10054 var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
10055 if (chan_desc.h and ma_present) {
10056 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10057 l3_msg.payload.ass_cmd.mobile_allocation.v);
10058 } else if (chan_desc.h and not ma_present) {
10059 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10060 continue;
10061 } else if (not chan_desc.h and ma_present) {
10062 setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
10063 continue;
10064 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010065
10066 f_perform_clear_test_ct(dt);
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010067 }
10068
10069 /* Give the IUT some time to release all channels */
10070 f_sleep(3.0);
10071
10072 /* Disable frequency hopping */
10073 f_TC_fh_params_unset(fhp);
10074
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010075 f_shutdown_helper();
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010076}
10077
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010078/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
10079private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
10080runs on test_CT {
10081 var RSL_Message rsl_msg;
10082 var RSL_IE_Body ie;
10083 var DchanTuple dt;
10084
10085 /* Establish a dedicated channel, so we can trigger handover */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010010086 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyc18ff472021-11-18 20:15:37 +030010087 f_sleep(0.5);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010088
10089 /* Trigger handover from BTS0 to BTS1 */
10090 f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
10091 f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
10092
10093 /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010094 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx := {1, 0});
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010095
10096 /* ACKnowledge channel activation and expect (RR) Handover Command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010097 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33), idx := {1, 0});
10098 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010099
10100 /* Make sure that L3 Information IE is present */
10101 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
10102 setverdict(fail, "RSL L3 Information IE is absent");
10103 return;
10104 }
10105
10106 /* Decode the L3 message and make sure it is (RR) Handover Command */
10107 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
10108 if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
10109 setverdict(fail, "Failed to match Handover Command: ", l3_msg);
10110 return;
10111 }
10112
10113 /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
10114 var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
10115 if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
10116 setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
10117 return;
10118 }
10119
10120 /* Make sure that hopping parameters (HSN/MAIO) match */
10121 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10122
10123 /* Make sure that Cell Channel Description IE is present */
10124 if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
10125 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
10126 return;
10127 }
10128
10129 /* Make sure that the Mobile Allocation (after time) IE is present and matches */
10130 var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
10131 if (ma_present) {
10132 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10133 l3_msg.payload.ho_cmd.mobile_allocation.v);
10134 } else {
10135 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10136 return;
10137 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010138
10139 f_perform_clear_test_ct(dt);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010140}
10141testcase TC_fh_params_handover_cmd() runs on test_CT {
10142 var FHParamsTrx fhp := f_TC_fh_params_gen();
10143
10144 f_init_vty();
10145
10146 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
10147 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
10148
10149 f_vty_transceive(BSCVTY, "timeslot 0");
10150 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10151 f_vty_transceive(BSCVTY, "exit"); /* go back */
10152
10153 f_vty_transceive(BSCVTY, "timeslot 1");
10154 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
10155 f_vty_transceive(BSCVTY, "end"); /* we're done */
10156
10157 f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
10158 f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
10159
10160 f_init(2);
10161
10162 f_TC_fh_params_handover_cmd(fhp);
10163
10164 /* Disable frequency hopping on BTS1 */
10165 f_TC_fh_params_unset(fhp, 1);
10166
10167 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
10168 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
10169
10170 f_vty_transceive(BSCVTY, "timeslot 0");
10171 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
10172 f_vty_transceive(BSCVTY, "exit"); /* go back */
10173
10174 f_vty_transceive(BSCVTY, "timeslot 1");
10175 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10176 f_vty_transceive(BSCVTY, "end"); /* we're done */
10177
10178 f_shutdown_helper();
10179}
10180
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010181/* Verify the hopping parameters in System Information Type 4 */
10182testcase TC_fh_params_si4_cbch() runs on test_CT {
10183 var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
10184 var ASP_RSL_Unitdata rx_rsl_ud;
10185 timer T := 5.0;
10186
10187 f_init_vty();
10188
10189 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
10190 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10191
10192 f_vty_transceive(BSCVTY, "timeslot 0");
10193 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10194 f_vty_transceive(BSCVTY, "exit"); /* go back */
10195
10196 f_vty_transceive(BSCVTY, "timeslot 1");
10197 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
10198 f_vty_transceive(BSCVTY, "end"); /* we're done */
10199
10200 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
10201 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10202
10203 f_init(1);
10204
10205 T.start;
10206 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010207 [] 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 +070010208 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
10209 var SystemInformation si := dec_SystemInformation(ie.other.payload);
10210
10211 /* Make sure that what we decoded is System Information Type 4 */
10212 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
10213 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
10214 repeat;
10215 }
10216
10217 /* Make sure that CBCH Channel Description IE is present */
10218 if (not ispresent(si.payload.si4.cbch_chan_desc)) {
10219 setverdict(fail, "CBCH Channel Description IE is absent");
10220 break;
10221 }
10222
10223 /* Finally, check the hopping parameters (HSN, MAIO) */
10224 var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
10225 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10226
10227 /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
10228 * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
10229 if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
10230 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10231 break;
10232 } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
10233 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10234 si.payload.si4.cbch_mobile_alloc.v);
10235 }
10236 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010237 [] IPA_RSL[0][0].receive { repeat; }
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010238 [] T.timeout {
10239 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
10240 }
10241 }
10242
10243 /* Disable frequency hopping */
10244 f_TC_fh_params_unset(fhp);
10245
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010246 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010247 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10248
10249 f_vty_transceive(BSCVTY, "timeslot 0");
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010250 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010251 f_vty_transceive(BSCVTY, "exit"); /* go back */
10252
10253 f_vty_transceive(BSCVTY, "timeslot 1");
10254 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10255 f_vty_transceive(BSCVTY, "end"); /* we're done */
10256
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010257 f_shutdown_helper();
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010258}
10259
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010260template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
10261 := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
10262
10263private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
10264 template (present) BSSLAP_PDU expect_bsslap)
10265{
10266 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
10267 if (not match(bsslap, expect_bsslap)) {
10268 log("EXPECTING BSSLAP: ", expect_bsslap);
10269 log("GOT BSSLAP: ", bsslap);
10270 setverdict(fail, "BSSLAP is not as expected");
10271 mtc.stop;
10272 }
10273 setverdict(pass);
10274}
10275
10276/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
10277const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
10278
10279private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
10280 var PDU_BSSAP_LE rx_bsslap;
10281 BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
10282 f_match_bsslap(rx_bsslap, expect_rx_bsslap);
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. Either with or without the SMLC doing a BSSLAP TA Request. */
10287private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
10288 f_sleep(1.0);
10289
10290 f_establish_fully(omit, omit);
10291 f_bssap_le_register_imsi(g_pars.imsi, omit);
10292
10293 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10294 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10295
10296 var PDU_BSSAP_LE plr;
10297 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10298
10299 if (not do_ta_request) {
10300 /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
10301 var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
10302 if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
10303 log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
10304 log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
10305 setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
10306 mtc.stop;
10307 }
10308 var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
10309 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
10310 if (not match(bsslap, expect_ta_layer3)) {
10311 log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
10312 log("GOT BSSLAP: ", bsslap);
10313 setverdict(fail, "BSSLAP is not as expected");
10314 mtc.stop;
10315 }
10316 /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
10317 * has no need to request the TA from the BSC and directly responds. */
10318 } else {
10319 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10320 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10321 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10322 }
10323
10324 /* SMLC got the TA from the BSC, now responds with geo information data. */
10325 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10326 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10327 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10328
10329 /* The LCS was using an active A-interface conn. It should still remain active after this. */
10330 f_mo_l3_transceive();
10331
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010332 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010333
10334 f_sleep(2.0);
10335 setverdict(pass);
10336}
10337
10338/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10339 * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
10340private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
10341 f_lcs_loc_req_for_active_ms(false);
10342}
10343testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
10344 var MSC_ConnHdlr vc_conn;
10345 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10346
10347 f_init(1, true);
10348 f_sleep(1.0);
10349 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
10350 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010351 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010352}
10353
10354/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10355 * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
10356private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
10357 f_lcs_loc_req_for_active_ms(true);
10358}
10359testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
10360 var MSC_ConnHdlr vc_conn;
10361 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10362
10363 f_init(1, true);
10364 f_sleep(1.0);
10365 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
10366 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010367 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010368}
10369
10370/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
10371 * conn without an active lchan. */
10372private function f_clear_A_conn() runs on MSC_ConnHdlr
10373{
10374 var BssmapCause cause := 0;
10375 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10376 BSSAP.receive(tr_BSSMAP_ClearComplete);
10377 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10378
10379 timer no_more_bssap := 5.0;
10380 no_more_bssap.start;
10381 alt {
10382 [] no_more_bssap.timeout { break; }
10383 [] BSSAP.receive(tr_BSSAP_BSSMAP) {
10384 setverdict(fail, "Expected no more BSSAP after Clear Complete");
10385 mtc.stop;
10386 }
10387 }
10388 setverdict(pass);
10389}
10390
10391/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
10392 * for LCS, for cases where there is only an A conn without an active lchan. */
10393private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
10394{
10395 f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
10396
10397 /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
10398 * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
10399 * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
10400 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10401 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10402 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10403
10404 /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
10405 f_clear_A_conn();
10406 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10407 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10408}
10409
10410/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10411 * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
10412 */
10413private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
10414 f_sleep(1.0);
10415
10416 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10417 f_bssap_le_register_imsi(g_pars.imsi, omit);
10418
10419 /* Register to receive the Paging Command */
10420 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10421 g_chan_nr := new_chan_nr;
10422 f_rslem_register(0, g_chan_nr);
10423
10424 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10425 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10426 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10427 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10428
10429 var PDU_BSSAP_LE plr;
10430 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10431
10432 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10433 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10434
10435 /* OsmoBSC needs to Page */
10436 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
10437 f_logp(BSCVTY, "got Paging Command");
10438
10439 /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
10440 * the MSC, and releases the lchan directly. */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +020010441 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 +020010442 f_expect_lchan_rel(RSL, RSL_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010443
10444 /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
10445
10446 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10447
10448 /* SMLC got the TA from the BSC, now responds with geo information data. */
10449 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10450 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10451
10452 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10453
10454 /* The lchan is gone, the A-interface conn was created for the LCS only.
10455 * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
10456 f_verify_active_A_conn_and_clear();
10457
10458 f_sleep(2.0);
10459 setverdict(pass);
10460}
10461testcase TC_lcs_loc_req_for_idle_ms() runs on test_CT {
10462 var MSC_ConnHdlr vc_conn;
10463 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10464
10465 f_init(1, true);
10466 f_sleep(1.0);
10467
10468 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10469 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10470
10471 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
10472 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010473 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010474}
10475
10476/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
10477 */
10478private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
10479 f_sleep(1.0);
10480
10481 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10482 f_bssap_le_register_imsi(g_pars.imsi, omit);
10483
10484 /* provoke an abort by omitting both IMSI and IMEI */
10485 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10486 valueof(ts_BSSMAP_Perform_Location_Request(omit,
10487 ts_CellId_CGI('262'H, '42'H, 23, 42)))));
10488 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10489
10490 /* BSC tells MSC about failure */
10491 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10492 locationEstimate := omit, positioningData := omit,
10493 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
10494
10495 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10496 f_verify_active_A_conn_and_clear();
10497
10498 f_sleep(2.0);
10499 setverdict(pass);
10500}
10501testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
10502 var MSC_ConnHdlr vc_conn;
10503 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10504
10505 f_init(1, true);
10506 f_sleep(1.0);
10507
10508 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10509 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10510
10511 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
10512 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010513 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010514}
10515
10516/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10517 * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
10518private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
10519 f_sleep(1.0);
10520
10521 f_establish_fully(omit, omit);
10522 f_bssap_le_register_imsi(g_pars.imsi, omit);
10523
10524 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10525 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10526
10527 var PDU_BSSAP_LE plr;
10528 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10529
10530 if (do_ta) {
10531 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10532 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10533 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10534 }
10535
10536 /* SMLC fails to respond, BSC runs into timeout */
10537 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
10538 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10539
10540 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10541 locationEstimate := omit, positioningData := omit,
10542 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
10543
10544 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10545 f_verify_active_A_conn_and_clear();
10546
10547 f_sleep(2.0);
10548 setverdict(pass);
10549}
10550
10551/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10552 * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
10553private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
10554 f_lcs_loc_req_for_active_ms_le_timeout(false);
10555}
10556
10557testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
10558 var MSC_ConnHdlr vc_conn;
10559 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10560
10561 f_init(1, true);
10562 f_sleep(1.0);
10563 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
10564 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010565 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010566}
10567
10568/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10569 * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
10570private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
10571 f_lcs_loc_req_for_active_ms_le_timeout(true);
10572}
10573
10574testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
10575 var MSC_ConnHdlr vc_conn;
10576 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10577
10578 f_init(1, true);
10579 f_sleep(1.0);
10580 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
10581 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010582 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010583}
10584
10585/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
10586private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
10587 f_sleep(1.0);
10588
10589 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10590 f_bssap_le_register_imsi(g_pars.imsi, omit);
10591
10592 /* Register to receive the Paging Command */
10593 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10594 g_chan_nr := new_chan_nr;
10595 f_rslem_register(0, g_chan_nr);
10596
10597 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10598 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10599 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10600 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10601
10602 var PDU_BSSAP_LE plr;
10603 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10604
10605 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10606 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10607
10608 /* OsmoBSC needs to Page */
10609 var PDU_BSSAP_LE rx_bsslap;
10610 alt {
10611 [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
10612 f_logp(BSCVTY, "got Paging Command");
10613 repeat;
10614 }
10615 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10616 /* MS does not respond to Paging, TA Req runs into timeout. */
10617 f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
10618 }
10619 }
10620
10621 /* SMLC responds with failure */
10622 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10623 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10624
10625 /* BSC tells MSC about failure */
10626 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10627 locationEstimate := omit, positioningData := omit,
10628 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
10629
10630 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10631 f_verify_active_A_conn_and_clear();
10632
10633 f_sleep(2.0);
10634 setverdict(pass);
10635}
10636testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
10637 var MSC_ConnHdlr vc_conn;
10638 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10639
10640 f_init(1, true);
10641 f_sleep(1.0);
10642
10643 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10644 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10645
10646 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
10647 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010648 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010649}
10650
10651/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
10652 * over. */
10653private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10654 f_sleep(1.0);
10655
10656 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10657 f_bssap_le_register_imsi(g_pars.imsi, omit);
10658
10659 /* Register to receive the Paging Command */
10660 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10661 g_chan_nr := new_chan_nr;
10662 f_rslem_register(0, g_chan_nr);
10663
10664 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10665 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10666 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10667 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
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 /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
10673 * and establish Layer 3. It should use the existing A-interface conn. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010674 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 +020010675 do_clear := false, expect_bssmap_l3 := true);
10676
10677 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10678 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10679
10680 /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
10681 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10682
10683 /* SMLC got the TA from the BSC, now responds with geo information data. */
10684 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10685 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10686 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10687
10688 /* The lchan should still exist, it was from a CM Service Request. */
10689 f_mo_l3_transceive();
10690
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010691 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010692
10693 f_sleep(2.0);
10694 setverdict(pass);
10695}
10696testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
10697 var MSC_ConnHdlr vc_conn;
10698 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10699
10700 f_init(1, true);
10701 f_sleep(1.0);
10702
10703 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10704 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10705
10706 vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
10707 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010708 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010709}
10710
10711/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
10712 * the new lchan after handover. */
10713private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10714 f_sleep(1.0);
10715
10716 f_establish_fully(omit, omit);
10717 f_bssap_le_register_imsi(g_pars.imsi, omit);
10718
10719 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10720 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10721
10722 var PDU_BSSAP_LE plr;
10723 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10724
10725 /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
10726 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
10727
10728 var HandoverState hs := {
10729 rr_ho_cmpl_seen := false,
10730 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +020010731 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010732 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010733 };
10734 /* issue hand-over command on VTY */
10735 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
10736 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
10737 f_rslem_suspend(RSL1_PROC);
10738
10739 /* From the MGW perspective, a handover is is characterized by
10740 * performing one MDCX operation with the MGW. So we expect to see
10741 * one more MDCX during handover. */
10742 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
10743
10744 alt {
10745 [] as_handover(hs);
10746 }
10747
10748 var PDU_BSSAP_LE rx_bsslap;
10749
10750 interleave {
10751 /* Expect the BSC to inform the MSC about the handover */
10752 [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
10753
10754 /* Expect the BSC to inform the SMLC about the handover */
10755 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10756 f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
10757 }
10758 }
10759
10760 /* SMLC now responds with geo information data. */
10761 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10762 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10763 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10764
10765 /* lchan still active */
10766 f_mo_l3_transceive(RSL1);
10767
10768 /* MSC decides it is done now. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010769 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010770
10771 f_sleep(2.0);
10772 setverdict(pass);
10773}
10774testcase TC_ho_during_lcs_loc_req() runs on test_CT {
10775 var MSC_ConnHdlr vc_conn;
10776 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10777
10778 f_init(2, true);
10779 f_sleep(1.0);
10780 vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
10781 vc_conn.done;
Oliver Smith39f53072022-10-27 14:44:04 +020010782 f_shutdown_helper(ho := true);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010783}
10784
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010785private function f_tc_emerg_call_and_lcs_loc_req(charstring id) runs on MSC_ConnHdlr
10786{
10787 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
10788 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
10789 * another lchan. */
Pau Espin Pedrol1809bce2023-01-03 16:54:41 +010010790 g_pars.ra := f_rnd_ra_emerg();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010791 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010792 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010793
10794 /* Here would usually be a CC Call Proceeding from the MSC, but what does the BSC care about DTAP. */
10795
10796 /* Do a Location Request in-between the CC call setup */
10797 f_bssap_le_register_imsi(g_pars.imsi, omit);
10798 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10799 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10800 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10801 /* SMLC got the TA from the BSC, now responds with geo information data. */
10802 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10803 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10804 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10805
Pau Espin Pedrol14076d32023-01-03 17:07:59 +010010806 f_assignment_emerg_setup_voice();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010807
10808 setverdict(pass);
10809 f_perform_clear();
10810}
10811
10812testcase TC_emerg_call_and_lcs_loc_req() runs on test_CT {
10813 var MSC_ConnHdlr vc_conn;
10814 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10815
10816 f_init(1, true);
10817 f_sleep(1.0);
10818 f_vty_allow_emerg_msc(true);
10819 f_vty_allow_emerg_bts(true, 0);
10820 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req), pars);
10821 vc_conn.done;
10822 f_shutdown_helper();
10823}
10824
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010825private altstep no_bssmap_clear_req() runs on MSC_ConnHdlr {
10826 [] BSSAP.receive(tr_BSSMAP_ClearRequest) {
10827 setverdict(fail, "unexpected BSSMAP Clear Request");
10828 mtc.stop;
10829 }
10830}
10831
10832private type enumerated RslRel {
10833 RSLREL_REL_IND,
10834 RSLREL_CONN_FAIL
10835};
10836
10837private function f_emerg_call_and_lcs_loc_req_early_lchan_release(RslRel rsl_rel) runs on MSC_ConnHdlr
10838{
10839 g_pars.ra := f_rnd_ra_emerg();
10840 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010841 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010842
10843 /* Start a Location Request to locate the emergency */
10844 f_bssap_le_register_imsi(g_pars.imsi, omit);
10845 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10846 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10847 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10848
10849 /* 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
10850 * do a Clear Command when the Location Response arrives. */
10851 activate(no_bssmap_clear_req());
10852
10853 /* the lchan gets interrupted while the Location Request has no response */
10854 select (rsl_rel) {
10855 case (RSLREL_REL_IND) {
10856 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
10857 f_expect_lchan_rel(RSL, RSL_PROC);
10858 }
10859 case (RSLREL_CONN_FAIL) {
10860 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
10861 }
10862 case else {
10863 setverdict(fail, "Unknown RslRel type");
10864 mtc.stop;
10865 }
10866 }
10867
10868 /* Still expect the Location Response to find its way to the MSC. */
10869 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10870 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10871 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10872
10873 setverdict(pass);
10874
10875 select (rsl_rel) {
10876 case (RSLREL_REL_IND) {
10877 f_perform_clear_no_lchan();
10878 }
10879 case (RSLREL_CONN_FAIL) {
10880 f_perform_clear();
10881 }
10882 }
10883}
10884
10885private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind(charstring id) runs on MSC_ConnHdlr
10886{
10887 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_REL_IND);
10888}
10889
10890testcase TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() runs on test_CT {
10891 var MSC_ConnHdlr vc_conn;
10892 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10893
10894 f_init(1, true);
10895 f_sleep(1.0);
10896 f_vty_allow_emerg_msc(true);
10897 f_vty_allow_emerg_bts(true, 0);
10898 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind), pars);
10899 vc_conn.done;
10900 f_shutdown_helper();
10901}
10902
10903private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail(charstring id) runs on MSC_ConnHdlr
10904{
10905 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_CONN_FAIL);
10906}
10907
10908testcase TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() runs on test_CT {
10909 var MSC_ConnHdlr vc_conn;
10910 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10911
10912 f_init(1, true);
10913 f_sleep(1.0);
10914 f_vty_allow_emerg_msc(true);
10915 f_vty_allow_emerg_bts(true, 0);
10916 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail), pars);
10917 vc_conn.done;
10918 f_shutdown_helper();
10919}
10920
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010921/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
10922private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
10923 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10924
10925 /* Also disable attach for the single connected MSC */
10926 f_vty_msc_allow_attach(BSCVTY, { false });
10927
10928 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) ));
10929 f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
10930
10931 /* No MSC is found, expecting a proper release on RSL */
10932 interleave {
10933 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
10934 f_logp(BSCVTY, "Got RSL RR Release");
10935 }
10936 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10937 f_logp(BSCVTY, "Got RSL Deact SACCH");
10938 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010939 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010940 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
10941 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010942 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010943 }
10944 }
10945 setverdict(pass);
10946}
10947testcase TC_no_msc() runs on test_CT {
10948
10949 f_init(1, true);
10950 f_sleep(1.0);
10951 var MSC_ConnHdlr vc_conn;
10952 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10953
10954 f_ctrs_bsc_init(counternames_bsc_mscpool);
10955
10956 vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
10957 vc_conn.done;
10958
10959 f_ctrs_bsc_add("mscpool:subscr:no_msc");
10960 f_ctrs_bsc_verify();
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010961 f_shutdown_helper();
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010962}
10963
Harald Welte0ea2d5e2018-04-07 21:40:29 +020010964/* Dyn PDCH todo:
10965 * activate OSMO as TCH/F
10966 * activate OSMO as TCH/H
10967 * does the BSC-located PCU socket get the updated INFO?
10968 * what if no PCU is connected at the time?
10969 * is the info correct on delayed PCU (re)connect?
10970 */
Harald Welte94e0c342018-04-07 11:33:23 +020010971
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010972private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +020010973 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020010974 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010975
10976 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
10977 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10978 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
10979 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
10980 g_pars.ass_codec_list.codecElements[0];
10981 if (isvalue(g_pars.expect_mr_s0_s7)) {
10982 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
10983 g_pars.expect_mr_s0_s7;
10984 }
10985 }
10986 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
10987 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
10988 log("expecting ASS COMPL like this: ", exp_compl);
10989
10990 f_establish_fully(ass_cmd, exp_compl);
10991
Neels Hofmeyr8746b0d2021-06-01 17:25:39 +020010992 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 +000010993
10994 var RSL_Message rsl;
10995
10996 timer T := 5.0;
10997 T.start;
10998 alt {
10999 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
11000 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
11001 log("Rx L3 from net: ", l3);
11002 if (ischosen(l3.msgs.rrm.channelModeModify)) {
11003 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
11004 mtc.stop;
11005 }
11006 }
11007 [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
11008 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
11009 mtc.stop;
11010 }
11011 [] T.timeout {
11012 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
11013 setverdict(pass);
11014 }
11015 }
11016 T.stop;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011017
11018 f_perform_clear();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011019}
11020
11021/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
11022 * osmo-bsc. */
11023testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
11024 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11025 var MSC_ConnHdlr vc_conn;
11026
11027 f_init(1, true);
11028 f_sleep(1.0);
11029
11030 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11031 vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
11032 vc_conn.done;
11033 f_shutdown_helper();
11034}
11035
11036/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
11037 */
11038testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
11039 f_init_vty();
11040
11041 f_init(1, false);
11042 f_sleep(1.0);
11043
11044 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
11045
11046 var ASP_RSL_Unitdata rx_rsl_ud;
11047 timer T := 5.0;
11048
11049 T.start;
11050 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011051 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011052 if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
11053 T.stop;
11054 setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
11055 mtc.stop;
11056 }
11057 repeat;
11058 }
11059 [] T.timeout {
11060 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
11061 setverdict(pass);
11062 }
11063 }
11064}
11065
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011066private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
11067 /* First fully set up a speech lchan */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011068 f_assignment_codec(id, do_perform_clear := false);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011069
11070 /* Trigger re-assignment to another lchan */
11071 var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
11072
11073 /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
11074 * one MDCX on MGCP. */
11075 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
11076
11077 /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
11078 * as the old lchan used. */
11079 g_media.bts.ipa_crcx_seen := false;
11080 g_media.bts.ipa_mdcx_seen := false;
11081
11082 /* Send different BTS side RTP port number for the new lchan */
11083 g_media.bts.bts.port_nr := 4223;
11084
11085 f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
11086
11087 /* Trigger re-assignment. */
11088 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
11089
11090 timer T := 5.0;
11091 T.start;
11092 alt {
11093 [] as_assignment(assignment_st);
11094 [] as_Media();
11095 [] T.timeout {
11096 break;
11097 }
11098 }
11099
11100 if (not assignment_st.assignment_done) {
11101 setverdict(fail, "Assignment did not complete");
11102 mtc.stop;
11103 }
11104
11105 f_check_mgcp_expectations()
11106 setverdict(pass);
11107
11108 f_sleep(2.0);
11109 log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
11110
11111 /* Instruct BSC to clear channel */
11112 var BssmapCause cause := 0;
11113 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
11114 interleave {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011115 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
11116 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020011117 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011118 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020011119 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011120 }
11121 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
11122 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11123 }
11124 }
Neels Hofmeyr40a45d12021-09-23 22:57:12 +020011125 f_expect_dlcx_conns();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011126
11127 f_sleep(0.5);
11128}
11129
11130testcase TC_reassignment_fr() runs on test_CT {
11131 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11132 var MSC_ConnHdlr vc_conn;
11133
11134 f_init(1, true);
11135 f_sleep(1.0);
11136
Neels Hofmeyrac432fa2021-11-02 16:45:56 +010011137 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011138
11139 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11140 vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
11141 vc_conn.done;
11142
11143 /* from f_establish_fully() */
11144 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
11145 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
11146 /* from re-assignment */
11147 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
11148 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
11149 f_ctrs_bsc_and_bts_verify();
11150 f_shutdown_helper();
11151}
11152
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011153const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
11154const charstring REEST_CLEAR := "REEST_CLEAR";
11155const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
11156
11157/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
11158 * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
11159 * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
11160 * the MSC as the CM Re-Establishment is handled.
11161 *
11162 * MS bts0 bts1 bsc msc test-component
11163 * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
11164 * | | _1 wait a bit, to settle down
11165 * |<-x x--| | _1 "lose connection"
11166 * | | REEST_LOST_CONNECTION
11167 * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
11168 * | | REEST_CLEAR
11169 * | |<-0---| _1 Clear Command on first A-conn
11170 * | |--0-->| _1 Clear Complete
11171 * | |<----------------->| | _1 Release first channel
11172 * | | REEST_CLEAR_DONE
11173 * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
11174 * |<-----------------|<-------|<-1---| _2 Clear Command, Release
11175 *
11176 */
11177private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
11178 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
11179 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11180
11181 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11182 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11183
11184 f_establish_fully(ass_cmd, exp_compl);
11185
11186 /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
11187 * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
11188 * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
11189 f_sleep(2.0);
11190 COORD.send(REEST_LOST_CONNECTION);
11191
11192 alt {
11193 [] COORD.receive(REEST_CLEAR);
11194 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
11195 setverdict(fail, "Unexpected channel release");
11196 mtc.stop;
11197 }
11198 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
11199 setverdict(fail, "Unexpected channel release");
11200 mtc.stop;
11201 }
11202 }
11203 f_perform_clear()
Neels Hofmeyr969abd02021-09-23 22:24:08 +020011204 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011205 COORD.send(REEST_CLEAR_DONE);
11206}
11207
11208private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
11209 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
11210
11211 /* The MS lost the connection on the first channel, now establishes another one */
11212 COORD.receive(REEST_LOST_CONNECTION);
11213
11214 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
11215 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
11216 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
11217
11218 f_create_bssmap_exp(l3_enc);
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011219 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 +020011220 BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
11221
11222 /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
11223 COORD.send(REEST_CLEAR);
11224 COORD.receive(REEST_CLEAR_DONE);
11225
11226 f_sleep(2.0);
11227
11228 /* Answer the CM Re-Establishment with an Assignment Command. */
11229 var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
11230 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11231 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11232 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11233
11234 var AssignmentState st := valueof(ts_AssignmentStateInit);
Oliver Smithce2dd692023-04-17 10:25:50 +020011235 st.rtp_stream := true;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011236 st.is_assignment := true;
11237
11238 var ExpectCriteria mgcpcrit := {
11239 connid := omit,
11240 endpoint := omit,
11241 transid := omit
11242 };
11243 f_create_mgcp_expect(mgcpcrit);
11244
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011245 f_rslem_dchan_queue_enable(RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011246
11247 BSSAP.send(ass_cmd);
11248
11249 var PDU_BSSAP bssap;
11250
11251 alt {
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011252 [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
11253 [] as_Media_ipacc(RSL1, RSL2);
11254 [] as_Media_mgw();
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011255 [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
11256 break;
11257 }
11258 }
11259
11260 f_sleep(3.0);
11261
11262 f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011263 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011264}
11265
11266testcase TC_cm_reestablishment() runs on test_CT {
11267 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
11268 var MSC_ConnHdlr vc_conn1;
11269
11270 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
11271 var MSC_ConnHdlr vc_conn2;
11272 pars2.imsi := pars1.imsi;
11273 pars2.media_nr := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011274 pars2.expect_tsc := c_BtsParams[1].tsc;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011275
11276 f_init(2, true, guard_timeout := 40.0);
11277 f_sleep(1.0);
11278
11279 vc_conn1 := f_start_handler_create(pars1);
11280 vc_conn2 := f_start_handler_create(pars2);
11281 connect(vc_conn1:COORD, vc_conn2:COORD);
11282 f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
11283 f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
11284 vc_conn1.done;
11285 vc_conn2.done;
11286
11287 f_shutdown_helper();
11288}
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011289
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011290function f_exp_ipa_rx_nonfatal(template (present) RSL_Message t_rx,
11291 boolean ignore_other_rx := true,
11292 BtsTrxIdx idx := {0, 0},
11293 float Tval := 2.0)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011294runs on test_CT return template (omit) RSL_Message {
11295 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011296 timer T := Tval;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011297
11298 T.start;
11299 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011300 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011301 T.stop;
11302 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011303 [ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
11304 [not ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011305 log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
11306 T.stop;
11307 return omit;
11308 }
11309 [] T.timeout {
11310 return omit;
11311 }
11312 }
11313 return rx_rsl_ud.rsl;
11314}
11315
11316private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
11317 f_vty_enter_cfg_bts(pt, bts_nr);
11318 f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
11319 f_vty_transceive(pt, "exit");
11320 f_vty_transceive(pt, "exit");
11321 f_vty_transceive(pt, "exit");
11322}
11323
11324private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +030011325 template (present) RslChannelNr chan_nr := ?,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011326 template (present) uint12_t arfcn := ?,
11327 template (present) uint3_t tsc := ?)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011328{
11329 var RSL_IE_Body full_imm_ass_info;
11330 if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
11331 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
11332 mtc.stop;
11333 }
11334
11335 var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
11336 var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
11337 fn := fn,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011338 ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011339 page_mode := ?);
11340 if (not match(rr_imm_ass, expect_imm_ass)) {
11341 log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
11342 setverdict(fail, "Failed to match Immediate Assignment");
11343 mtc.stop;
11344 }
11345}
11346
11347testcase TC_imm_ass_post_chan_ack() runs on test_CT {
11348 var RSL_Message chan_act;
11349 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011350 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011351
11352 f_init(1, false);
11353 f_sleep(1.0);
11354
11355 /* (should be the default anyway, just to make things clear) */
11356 f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
11357
11358 /* RA containing reason=LU */
11359 var GsmFrameNumber fn := 2342;
11360 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011361 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011362
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011363 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011364
11365 /* First send the Chan Act ACK */
11366 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011367 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011368 var RSL_IE_Body chan_ident_ie;
11369 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11370 setverdict(fail, "RSL Channel Identification IE is absent");
11371 mtc.stop;
11372 }
11373
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011374 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011375
11376 /* Then expect the Immediate Assignment, after we ACKed the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011377 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011378
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011379 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11380 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011381
11382 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011383 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011384
11385 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011386 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011387 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011388 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11389
11390 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011391 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011392 f_shutdown_helper();
11393}
11394
11395testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
11396 var RSL_Message chan_act;
11397 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011398 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011399
11400 f_init(1, false);
11401 f_sleep(1.0);
11402
11403 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11404
11405 /* RA containing reason=LU */
11406 var GsmFrameNumber fn := 2342;
11407 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011408 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011409
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011410 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011411 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011412 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011413 var RSL_IE_Body chan_ident_ie;
11414 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11415 setverdict(fail, "RSL Channel Identification IE is absent");
11416 mtc.stop;
11417 }
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011418
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011419 /* (set bts 0 cfg back to default) */
11420 f_vty_set_imm_ass(BSCVTY);
11421
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011422 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011423 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011424 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11425 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011426
11427 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011428 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011429
11430 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011431 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011432
11433 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011434 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011435 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011436 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11437
11438 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011439 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011440 f_shutdown_helper();
11441}
11442
Neels Hofmeyr23158742021-09-07 19:08:07 +020011443testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
11444 var RSL_Message chan_act;
11445 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011446 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr23158742021-09-07 19:08:07 +020011447
11448 f_init(1, false);
11449 f_sleep(1.0);
11450
11451 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11452
11453 /* RA containing reason=LU */
11454 var GsmFrameNumber fn := 2342;
11455 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011456 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011457
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011458 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011459 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011460 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr23158742021-09-07 19:08:07 +020011461 var RSL_IE_Body chan_ident_ie;
11462 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11463 setverdict(fail, "RSL Channel Identification IE is absent");
11464 mtc.stop;
11465 }
11466
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011467 /* (set bts 0 cfg back to default) */
11468 f_vty_set_imm_ass(BSCVTY);
11469
Neels Hofmeyr23158742021-09-07 19:08:07 +020011470 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011471 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011472 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11473 chan_ident_ie.chan_ident.ch_desc.v.tsc);
11474
11475 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011476 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011477
11478 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011479 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011480
11481 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011482 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011483 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr23158742021-09-07 19:08:07 +020011484 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11485
11486 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011487 f_perform_clear_test_ct(dt);
Neels Hofmeyr23158742021-09-07 19:08:07 +020011488 f_shutdown_helper();
11489}
11490
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011491testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
11492 /* change Timeslot 6 before f_init() starts RSL */
11493 f_init_vty();
11494 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11495 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11496
11497 f_init(1, false);
11498 f_sleep(1.0);
11499
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011500 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011501 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11502 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011503 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11504 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011505
11506 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11507 f_ts_set_chcomb(0, 0, 6, "PDCH");
11508
11509 /* block all static timeslots so that the dyn TS will be used */
11510 f_disable_all_tch_f();
11511 f_disable_all_tch_h();
11512 f_disable_all_sdcch();
11513
11514 var RSL_Message chan_act;
11515 var RSL_Message imm_ass;
11516
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011517 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11518
11519 /* RA containing reason=LU */
11520 var GsmFrameNumber fn := 2342;
11521 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011522 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011523
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011524 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011525 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
11526 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011527
11528 /* Now activation as SDCCH8 */
11529 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011530 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011531
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011532 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011533 var RSL_IE_Body chan_ident_ie;
11534 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11535 setverdict(fail, "RSL Channel Identification IE is absent");
11536 mtc.stop;
11537 }
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011538
11539 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011540 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011541 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11542 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011543
11544 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011545 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011546
11547 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011548 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011549
11550 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011551 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011552 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011553 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11554
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011555 /* (set bts 0 cfg back to default) */
11556 f_vty_set_imm_ass(BSCVTY);
11557
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011558 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011559 f_perform_clear_test_ct(dt);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011560 f_shutdown_helper();
11561}
11562
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011563testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
11564 /* change Timeslot 6 before f_init() starts RSL */
11565 f_init_vty();
11566 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11567 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11568
11569 f_init(1, false);
11570 f_sleep(1.0);
11571
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011572 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011573 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11574 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011575 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11576 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011577
11578 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11579 f_ts_set_chcomb(0, 0, 6, "PDCH");
11580
11581 /* block all static timeslots so that the dyn TS will be used */
11582 f_disable_all_tch_f();
11583 f_disable_all_tch_h();
11584 f_disable_all_sdcch();
11585
11586 var RSL_Message chan_act;
11587 var RSL_Message imm_ass;
11588
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011589 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11590
11591 /* RA containing reason=LU */
11592 var GsmFrameNumber fn := 2342;
11593 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011594 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011595
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011596 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011597 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011598
11599 /* And already the Immediate Assignment even before the PDCH Deact ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011600 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011601
11602 /* continue the Osmo style PDCH Deact (usual chan rel) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011603 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011604
11605 /* Now activation as SDCCH8 */
11606 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011607 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011608
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011609 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011610 var RSL_IE_Body chan_ident_ie;
11611 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11612 setverdict(fail, "RSL Channel Identification IE is absent");
11613 mtc.stop;
11614 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011615 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011616
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011617 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11618 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011619
11620 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011621 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011622
11623 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011624 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011625 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011626 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11627
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011628 /* (set bts 0 cfg back to default) */
11629 f_vty_set_imm_ass(BSCVTY);
11630
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011631 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011632 f_perform_clear_test_ct(dt);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011633 f_shutdown_helper();
11634}
11635
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011636/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
11637testcase TC_ctrl_trx_rf_locked() runs on test_CT {
11638 var MSC_ConnHdlr vc_conn;
11639
11640 f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
11641 f_sleep(1.0);
11642
11643 /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
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: lock BTS 1 TRX 0");
11654 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11655 /* give it a moment to settle the FSM status */
11656 f_sleep(1.0);
11657
11658 /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
11659 * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
11660 * of "off"? But that's for a future patch if at all. */
11661 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11662 "0,0,operational,unlocked,on,rsl-up;" &
11663 "1,0,operational,locked,on,rsl-up;" &
11664 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011665 "2,1,operational,unlocked,on,rsl-down;" &
11666 "2,2,operational,unlocked,on,rsl-down;" &
11667 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011668 "3,0,inoperational,locked,on,rsl-down;");
11669
11670 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
11671 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11672 f_sleep(1.0);
11673 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11674 "0,0,operational,unlocked,on,rsl-up;" &
11675 "1,0,operational,locked,on,rsl-up;" &
11676 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011677 "2,1,operational,unlocked,on,rsl-down;" &
11678 "2,2,operational,unlocked,on,rsl-down;" &
11679 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011680 "3,0,inoperational,locked,on,rsl-down;");
11681
11682 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
11683 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
11684 f_sleep(1.0);
11685 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11686 "0,0,operational,unlocked,on,rsl-up;" &
11687 "1,0,operational,unlocked,on,rsl-up;" &
11688 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011689 "2,1,operational,unlocked,on,rsl-down;" &
11690 "2,2,operational,unlocked,on,rsl-down;" &
11691 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011692 "3,0,inoperational,locked,on,rsl-down;");
11693
11694 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
11695 f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
11696 f_sleep(1.0);
11697 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11698 "0,0,operational,unlocked,on,rsl-up;" &
11699 "1,0,operational,unlocked,on,rsl-up;" &
11700 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011701 "2,1,operational,unlocked,on,rsl-down;" &
11702 "2,2,operational,unlocked,on,rsl-down;" &
11703 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011704 "3,0,inoperational,locked,on,rsl-down;");
11705
11706 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
11707 f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
11708 f_sleep(1.0);
11709 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11710 "0,0,operational,unlocked,on,rsl-up;" &
11711 "1,0,operational,unlocked,on,rsl-up;" &
11712 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011713 "2,1,operational,unlocked,on,rsl-down;" &
11714 "2,2,operational,unlocked,on,rsl-down;" &
11715 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011716 "3,0,inoperational,locked,on,rsl-down;");
11717
11718 f_shutdown_helper();
11719}
11720
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011721const CounterNameVals counternames_cm_serv_rej := {
11722 { "cm_serv_rej", 0 },
11723 { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
11724 { "cm_serv_rej:illegal_ms", 0 },
11725 { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
11726 { "cm_serv_rej:imei_not_accepted", 0 },
11727 { "cm_serv_rej:illegal_me", 0 },
11728 { "cm_serv_rej:plmn_not_allowed", 0 },
11729 { "cm_serv_rej:loc_not_allowed", 0 },
11730 { "cm_serv_rej:roaming_not_allowed", 0 },
11731 { "cm_serv_rej:network_failure", 0 },
11732 { "cm_serv_rej:synch_failure", 0 },
11733 { "cm_serv_rej:congestion", 0 },
11734 { "cm_serv_rej:srv_opt_not_supported", 0 },
11735 { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
11736 { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
11737 { "cm_serv_rej:call_can_not_be_identified", 0 },
11738 { "cm_serv_rej:incorrect_message", 0 },
11739 { "cm_serv_rej:invalid_mandantory_inf", 0 },
11740 { "cm_serv_rej:msg_type_not_implemented", 0 },
11741 { "cm_serv_rej:msg_type_not_compatible", 0 },
11742 { "cm_serv_rej:inf_eleme_not_implemented", 0 },
11743 { "cm_serv_rej:condtional_ie_error", 0 },
11744 { "cm_serv_rej:msg_not_compatible", 0 },
11745 { "cm_serv_rej:protocol_error", 0 },
11746 { "cm_serv_rej:retry_in_new_cell", 0 }
11747};
11748
11749private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
11750{
11751 f_create_chan_and_exp();
Vadim Yanitskiya7fc5a62021-12-04 20:10:08 +030011752 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011753 BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011754 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_CM_SERV_REJ));
11755 f_perform_clear();
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011756 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011757}
11758testcase TC_cm_serv_rej() runs on test_CT {
11759 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11760 var MSC_ConnHdlr vc_conn;
11761
11762 f_init(1, true);
11763 f_sleep(1.0);
11764
11765 f_ctrs_bts_init(1, counternames_cm_serv_rej);
11766
11767 vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
11768 vc_conn.done;
11769
11770 f_ctrs_bts_add(0, "cm_serv_rej", 1);
11771 f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
11772 f_ctrs_bts_verify();
11773
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011774 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011775 f_shutdown_helper();
11776}
11777
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011778/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
11779 * Activ Ack (SYS#5627). */
11780private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
11781 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Vadim Yanitskiyf0310e32021-10-26 00:30:59 +030011782
11783 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11784 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011785
11786 var BSSMAP_FIELD_CodecType codecType;
11787 codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
11788
11789 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
11790
11791 /* First establish a signalling lchan */
11792 f_create_chan_and_exp();
11793 f_rslem_dchan_queue_enable();
11794
11795 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011796
11797 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
Oliver Smith735b47c2023-02-15 16:03:54 +010011798 activate(as_Media_mgw());
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011799
11800 var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
11801 f_rslem_register(0, chan_nr);
11802
11803 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
11804 BSSAP.send(ass_cmd);
11805
11806
11807 /* Wait for the Channel Activ for the TCH channel */
11808 var ASP_RSL_Unitdata rx_rsl_ud;
11809 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
11810
11811 /* make the original SDCCH disappear */
11812 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
11813
11814 /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
11815 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
11816
11817 interleave {
11818 [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
11819 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
11820 }
11821
11822 BSSAP.send(ts_BSSMAP_ClearCommand(0));
11823 BSSAP.receive(tr_BSSMAP_ClearComplete);
11824 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11825
11826 var MgcpCommand mgcp;
Vadim Yanitskiy6be4cf42022-06-04 21:25:47 +060011827 var MGCP_RecvFrom mrf;
11828 var template MgcpMessage msg_dlcx := { command := tr_DLCX };
11829 alt {
11830 [g_pars.aoip] MGCP.receive(tr_DLCX) -> value mgcp {
11831 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
11832 }
11833 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
11834 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
11835 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
11836 }));
11837 }
11838 }
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011839
11840 f_sleep(0.5);
11841}
11842testcase TC_lost_sdcch_during_assignment() runs on test_CT {
11843 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11844 var MSC_ConnHdlr vc_conn;
11845
Oliver Smith735b47c2023-02-15 16:03:54 +010011846 pars.fail_on_dlcx := false;
11847
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011848 f_init(1, true);
11849 f_sleep(1.0);
11850
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011851 vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
11852 vc_conn.done;
11853
11854 f_shutdown_helper();
11855}
11856
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011857const CounterNameVals counternames_bsc_bts_all_available_allocated := {
11858 { "all_allocated:sdcch", 0 },
11859 { "all_allocated:static_sdcch", 0 },
11860 { "all_allocated:tch", 0 },
11861 { "all_allocated:static_tch", 0 }
11862}
11863
11864private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
11865{
11866 /* Make sure counters settle first */
11867 f_sleep(1.0);
11868
11869 /* Take a baseline of counters */
11870 f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
11871
11872 /* Elapse some time so that we see changes in counters, hopefully where expected */
11873 f_sleep(2.0);
11874
11875 /* Get new counters */
11876 var charstring_list all_changed := {};
11877 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
11878 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
11879
11880 /* Compare with expectations */
11881 var charstring_list all_expect_changed := {};
11882 for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
11883 all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
11884 }
11885 f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
11886}
11887
11888testcase TC_ratectr_all_available_allocated() runs on test_CT {
11889 var ASP_RSL_Unitdata rsl_ud;
11890 var integer i;
11891 var integer chreq_total, chreq_nochan;
11892
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011893 f_init(1, guard_timeout := 60.0);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011894 f_sleep(1.0);
11895
11896 /* Exhaust all dedicated SDCCH lchans.
11897 /* GSM 44.018 Table 9.1.8.2:
11898 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11899 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011900 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011901 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011902 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 +020011903 }
11904
11905 /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
11906 * level.
11907 * All SDCCH are now occupied. */
11908 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11909
11910 /* Also fill up all remaining (TCH) channels */
11911 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011912 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 +020011913 }
11914
11915 /* All TCH are now also occupied */
11916 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11917 "all_allocated:tch", "all_allocated:static_tch"});
11918
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011919 /* Clean up SDCCH lchans */
11920 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11921 f_perform_clear_test_ct(chan_cleanup[i]);
11922 }
11923
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011924 f_shutdown_helper();
11925}
11926
11927testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
11928 var ASP_RSL_Unitdata rsl_ud;
11929 var integer i;
11930 var integer chreq_total, chreq_nochan;
11931
11932 f_init_vty();
11933 f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
11934 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11935 /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
11936
11937 f_init(1, guard_timeout := 60.0);
11938 f_sleep(1.0);
11939
11940 /* The dyn TS wants to activate PDCH mode, ACK that. */
11941 var RslChannelNr chan_nr;
11942 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011943 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11944 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011945
11946 /* Exhaust all dedicated SDCCH lchans.
11947 /* GSM 44.018 Table 9.1.8.2:
11948 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11949 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011950 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011951 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011952 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 +020011953 }
11954
11955 /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
11956 * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
11957 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
11958
11959 /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
11960 * Will release them later, so remember all the DchanTuples. */
11961 var DchanTuples dyn_sddch := {};
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011962 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 +020011963
11964 /* Also occupy the seven other SDCCH of the dyn TS */
11965 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011966 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 +020011967 }
11968
11969 /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
11970 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11971
11972 /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
11973 for (i := 0; i < 5; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011974 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 +020011975 }
11976
11977 /* All TCH lchans are now also occupied, both static and dynamic */
11978 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11979 "all_allocated:tch", "all_allocated:static_tch"});
11980
11981 /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
11982 * incrementing. */
11983 var BssmapCause cause := 0;
11984 var DchanTuple dt := dyn_sddch[0];
11985 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011986 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011987
11988 /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
11989 * count as occupied, so those still both increment. */
11990 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
11991 "all_allocated:tch", "all_allocated:static_tch"});
11992
11993 /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
11994 for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
11995 dt := dyn_sddch[i];
11996 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011997 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011998 }
11999
12000 /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
12001 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060012002 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
12003 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012004
12005 /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
12006 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
12007
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010012008 /* Clean up SDCCH lchans */
12009 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
12010 f_perform_clear_test_ct(chan_cleanup[i]);
12011 }
12012
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012013 /* clean up config */
12014 f_ts_reset_chcomb(0);
12015
12016 f_shutdown_helper();
12017}
12018
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012019private function f_TC_chan_alloc_algo(DchanTuple dt, BtsTrxIdx idx)
12020runs on test_CT {
12021 /* MSC sends an Assignment Request */
12022 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12023 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12024 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12025 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
12026
12027 /* Expect the BSC to allocate a TCH channel on the given BTS/TRX */
12028 var RSL_Message rsl_chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
12029 /* Send CHAN ACT NACK, so that the requested TCH channel becomes BORKEN */
12030 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(rsl_chan_act.ies[0].body.chan_nr, RSL_ERR_EQUIPMENT_FAIL), idx);
12031 /* Expect to receive an Assignment Failure */
12032 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail));
12033}
12034
12035testcase TC_chan_alloc_algo_ascending() runs on test_CT {
12036 /* We need to access BTS2, which has 4 TRXs */
12037 f_init(nr_bts := 3);
12038
12039 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012040 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012041
12042 f_vty_enter_cfg_bts(BSCVTY, 2);
12043 f_vty_transceive(BSCVTY, "channel allocator ascending");
12044 f_vty_transceive(BSCVTY, "end");
12045
12046 /* Expect the BSC to allocate 4 x TCH/F channels on BTS2/TRX0 */
12047 for (var integer i := 0; i < 4; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012048 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012049 f_TC_chan_alloc_algo(dt, {2, 0});
12050 f_perform_clear_test_ct(dt);
12051 }
12052
12053 /* At this point all 4 x TCH/F channels are BORKEN, but they will be
12054 * resurrected upon the A-bis/OML link re-establishment. */
12055 f_shutdown_helper();
12056}
12057
12058testcase TC_chan_alloc_algo_descending() runs on test_CT {
12059 /* We need to access BTS2, which has 4 TRXs */
12060 f_init(nr_bts := 3);
12061
12062 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012063 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012064
12065 f_vty_enter_cfg_bts(BSCVTY, 2);
12066 f_vty_transceive(BSCVTY, "channel allocator descending");
12067 f_vty_transceive(BSCVTY, "end");
12068
12069 /* Expect the BSC to allocate 5 x TCH/F channels on BTS2/TRX3 */
12070 for (var integer i := 0; i < 5; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012071 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012072 f_TC_chan_alloc_algo(dt, {2, 3});
12073 f_perform_clear_test_ct(dt);
12074 }
12075
12076 /* At this point all 5 x TCH/F channels are BORKEN, but they will be
12077 * resurrected upon the A-bis/OML link re-establishment. */
12078 f_shutdown_helper();
12079}
12080
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012081testcase TC_chan_alloc_algo_ass_dynamic() runs on test_CT {
12082 const BtsTrxIdx TRX0 := {2, 0};
12083 const BtsTrxIdx TRX3 := {2, 3};
12084
12085 /* We need to access BTS2, which has 4 TRXs */
12086 f_init(nr_bts := 3);
12087
12088 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012089 vc_MGCP[0].stop;
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012090
12091 f_vty_enter_cfg_bts(BSCVTY, 2);
12092 f_vty_transceive(BSCVTY, "channel allocator mode assignment dynamic");
12093 f_vty_transceive(BSCVTY, "channel allocator dynamic-param ul-rxlev thresh 50 avg-num 2");
12094 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 0");
12095 f_vty_transceive(BSCVTY, "end");
12096
12097 var DchanTuple dt;
12098
12099 f_logp(BSCVTY, "Case a) Unknown Uplink RxLev, fall-back to ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012100 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012101 f_TC_chan_alloc_algo(dt, TRX0);
12102 f_perform_clear_test_ct(dt);
12103
12104 f_logp(BSCVTY, "Case b) Not enough RxLev samples, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012105 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012106 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12107 ts_RSL_IE_UplinkMeas(30, 0),
12108 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012109 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012110 f_TC_chan_alloc_algo(dt, TRX0);
12111 f_perform_clear_test_ct(dt);
12112
12113 f_logp(BSCVTY, "Case c) Uplink RxLev below the threshold, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012114 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012115 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12116 ts_RSL_IE_UplinkMeas(45, 0),
12117 ts_RSL_IE_BS_Power(0)), TRX0);
12118 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12119 ts_RSL_IE_UplinkMeas(48, 0),
12120 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012121 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012122 f_TC_chan_alloc_algo(dt, TRX0);
12123 f_perform_clear_test_ct(dt);
12124
12125 f_logp(BSCVTY, "Case d) Uplink RxLev above the threshold, use descending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012126 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012127 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12128 ts_RSL_IE_UplinkMeas(50, 0),
12129 ts_RSL_IE_BS_Power(0)), TRX0);
12130 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12131 ts_RSL_IE_UplinkMeas(58, 0),
12132 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012133 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012134 f_TC_chan_alloc_algo(dt, TRX3);
12135 f_perform_clear_test_ct(dt);
12136
12137 f_vty_enter_cfg_bts(BSCVTY, 2);
12138 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 90");
12139 f_vty_transceive(BSCVTY, "end");
12140
12141 f_logp(BSCVTY, "Case e) Uplink RxLev above the threshold, but C0 load is not");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012142 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012143 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12144 ts_RSL_IE_UplinkMeas(50, 0),
12145 ts_RSL_IE_BS_Power(0)), TRX0);
12146 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12147 ts_RSL_IE_UplinkMeas(58, 0),
12148 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012149 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012150 f_TC_chan_alloc_algo(dt, TRX0);
12151 f_perform_clear_test_ct(dt);
12152
12153 f_vty_enter_cfg_bts(BSCVTY, 2);
12154 f_vty_transceive(BSCVTY, "channel allocator ascending");
12155 f_vty_transceive(BSCVTY, "end");
12156
12157 /* At this point some TCH/F channels are BORKEN, but they will be
12158 * resurrected upon the A-bis/OML link re-establishment. */
12159 f_shutdown_helper();
12160}
12161
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012162private function f_vty_mgw_enable(integer mgw_nr := 1) runs on test_CT {
12163 var rof_charstring cmds := {
12164 "remote-ip " & mp_test_ip,
12165 "remote-port " & int2str(2427 + mgw_nr)
12166 };
12167 f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
12168 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " reconnect")
12169}
12170private function f_vty_mgw_disable(integer mgw_nr := 1) runs on test_CT {
12171 f_vty_config3(BSCVTY, {"network"}, { "no mgw " &int2str(mgw_nr) });
12172}
12173private function f_vty_mgw_block(integer mgw_nr := 1, boolean blocked := true) runs on test_CT {
12174 var charstring arg;
12175 if (blocked) {
12176 arg := "block";
12177 } else {
12178 arg := "unblock";
12179 }
12180 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " " & arg);
12181}
Pau Espin Pedrolbd598422023-06-15 17:29:09 +020012182private function f_vty_mgw_cfg_keepalive(integer mgw_nr := 1, integer req_intval := 0, charstring req_endp := "null", integer rx_timeout := 0) runs on test_CT {
12183 var charstring arg;
12184 var rof_charstring cmds := {
12185 "keepalive request-interval " & int2str(req_intval),
12186 "keepalive request-endpoint " & req_endp,
12187 "keepalive timeout " & int2str(rx_timeout)
12188 };
12189 f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
12190}
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012191private const charstring COORD_CMD_ESTABLISHED := "COORD_CMD_ESTABLISHED";
12192private function f_TC_mgwpool_call_seq_1(charstring id) runs on MSC_ConnHdlr {
12193 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Pau Espin Pedrolb522e1c2023-09-28 13:38:50 +020012194 var PDU_BSSAP ass_cmd := f_gen_ass_req(ass_cid := 0);
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012195 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12196 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12197
12198 f_establish_fully(ass_cmd, exp_compl);
12199 COORD.send(COORD_CMD_ESTABLISHED);
12200
12201 COORD.receive(COORD_CMD_ESTABLISHED);
12202 f_perform_clear()
12203 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12204}
12205private function f_TC_mgwpool_call_seq_2(charstring id) runs on MSC_ConnHdlr {
12206 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Pau Espin Pedrolb522e1c2023-09-28 13:38:50 +020012207 var PDU_BSSAP ass_cmd := f_gen_ass_req(ass_cid := 1);
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012208 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12209 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12210
12211
12212 COORD.receive(COORD_CMD_ESTABLISHED);
12213 f_establish_fully(ass_cmd, exp_compl);
12214 COORD.send(COORD_CMD_ESTABLISHED);
12215
12216 f_perform_clear()
12217 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12218}
12219/* Test load is spread around 2 available MGWs */
12220testcase TC_mgwpool_all_used() runs on test_CT {
12221 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12222 var MSC_ConnHdlr vc_conn1;
12223 pars1.mgwpool_idx := 0;
12224
12225 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12226 var MSC_ConnHdlr vc_conn2;
12227 pars2.mgwpool_idx := 1;
Pau Espin Pedrol577688b2023-09-28 14:51:42 +020012228 pars2.media_nr := 2;
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012229
12230 f_init(1, true, nr_mgw := 2);
12231 f_sleep(1.0);
12232
12233 f_vty_mgw_enable(1);
12234
12235 vc_conn1 := f_start_handler_create(pars1);
12236 vc_conn2 := f_start_handler_create(pars2);
12237 connect(vc_conn1:COORD, vc_conn2:COORD);
12238 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12239 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12240 vc_conn1.done;
12241 vc_conn2.done;
12242
12243 f_vty_mgw_disable(1);
12244
12245 f_shutdown_helper();
12246}
12247
12248/* Test blocked MGW in the pool are not selected */
12249testcase TC_mgwpool_blocked_not_used() runs on test_CT {
12250 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12251 var MSC_ConnHdlr vc_conn1;
12252 pars1.mgwpool_idx := 0;
12253
12254 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12255 var MSC_ConnHdlr vc_conn2;
12256 pars2.mgwpool_idx := 0; /* expect it in the first one, since the second will be blocked */
12257 pars2.media_nr := 2;
12258
12259 f_init(1, true, nr_mgw := 2);
12260 f_sleep(1.0);
12261
12262 f_vty_mgw_enable(1);
12263 f_vty_mgw_block(1, true);
12264
12265 vc_conn1 := f_start_handler_create(pars1);
12266 vc_conn2 := f_start_handler_create(pars2);
12267 connect(vc_conn1:COORD, vc_conn2:COORD);
12268 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12269 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12270 vc_conn1.done;
12271 vc_conn2.done;
12272
12273 f_vty_mgw_disable(1);
12274
12275 f_shutdown_helper();
12276}
12277
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012278/* Test BTS pinning to an MGW is applied */
12279testcase TC_mgwpool_pin_bts() runs on test_CT {
12280 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12281 var MSC_ConnHdlr vc_conn1;
12282 pars1.mgwpool_idx := 0;
12283
12284 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12285 var MSC_ConnHdlr vc_conn2;
12286 pars2.mgwpool_idx := 0; /* expect it in the first one, since the BTS is pinned to the first MGW */
12287 pars2.media_nr := 2;
12288
12289 f_init(1, true, nr_mgw := 2);
12290 f_sleep(1.0);
12291
12292 f_vty_mgw_enable(1);
12293 f_vty_cfg_bts(BSCVTY, 0, { "mgw pool-target 0" });
12294
12295 vc_conn1 := f_start_handler_create(pars1);
12296 vc_conn2 := f_start_handler_create(pars2);
12297 connect(vc_conn1:COORD, vc_conn2:COORD);
12298 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12299 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12300 vc_conn1.done;
12301 vc_conn2.done;
12302
12303 f_vty_cfg_bts(BSCVTY, 0, { "no mgw pool-target" } );
Vadim Yanitskiy389d7e02022-10-25 17:44:05 +070012304 f_vty_mgw_disable(1);
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012305
12306 f_shutdown_helper();
12307}
12308
Pau Espin Pedrolbd598422023-06-15 17:29:09 +020012309/* Test keepalive procedure on the MGW */
12310private function f_TC_mgwpool_keepalive_mgw0(charstring id) runs on MSC_ConnHdlr {
12311 /* Make sure the MGW is considered DOWN by the keepalive. See "timeout"
12312 * param in TC_mgwpool_keepalive. */
12313 f_sleep(3.0);
12314
12315 COORD.send(COORD_CMD_ESTABLISHED);
12316
12317 /* Wait for signal that call was established successfully over the other MSC/MGW: */
12318 COORD.receive(COORD_CMD_ESTABLISHED);
12319}
12320private function f_TC_mgwpool_keepalive_mgw1(charstring id) runs on MSC_ConnHdlr {
12321 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12322 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12323 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12324 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12325
12326 /* Wait for other MSC/MGW component to tell us the timeout is done and
12327 * we can start the call, which will be assigned to use because the other
12328 * MGW will be seen as DOWN. */
12329 COORD.receive(COORD_CMD_ESTABLISHED);
12330 f_establish_fully(ass_cmd, exp_compl);
12331 /* signal that call was established successfully over the other MSC/MGW: */
12332 COORD.send(COORD_CMD_ESTABLISHED);
12333
12334 f_perform_clear()
12335 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12336}
12337testcase TC_mgwpool_keepalive_down_not_used() runs on test_CT {
12338 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12339 var MSC_ConnHdlr vc_conn1;
12340 pars1.mgwpool_idx := 0;
12341
12342 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12343 var MSC_ConnHdlr vc_conn2;
12344 pars2.mgwpool_idx := 1; /* expect it in the second one, since the first will be considered DOWN */
12345 pars2.media_nr := 2;
12346
12347 f_init(1, true, nr_mgw := 2);
12348 f_sleep(1.0);
12349
Vadim Yanitskiycf25a3a2023-06-20 17:27:18 +070012350 f_vty_mgw_cfg_keepalive(0, req_intval := 1, req_endp := "null", rx_timeout := 3);
Pau Espin Pedrolbd598422023-06-15 17:29:09 +020012351 f_vty_mgw_enable(1);
12352 f_vty_mgw_block(1, false);
Pau Espin Pedrolbd598422023-06-15 17:29:09 +020012353
12354 vc_conn1 := f_start_handler_create(pars1);
12355 vc_conn2 := f_start_handler_create(pars2);
12356 connect(vc_conn1:COORD, vc_conn2:COORD);
12357 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_keepalive_mgw0), pars1);
12358 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_keepalive_mgw1), pars2);
12359 vc_conn1.done;
12360 vc_conn2.done;
12361
12362 f_vty_mgw_disable(1);
12363 /* disable keepalive (default status): */
12364 f_vty_mgw_cfg_keepalive(0, req_intval := 0, req_endp := "null", rx_timeout := 0);
12365
12366 f_shutdown_helper();
12367}
12368
Oliver Smithc9a5f532022-10-21 11:32:23 +020012369private function f_tc_ho_meas_rep_multi_band(charstring id) runs on MSC_ConnHdlr {
12370 g_pars := f_gen_test_hdlr_pars();
12371 var PDU_BSSAP ass_req := f_gen_ass_req();
12372 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12373 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12374 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12375 f_establish_fully(ass_req, exp_compl);
12376
12377 /* Send a measurement report with bad rxlev except on 3rd entry. The
12378 * measurement report is divided into two sub lists, as described in
12379 * 3GPP TS 04.08 § 10.5.2.20. */
12380 var NcellReports neighbor_rep := {
12381 /* Sub list 1: same band */
Oliver Smitha6773042022-10-24 12:56:30 +020012382 { rxlev := 0, bcch_freq := 0, bsic := 12 }, /* ARFCN 800, band 1800, LAC 98 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012383 /* Sub list 2: different band */
Oliver Smitha6773042022-10-24 12:56:30 +020012384 { rxlev := 0, bcch_freq := 1, bsic := 13 }, /* ARFCN 200, band 850, LAC 97 */
12385 { rxlev := 40, bcch_freq := 2, bsic := 14 }, /* ARFCN 1000, band 900, LAC 99 */
12386 { rxlev := 0, bcch_freq := 3, bsic := 11 } /* ARFCN 0, band 900, LAC 96 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012387 };
12388 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
12389 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
12390 l3_mr, 0));
12391
12392 /* Expect a handover to the third entry. If the BSC parsed the report
Oliver Smitha6773042022-10-24 12:56:30 +020012393 * correctly, the third entry has LAC 99. */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012394 var template BSSMAP_FIELD_CellIdentificationList cid_list := {
Oliver Smitha6773042022-10-24 12:56:30 +020012395 cIl_LAC := { ts_BSSMAP_CI_LAC(99) }
Oliver Smithc9a5f532022-10-21 11:32:23 +020012396 };
12397 alt {
12398 [] BSSAP.receive(tr_BSSMAP_HandoverRequired(cid_list := cid_list)) {
12399 setverdict(pass);
12400 }
12401 [] BSSAP.receive(tr_BSSMAP_HandoverRequired()) {
12402 setverdict(fail, "Handover has unexpected LAC in Cell Identification List. The BSC probably"
12403 & " didn't parse the multi-band measurement report correctly.");
12404 }
12405 }
12406
12407 f_ho_out_of_this_bsc(skip_meas_rep := true);
12408}
12409testcase TC_ho_meas_rep_multi_band() runs on test_CT {
12410 /* Verify that the BSC parses the measurement report correctly when
12411 * neighbors in multiple bands are configured (OS#5717). See
12412 * gsm_arfcn2band_rc() in libosmocore src/gsm/gsm_utils.c for the
12413 * ARFCN -> band mapping. The MS is connected to band 1800. */
12414 var MSC_ConnHdlr vc_conn;
12415
12416 f_init_vty();
12417 f_bts_0_cfg(BSCVTY,
12418 {"neighbor-list mode automatic",
12419 "handover 1",
12420 "handover algorithm 2",
12421 "handover2 window rxlev averaging 1",
12422 "no neighbors",
12423 "neighbor lac 99 arfcn 1000 bsic any", /* band 900 */
12424 "neighbor lac 98 arfcn 800 bsic any", /* band 1800 */
12425 "neighbor lac 97 arfcn 200 bsic any", /* band 850 */
Oliver Smitha6773042022-10-24 12:56:30 +020012426 "neighbor lac 96 arfcn 0 bsic any"}); /* band 900 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012427 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
12428
12429 f_init(1, true);
12430 f_sleep(1.0);
12431
12432 f_ctrs_bsc_and_bts_handover_init();
12433
12434 vc_conn := f_start_handler(refers(f_tc_ho_meas_rep_multi_band));
12435 vc_conn.done;
12436
12437 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
12438 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
12439 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
12440 f_ctrs_bsc_and_bts_add(0, "handover:completed");
12441 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
12442 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
12443 f_ctrs_bsc_and_bts_verify();
12444 f_shutdown_helper(ho := true);
12445}
12446
Neels Hofmeyr8f4db542023-11-22 04:15:10 +010012447private function f_vty_expect_borken(TELNETasp_PT pt, boolean expect_borken)
12448{
12449 var charstring lchan_summary;
12450 lchan_summary := f_vty_transceive_ret(pt, "show lchan summary");
12451 var boolean found_borken := (f_strstr(lchan_summary, "State BORKEN") >= 0);
12452 if (found_borken != expect_borken) {
12453 if (expect_borken) {
12454 setverdict(fail, "Expected 'BORKEN' state in ", lchan_summary);
12455 } else {
12456 setverdict(fail, "Expected no 'BORKEN' state in ", lchan_summary);
12457 }
12458 mtc.stop;
12459 }
12460}
12461
12462private function f_tc_unbreak_lchan_after_missing_rel_ack(integer test_variant) runs on MSC_ConnHdlr {
12463
12464 /* Establish a channel, so we can mess with the release of it. */
12465 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12466 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12467
12468 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12469 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12470
12471 f_establish_fully(ass_cmd, exp_compl);
12472
12473 /* shorten X28, the time after which a BORKEN lchan recovers, from 30s to something short */
12474 f_vty_enter_cfg_network(BSCVTY);
12475 f_vty_transceive(BSCVTY, "timer X28 3");
12476 f_vty_transceive(BSCVTY, "end");
12477
12478 /* Allow us to include handling of Channel Activation in this component, to test recovery from BORKEN */
12479 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
12480
12481 /* give a moment before releasing */
12482 f_sleep(2.0);
12483
12484 /* Perform a channel release, but omit the RF CHAN REL ACK. The aim is to get the lchan to go BORKEN. */
12485 f_perform_clear(send_rel_ack := false);
12486
12487 f_vty_expect_borken(BSCVTY, false);
12488
12489 /* After a timeout of X6, the lchan ends up in LCHAN_ST_BORKEN */
12490 f_sleep(6.0);
12491
12492 f_vty_expect_borken(BSCVTY, true);
12493
12494 /* Now within two seconds, we expect OsmoBSC to attempt recovering from the broken state.
12495 *
12496 * test_variant == 1:
12497 * It will first attempt a Channel Activation. If the BTS accepts that, it means the state is back in sync.
12498 * Then OsmoBSC releases the lchan again and makes it available for use.
12499 *
12500 * test_variant == 2:
12501 * It will first attempt a Channel Activation and the BTS NACKs that.
12502 * It will then attempt a release, which we ACK, and the channel will be available again.
12503 */
12504
12505 /* Receive the Channel Activation */
12506 var ASP_RSL_Unitdata rx_rsl_ud;
12507 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
12508
12509 var RslChannelNr chan_nr;
12510 var RSL_IE_Body ie;
12511 if (f_rsl_find_ie(rx_rsl_ud.rsl, RSL_IE_CHAN_NR, ie) == true) {
12512 chan_nr := ie.chan_nr;
12513 } else {
12514 setverdict(fail, "Unable to find RSL_IE_CHAN_NR in ", rx_rsl_ud);
12515 return;
12516 }
12517
12518 if (test_variant == 1) {
12519 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
12520
12521 /* Back in sync, receive the Channel Release */
12522 RSL.receive(tr_RSL_RF_CHAN_REL(chan_nr));
12523 RSL.send(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
12524 } else if (test_variant == 2) {
12525 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL), rx_rsl_ud.streamId));
12526
12527 /* Instead tries a release */
12528 RSL.receive(tr_RSL_RF_CHAN_REL(chan_nr));
12529 RSL.send(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
12530 /* That worked, channel usable again */
12531 } else {
12532 setverdict(fail, "undefined test_variant ", test_variant);
12533 }
12534
12535 f_vty_expect_borken(BSCVTY, false);
12536 setverdict(pass);
12537}
12538
12539/* Test recovery path from a BORKEN lchan */
12540private function f_TC_unbreak_lchan_after_missing_rel_ack_1(charstring id) runs on MSC_ConnHdlr {
12541 f_tc_unbreak_lchan_after_missing_rel_ack(test_variant := 1);
12542}
12543testcase TC_unbreak_lchan_after_missing_rel_ack_1() runs on test_CT {
12544 var TestHdlrParams pars := f_gen_test_hdlr_pars();
12545 var MSC_ConnHdlr vc_conn;
12546 f_init(1, true);
12547 f_sleep(1.0);
12548 vc_conn := f_start_handler(refers(f_TC_unbreak_lchan_after_missing_rel_ack_1), pars);
12549 vc_conn.done;
12550 f_shutdown_helper();
12551}
12552
12553private function f_TC_unbreak_lchan_after_missing_rel_ack_2(charstring id) runs on MSC_ConnHdlr {
12554 f_tc_unbreak_lchan_after_missing_rel_ack(test_variant := 2);
12555}
12556testcase TC_unbreak_lchan_after_missing_rel_ack_2() runs on test_CT {
12557 var TestHdlrParams pars := f_gen_test_hdlr_pars();
12558 var MSC_ConnHdlr vc_conn;
12559 f_init(1, true);
12560 f_sleep(1.0);
12561 vc_conn := f_start_handler(refers(f_TC_unbreak_lchan_after_missing_rel_ack_2), pars);
12562 vc_conn.done;
12563 f_shutdown_helper();
12564}
12565
Harald Welte28d943e2017-11-25 15:00:50 +010012566control {
Harald Welte898113b2018-01-31 18:32:21 +010012567 /* CTRL interface testing */
Harald Welte4003d112017-12-09 22:35:39 +010012568 execute( TC_ctrl_msc_connection_status() );
Stefan Sperlingb041b3d2018-01-03 17:14:55 +010012569 execute( TC_ctrl_msc0_connection_status() );
Neels Hofmeyrf65ce872021-09-23 18:40:10 +020012570 /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
12571 * these in the AoIP test suite. */
12572 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12573 execute( TC_stat_num_msc_connected_1() );
12574 execute( TC_stat_num_msc_connected_2() );
12575 execute( TC_stat_num_msc_connected_3() );
12576 }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020012577 execute( TC_stat_num_bts_connected_1() );
12578 execute( TC_stat_num_bts_connected_2() );
12579 execute( TC_stat_num_bts_connected_3() );
Harald Welte96c94412017-12-09 03:12:45 +010012580 execute( TC_ctrl() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012581 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +020012582 execute( TC_ctrl_location() );
12583 }
Harald Welte898113b2018-01-31 18:32:21 +010012584
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012585 execute( TC_si_default() );
Neels Hofmeyr66aeba42020-07-06 02:21:21 +020012586 execute( TC_si2quater_2_earfcns() );
12587 execute( TC_si2quater_3_earfcns() );
12588 execute( TC_si2quater_4_earfcns() );
12589 execute( TC_si2quater_5_earfcns() );
12590 execute( TC_si2quater_6_earfcns() );
Neels Hofmeyrad132f22020-07-08 02:20:16 +020012591 execute( TC_si2quater_12_earfcns() );
12592 execute( TC_si2quater_23_earfcns() );
12593 execute( TC_si2quater_32_earfcns() );
12594 execute( TC_si2quater_33_earfcns() );
12595 execute( TC_si2quater_42_earfcns() );
12596 execute( TC_si2quater_48_earfcns() );
12597 execute( TC_si2quater_49_earfcns() );
Pau Espin Pedrol85a84432020-07-20 18:45:03 +020012598 execute( TC_si_acc_rotate() );
Alexander Couzens4ad3a352020-09-10 22:29:12 +020012599 execute( TC_si_acc_ramp_rotate() );
Oliver Smith45a6dd32023-09-27 10:52:50 +020012600 execute( TC_si2_ncc_permitted() ); /* TODO: test in SI6 too */
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012601
Harald Welte898113b2018-01-31 18:32:21 +010012602 /* RSL DCHAN Channel ACtivation / Deactivation */
Harald Welteae026692017-12-09 01:03:01 +010012603 execute( TC_chan_act_noreply() );
Harald Welte4003d112017-12-09 22:35:39 +010012604 execute( TC_chan_act_counter() );
Harald Welteae026692017-12-09 01:03:01 +010012605 execute( TC_chan_act_ack_noest() );
Philipp Maier9c60a622020-07-09 15:08:46 +020012606 execute( TC_chan_act_ack_noest_emerg() );
Philipp Maier606f07d2020-08-12 17:21:58 +020012607 execute( TC_chan_rqd_emerg_deny() );
Harald Welteae026692017-12-09 01:03:01 +010012608 execute( TC_chan_act_ack_est_ind_noreply() );
12609 execute( TC_chan_act_ack_est_ind_refused() );
Harald Welte618ef642017-12-14 14:58:20 +010012610 execute( TC_chan_act_nack() );
Harald Welte799c97b2017-12-14 17:50:30 +010012611 execute( TC_chan_exhaustion() );
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +070012612 execute( TC_chan_deact_silence() );
Harald Welte4003d112017-12-09 22:35:39 +010012613 execute( TC_chan_rel_rll_rel_ind() );
12614 execute( TC_chan_rel_conn_fail() );
12615 execute( TC_chan_rel_hard_clear() );
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +020012616 execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
12617 execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
Harald Welte99787102019-02-04 10:41:36 +010012618 execute( TC_chan_rel_hard_clear_csfb() );
Harald Welted8c36cd2017-12-09 23:05:31 +010012619 execute( TC_chan_rel_hard_rlsd() );
Harald Welte550daf92018-06-11 19:22:13 +020012620 execute( TC_chan_rel_hard_rlsd_ms_dead() );
Harald Welte85804d42017-12-10 14:11:58 +010012621 execute( TC_chan_rel_a_reset() );
Pau Espin Pedrolc675b612020-01-09 19:55:40 +010012622 execute( TC_chan_rel_sccp_tiar_timeout() );
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +020012623 execute( TC_chan_rel_rr_cause() );
Harald Welte6f521d82017-12-11 19:52:02 +010012624
Harald Weltecfe2c962017-12-15 12:09:32 +010012625 execute( TC_outbound_connect() );
Harald Welte898113b2018-01-31 18:32:21 +010012626
12627 /* Assignment related */
Harald Welte16a4adf2017-12-14 18:54:01 +010012628 execute( TC_assignment_cic_only() );
Harald Welte235ebf12017-12-15 14:18:16 +010012629 execute( TC_assignment_csd() );
12630 execute( TC_assignment_ctm() );
12631 execute( TC_assignment_sign() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012632 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12633 execute( TC_assignment_aoip_tla_v6() );
12634 }
Harald Welte235ebf12017-12-15 14:18:16 +010012635 execute( TC_assignment_fr_a5_0() );
12636 execute( TC_assignment_fr_a5_1() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012637 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte8f67d1d2018-05-25 20:38:42 +020012638 execute( TC_assignment_fr_a5_1_codec_missing() );
12639 }
Harald Welte235ebf12017-12-15 14:18:16 +010012640 execute( TC_assignment_fr_a5_3() );
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +020012641 execute( TC_assignment_fr_a5_4() );
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +020012642 execute( TC_assignment_fr_a5_4_fail() );
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +020012643 execute( TC_assignment_fr_a5_not_sup() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012644 execute( TC_ciph_mode_a5_0() );
12645 execute( TC_ciph_mode_a5_1() );
Oliver Smith50b98122021-07-09 15:00:28 +020012646 execute( TC_ciph_mode_a5_2_0() );
Oliver Smith1dff88d2021-07-09 08:45:51 +020012647 execute( TC_ciph_mode_a5_2_1() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012648 execute( TC_ciph_mode_a5_3() );
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +020012649 execute( TC_ciph_mode_a5_4() );
Harald Welte16a4adf2017-12-14 18:54:01 +010012650
Harald Welte60aa5762018-03-21 19:33:13 +010012651 execute( TC_assignment_codec_fr() );
Neels Hofmeyr559d5d02021-04-16 16:50:49 +020012652 execute( TC_assignment_codec_fr_by_mode_modify() );
Harald Welte60aa5762018-03-21 19:33:13 +010012653 execute( TC_assignment_codec_hr() );
12654 execute( TC_assignment_codec_efr() );
12655 execute( TC_assignment_codec_amr_f() );
12656 execute( TC_assignment_codec_amr_h() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012657
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012658 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier8a581d22019-03-26 18:32:48 +010012659 execute( TC_assignment_codec_amr_f_S1() );
12660 execute( TC_assignment_codec_amr_h_S1() );
12661 execute( TC_assignment_codec_amr_f_S124() );
12662 execute( TC_assignment_codec_amr_h_S124() );
12663 execute( TC_assignment_codec_amr_f_S0() );
12664 execute( TC_assignment_codec_amr_f_S02() );
12665 execute( TC_assignment_codec_amr_f_S024() );
12666 execute( TC_assignment_codec_amr_f_S0247() );
12667 execute( TC_assignment_codec_amr_h_S0() );
12668 execute( TC_assignment_codec_amr_h_S02() );
12669 execute( TC_assignment_codec_amr_h_S024() );
12670 execute( TC_assignment_codec_amr_h_S0247() );
12671 execute( TC_assignment_codec_amr_f_S01234567() );
12672 execute( TC_assignment_codec_amr_f_S0234567() );
12673 execute( TC_assignment_codec_amr_f_zero() );
12674 execute( TC_assignment_codec_amr_f_unsupp() );
12675 execute( TC_assignment_codec_amr_h_S7() );
Neels Hofmeyr21863562020-11-26 00:34:33 +000012676 execute( TC_assignment_codec_amr_f_start_mode_auto() );
12677 execute( TC_assignment_codec_amr_h_start_mode_auto() );
Neels Hofmeyr3eb94562020-11-26 02:40:26 +000012678 execute( TC_assignment_codec_amr_f_start_mode_4() );
12679 execute( TC_assignment_codec_amr_h_start_mode_4() );
Neels Hofmeyr454d7922020-11-26 02:24:57 +000012680 execute( TC_assignment_codec_amr_startmode_cruft() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012681 }
Harald Welte60aa5762018-03-21 19:33:13 +010012682
Philipp Maierac09bfc2019-01-08 13:41:39 +010012683 execute( TC_assignment_codec_fr_exhausted_req_hr() );
12684 execute( TC_assignment_codec_fr_exhausted_req_fr() );
12685 execute( TC_assignment_codec_fr_exhausted_req_fr_hr() );
12686 execute( TC_assignment_codec_fr_exhausted_req_hr_fr() );
12687 execute( TC_assignment_codec_hr_exhausted_req_fr() );
12688 execute( TC_assignment_codec_hr_exhausted_req_hr() );
12689 execute( TC_assignment_codec_hr_exhausted_req_hr_fr() );
12690 execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
12691 execute( TC_assignment_codec_req_hr_fr() );
12692 execute( TC_assignment_codec_req_fr_hr() );
Pau Espin Pedrol14475352021-07-22 15:48:16 +020012693 execute( TC_assignment_sdcch_exhausted_req_signalling() );
12694 execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
12695 execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
Philipp Maierac09bfc2019-01-08 13:41:39 +010012696
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +020012697 execute( TC_assignment_codec_hr_osmux_on() );
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +020012698 execute( TC_assignment_osmux() );
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020012699 execute( TC_assignment_osmux_cn() );
12700 execute( TC_assignment_osmux_bts() );
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +020012701
Harald Welte898113b2018-01-31 18:32:21 +010012702 /* RLL Establish Indication on inactive DCHAN / SAPI */
Harald Welte5cd20ed2017-12-13 21:03:20 +010012703 execute( TC_rll_est_ind_inact_lchan() );
12704 execute( TC_rll_est_ind_inval_sapi1() );
12705 execute( TC_rll_est_ind_inval_sapi3() );
12706 execute( TC_rll_est_ind_inval_sacch() );
12707
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +070012708 /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
12709 execute( TC_tch_dlci_link_id_sapi() );
12710
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012711 /* SAPI N Reject triggered by RLL establishment failures */
12712 execute( TC_rll_rel_ind_sapi_n_reject() );
12713 execute( TC_rll_err_ind_sapi_n_reject() );
12714 execute( TC_rll_timeout_sapi_n_reject() );
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +070012715 execute( TC_rll_sapi_n_reject_dlci_cc() );
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012716
Harald Welte898113b2018-01-31 18:32:21 +010012717 /* Paging related tests */
Harald Welte6f521d82017-12-11 19:52:02 +010012718 execute( TC_paging_imsi_nochan() );
12719 execute( TC_paging_tmsi_nochan() );
12720 execute( TC_paging_tmsi_any() );
12721 execute( TC_paging_tmsi_sdcch() );
12722 execute( TC_paging_tmsi_tch_f() );
12723 execute( TC_paging_tmsi_tch_hf() );
12724 execute( TC_paging_imsi_nochan_cgi() );
12725 execute( TC_paging_imsi_nochan_lac_ci() );
12726 execute( TC_paging_imsi_nochan_ci() );
12727 execute( TC_paging_imsi_nochan_lai() );
12728 execute( TC_paging_imsi_nochan_lac() );
12729 execute( TC_paging_imsi_nochan_all() );
Harald Welte751d3eb2018-01-31 15:51:06 +010012730 execute( TC_paging_imsi_nochan_plmn_lac_rnc() );
12731 execute( TC_paging_imsi_nochan_rnc() );
12732 execute( TC_paging_imsi_nochan_lac_rnc() );
12733 execute( TC_paging_imsi_nochan_lacs() );
12734 execute( TC_paging_imsi_nochan_lacs_empty() );
Stefan Sperling049a86e2018-03-20 15:51:00 +010012735 execute( TC_paging_imsi_nochan_cgi_unknown_cid() );
Harald Welte10985002017-12-12 09:29:15 +010012736 execute( TC_paging_imsi_a_reset() );
Harald Weltee65d40e2017-12-13 00:09:06 +010012737 execute( TC_paging_imsi_load() );
Philipp Maier779a7922018-02-16 11:00:37 +010012738 execute( TC_paging_counter() );
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +010012739 execute( TC_paging_resp_unsol() );
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +020012740 execute( TC_paging_500req() );
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +020012741 execute( TC_paging_450req_no_paging_load_ind() );
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +010012742 execute( TC_paging_imsi_nochan_ci_resp_invalid_mi() );
Harald Welte4e9b9cc2017-12-14 18:31:02 +010012743
12744 execute( TC_rsl_drop_counter() );
Stefan Sperling830dc9d2018-02-12 21:08:28 +010012745 execute( TC_rsl_unknown_unit_id() );
12746
12747 execute( TC_oml_unknown_unit_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012748
12749 execute( TC_classmark() );
Harald Welteeddf0e92020-06-21 19:42:15 +020012750 execute( TC_common_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012751 execute( TC_unsol_ass_fail() );
Harald Welteea99a002018-01-31 20:46:43 +010012752 execute( TC_unsol_ass_compl() );
Harald Weltefbf9b5e2018-01-31 20:41:23 +010012753 execute( TC_unsol_ho_fail() );
Harald Weltee3bd6582018-01-31 22:51:25 +010012754 execute( TC_err_82_short_msg() );
Harald Weltee9e02e42018-01-31 23:36:25 +010012755 execute( TC_err_84_unknown_msg() );
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012756
Harald Welte261af4b2018-02-12 21:20:39 +010012757 execute( TC_ho_int() );
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +020012758 execute( TC_ho_int_a5_0() );
12759 execute( TC_ho_int_a5_1() );
12760 execute( TC_ho_int_a5_3() );
12761 execute( TC_ho_int_a5_4() );
Neels Hofmeyr5f144212020-11-03 15:41:58 +000012762 execute( TC_ho_int_radio_link_failure() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012763
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012764 /* TC_ho_out_of_this_bsc is run last, see comment below */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +020012765 execute( TC_ho_out_fail_no_msc_response() );
12766 execute( TC_ho_out_fail_rr_ho_failure() );
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +020012767 execute( TC_ho_out_fail_no_result_after_ho_cmd() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012768
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012769 execute( TC_ho_into_this_bsc() );
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +020012770 execute( TC_ho_into_this_bsc_a5_0() );
12771 execute( TC_ho_into_this_bsc_a5_1() );
12772 execute( TC_ho_into_this_bsc_a5_3() );
12773 execute( TC_ho_into_this_bsc_a5_4() );
Neels Hofmeyr93182e02022-02-17 21:59:07 +010012774 execute( TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() );
12775 execute( TC_ho_into_this_bsc_a5_1_3() );
Neels Hofmeyr907b23b2022-02-17 21:58:47 +010012776 execute( TC_ho_into_this_bsc_a5_mismatch() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012777 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12778 execute( TC_ho_into_this_bsc_tla_v6() );
12779 }
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +020012780 execute( TC_srvcc_eutran_to_geran() );
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +030012781 execute( TC_srvcc_eutran_to_geran_a5_3() );
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +010012782 execute( TC_srvcc_eutran_to_geran_src_sai() );
Pau Espin Pedrol35801c32021-04-19 13:03:20 +020012783 execute( TC_srvcc_eutran_to_geran_ho_out() );
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +020012784 execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
12785 execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012786 execute( TC_ho_in_fail_msc_clears() );
12787 execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
12788 execute( TC_ho_in_fail_no_detect() );
12789 execute( TC_ho_in_fail_no_detect2() );
Oliver Smith7a8594a2023-02-13 14:30:49 +010012790 execute( TC_ho_in_fail_mgw_mdcx_timeout() );
Oliver Smith4eed06f2023-02-15 15:43:19 +010012791 execute( TC_ho_in_fail_ipa_crcx_timeout() );
Neels Hofmeyra23f3b12022-03-02 19:57:12 +010012792 execute( TC_ho_into_this_bsc_sccp_cr_without_bssap() );
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012793
Neels Hofmeyr91401012019-07-11 00:42:35 +020012794 execute( TC_ho_neighbor_config_1() );
12795 execute( TC_ho_neighbor_config_2() );
12796 execute( TC_ho_neighbor_config_3() );
12797 execute( TC_ho_neighbor_config_4() );
12798 execute( TC_ho_neighbor_config_5() );
12799 execute( TC_ho_neighbor_config_6() );
12800 execute( TC_ho_neighbor_config_7() );
12801
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012802 execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() );
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010012803 execute( TC_bssmap_clear_does_not_cause_bssmap_reset() );
Neels Hofmeyrfd445c32018-03-09 15:39:31 +010012804 execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() );
Harald Welte94e0c342018-04-07 11:33:23 +020012805
12806 execute( TC_dyn_pdch_ipa_act_deact() );
12807 execute( TC_dyn_pdch_ipa_act_nack() );
12808 execute( TC_dyn_pdch_osmo_act_deact() );
12809 execute( TC_dyn_pdch_osmo_act_nack() );
Pau Espin Pedrol37a4c152021-11-16 19:02:23 +010012810 execute( TC_dyn_ts_sdcch8_act_deact() );
12811 execute( TC_dyn_ts_sdcch8_all_subslots_used() );
12812 execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
12813 execute( TC_dyn_ts_sdcch8_act_nack() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012814
Stefan Sperling0796a822018-10-05 13:01:39 +020012815 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +020012816 execute( TC_chopped_ipa_payload() );
Stefan Sperling0796a822018-10-05 13:01:39 +020012817
Pau Espin Pedrol8f773632019-11-05 11:46:53 +010012818 /* Power control related */
12819 execute( TC_assignment_verify_ms_power_params_ie() );
Vadim Yanitskiy4b233042021-06-30 00:58:43 +020012820 execute( TC_c0_power_red_mode() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012821
12822 /* MSC pooling */
12823 /* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
12824 * RESET->RESET-ACK is unconditionally negotiated for all configured MSCs, they always all appear as connected
12825 * to osmo-bsc. The MSC pooling tests however require disconnecting selected MSCs, and hence don't work out as
12826 * intended on SCCPlite. So for now, run these only for SCCP/M3UA. */
12827 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12828 execute( TC_mscpool_L3Compl_on_1_msc() );
12829 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
12830 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
12831 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
12832 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
12833 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
12834 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
12835 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
12836 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
12837 execute( TC_mscpool_paging_and_response_imsi() );
12838 execute( TC_mscpool_paging_and_response_tmsi() );
12839 execute( TC_mscpool_no_allow_attach_round_robin() );
12840 execute( TC_mscpool_no_allow_attach_valid_nri() );
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +020012841
12842 execute( TC_mscpool_sccp_n_pcstate_detaches_msc() );
Neels Hofmeyr38632aa2023-04-05 03:50:51 +020012843 execute( TC_mscpool_sccp_n_pcstate_attaches_msc() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012844 }
12845
Harald Welte99f3ca02018-06-14 13:40:29 +020012846 execute( TC_early_conn_fail() );
12847 execute( TC_late_conn_fail() );
Oliver Smithaf03bef2021-08-24 15:34:51 +020012848 execute( TC_stats_conn_fail() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012849
Philipp Maier783681c2020-07-16 16:47:06 +020012850 /* Emergency call handling (deny / allow) */
12851 execute( TC_assignment_emerg_setup_allow() );
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +010012852 execute( TC_assignment_emerg_setup_allow_imei() );
Philipp Maier783681c2020-07-16 16:47:06 +020012853 execute( TC_assignment_emerg_setup_deny_msc() );
12854 execute( TC_assignment_emerg_setup_deny_bts() );
Philipp Maier82812002020-08-13 18:48:27 +020012855 execute( TC_emerg_premption() );
12856
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +070012857 /* Frequency hopping parameters handling */
12858 execute( TC_fh_params_chan_activ() );
12859 execute( TC_fh_params_imm_ass() );
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070012860 execute( TC_fh_params_assignment_cmd() );
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070012861 execute( TC_fh_params_handover_cmd() );
Vadim Yanitskiyca974032020-09-01 07:20:39 +070012862 execute( TC_fh_params_si4_cbch() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012863
12864 if (mp_enable_lcs_tests) {
12865 execute( TC_lcs_loc_req_for_active_ms() );
12866 execute( TC_lcs_loc_req_for_active_ms_ta_req() );
12867 execute( TC_lcs_loc_req_for_idle_ms() );
12868 execute( TC_lcs_loc_req_no_subscriber() );
12869 execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
12870 execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
12871 execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
12872 execute( TC_cm_service_during_lcs_loc_req() );
12873 execute( TC_ho_during_lcs_loc_req() );
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020012874 execute( TC_emerg_call_and_lcs_loc_req() );
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020012875 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() );
12876 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012877 }
Neels Hofmeyrbf037052020-10-28 22:52:02 +000012878
12879 execute( TC_no_msc() );
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000012880
12881 execute( TC_refuse_chan_act_to_vamos() );
12882 execute( TC_refuse_mode_modif_to_vamos() );
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000012883
12884 execute( TC_reassignment_fr() );
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020012885
12886 execute( TC_cm_reestablishment() );
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020012887
12888 execute( TC_imm_ass_post_chan_ack() );
12889 execute( TC_imm_ass_pre_chan_ack() );
Neels Hofmeyr23158742021-09-07 19:08:07 +020012890 execute( TC_imm_ass_pre_ts_ack() );
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020012891 execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020012892 execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020012893
12894 execute( TC_ctrl_trx_rf_locked() );
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012895
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012896 execute( TC_ratectr_all_available_allocated() );
12897 execute( TC_ratectr_all_available_allocated_dyn() );
12898
Neels Hofmeyrb7581872021-11-07 14:02:49 +010012899 execute( TC_cm_serv_rej() );
12900
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012901 execute( TC_lost_sdcch_during_assignment() );
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012902
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012903 /* Channel allocator */
12904 execute( TC_chan_alloc_algo_ascending() );
12905 execute( TC_chan_alloc_algo_descending() );
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012906 execute( TC_chan_alloc_algo_ass_dynamic() );
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012907
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012908 /* MGW pool */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +010012909 execute( TC_mgwpool_all_used() );
12910 execute( TC_mgwpool_blocked_not_used() );
12911 execute( TC_mgwpool_pin_bts() );
Pau Espin Pedrolbd598422023-06-15 17:29:09 +020012912 execute( TC_mgwpool_keepalive_down_not_used() );
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012913
Oliver Smithc9a5f532022-10-21 11:32:23 +020012914 execute( TC_ho_meas_rep_multi_band() );
12915
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012916 /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
12917 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
12918 execute( TC_ho_out_of_this_bsc() );
Neels Hofmeyr8f4db542023-11-22 04:15:10 +010012919
12920 execute( TC_unbreak_lchan_after_missing_rel_ack_1() );
12921 execute( TC_unbreak_lchan_after_missing_rel_ack_2() );
Harald Welte28d943e2017-11-25 15:00:50 +010012922}
12923
12924}