blob: 0844955569ab1284c5c97db6127b83e607c1e37f [file] [log] [blame]
Harald Welte28d943e2017-11-25 15:00:50 +01001module BSC_Tests {
2
Harald Welte21b46bd2017-12-17 19:46:32 +01003/* Integration Tests for OsmoBSC
Harald Weltea0630032018-03-20 21:09:55 +01004 * (C) 2017-2018 by Harald Welte <laforge@gnumonks.org>
Harald Welte21b46bd2017-12-17 19:46:32 +01005 * All rights reserved.
6 *
7 * Released under the terms of GNU General Public License, Version 2 or
8 * (at your option) any later version.
9 *
Harald Welte34b5a952019-05-27 11:54:11 +020010 * SPDX-License-Identifier: GPL-2.0-or-later
11 *
Harald Welte21b46bd2017-12-17 19:46:32 +010012 * This test suite tests OsmoBSC while emulating both multiple BTS + MS as
13 * well as the MSC. See README for more details.
14 *
15 * There are test cases that run in so-called 'handler mode' and test cases
16 * that run directly on top of the BSSAP and RSL CodecPorts. The "handler mode"
17 * tests abstract the multiplexing/demultiplexing of multiple SCCP connections
18 * and/or RSL channels and are hence suitable for higher-level test cases, while
19 * the "raw" tests directly on top of the CodecPorts are more suitable for lower-
20 * level testing.
21 */
22
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +020023friend module BSC_Tests_VAMOS;
Vadim Yanitskiy5eb06a32022-06-23 18:39:46 +070024friend module BSC_Tests_CBSP;
Vadim Yanitskiy3cc065b2023-01-06 21:35:12 +070025friend module BSC_Tests_LCLS;
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +020026
Neels Hofmeyr4f118412020-06-04 15:25:10 +020027import from Misc_Helpers all;
Harald Welte4003d112017-12-09 22:35:39 +010028import from General_Types all;
Harald Welte28d943e2017-11-25 15:00:50 +010029import from Osmocom_Types all;
Harald Welteae026692017-12-09 01:03:01 +010030import from GSM_Types all;
Harald Welte28d943e2017-11-25 15:00:50 +010031import from IPL4asp_Types all;
32
Harald Welte6f521d82017-12-11 19:52:02 +010033import from BSSAP_Types all;
Harald Welte6811d102019-04-14 22:23:14 +020034import from RAN_Adapter all;
Harald Welte47cd0e32020-08-21 12:39:11 +020035import from BSSAP_LE_Adapter all;
36import from BSSAP_LE_CodecPort all;
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020037import from BSSAP_LE_Types all;
38import from BSSLAP_Types all;
Harald Welteae026692017-12-09 01:03:01 +010039import from BSSAP_CodecPort all;
40import from BSSMAP_Templates all;
Harald Welte28d943e2017-11-25 15:00:50 +010041import from IPA_Emulation all;
Stefan Sperling830dc9d2018-02-12 21:08:28 +010042import from IPA_CodecPort all;
Harald Welteae026692017-12-09 01:03:01 +010043import from IPA_Types all;
Stefan Sperling0796a822018-10-05 13:01:39 +020044import from IPA_Testing all;
Harald Welteae026692017-12-09 01:03:01 +010045import from RSL_Types all;
Harald Welte624f9632017-12-16 19:26:04 +010046import from RSL_Emulation all;
Daniel Willmann191e0d92018-01-17 12:44:35 +010047import from MGCP_Emulation all;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010048import from MGCP_Templates all;
49import from MGCP_Types all;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +020050import from MGCP_CodecPort all;
Harald Welte28d943e2017-11-25 15:00:50 +010051
Harald Welte96c94412017-12-09 03:12:45 +010052import from Osmocom_CTRL_Functions all;
Harald Weltea5d2ab22017-12-09 14:21:42 +010053import from Osmocom_CTRL_Types all;
Harald Welteffe55fc2018-01-17 22:39:54 +010054import from Osmocom_CTRL_Adapter all;
Harald Welte96c94412017-12-09 03:12:45 +010055
Daniel Willmannebdecc02020-08-12 15:30:17 +020056import from StatsD_Types all;
57import from StatsD_CodecPort all;
58import from StatsD_CodecPort_CtrlFunct all;
59import from StatsD_Checker all;
60
Harald Weltebc03c762018-02-12 18:09:38 +010061import from Osmocom_VTY_Functions all;
62import from TELNETasp_PortType all;
63
Harald Welte6f521d82017-12-11 19:52:02 +010064import from MobileL3_CommonIE_Types all;
Harald Weltee3bd6582018-01-31 22:51:25 +010065import from MobileL3_Types all;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010066import from MobileL3_RRM_Types all;
Harald Welte6f521d82017-12-11 19:52:02 +010067import from L3_Templates all;
68import from GSM_RR_Types all;
69
Stefan Sperlingc307e682018-06-14 15:15:46 +020070import from SCCP_Templates all;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010071import from BSSMAP_Templates all;
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020072import from BSSMAP_LE_Templates all;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010073
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010074import from SCCPasp_Types all;
75
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020076import from GSM_SystemInformation all;
77import from GSM_RestOctets all;
Neels Hofmeyrad132f22020-07-08 02:20:16 +020078import from TCCConversion_Functions all;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020079
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060080const integer NUM_TRX := 4;
Harald Welte5d1a2202017-12-13 19:51:29 +010081const integer NUM_BTS := 3;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020082const integer NUM_BTS_CFG := 4; /* we have 4 BTS in the osmo-bsc.cfg (for inter-BSC HO tests) but use only 3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060083const integer NUM_TRX_CFG := 1; /* we support up to 4 TRX per BTS, but have only 1 TRX per BTS in osmo-bsc.cfg */
Neels Hofmeyrf246a922020-05-13 02:27:10 +020084const integer NUM_MSC := 3;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020085const integer NUM_MGW := 2;
Harald Welteae026692017-12-09 01:03:01 +010086const float T3101_MAX := 12.0;
Harald Welte28d943e2017-11-25 15:00:50 +010087
Harald Welte799c97b2017-12-14 17:50:30 +010088/* make sure to sync this with the osmo-bts.cfg you're using */
Philipp Maiercb6cc482018-03-26 13:08:00 +020089const integer NUM_TCHH_PER_BTS := 2;
90const integer NUM_TCHF_PER_BTS := 4;
Neels Hofmeyr74083c22020-07-29 00:43:01 +020091const integer NUM_SDCCH_PER_BTS := 3;
Harald Welte799c97b2017-12-14 17:50:30 +010092
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060093friend type record BtsTrxIdx {
94 uint8_t bts,
95 uint8_t trx
96}
97
98private type record BtsParams {
99 integer trx_num,
100 integer tsc
101}
102
Neels Hofmeyrbf720202021-10-02 12:58:24 +0200103/* Default Training Sequence Code expected for bts[i]:
104 * BTS 0 has BSIC 10 (and no explicit timeslot training_sequence_code config), so expecting TSC = (BSIC & 7) = 2.
105 * BTS 1 has BSIC 11, TSC = (BSIC & 7) = 3.
106 * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
107 * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
108 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600109private const BtsParams c_BtsParams[NUM_BTS_CFG] := {
110 /* BTS0 */ { trx_num := 1, tsc := 2 },
111 /* BTS1 */ { trx_num := 1, tsc := 3 },
Vadim Yanitskiy7a3d2932022-05-29 20:37:46 +0600112 /* BTS2 */ { trx_num := 4, tsc := 4 },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600113 /* BTS3 */ { trx_num := 1, tsc := 4 }
Neels Hofmeyrbf720202021-10-02 12:58:24 +0200114}
Harald Welte4003d112017-12-09 22:35:39 +0100115
Vadim Yanitskiy59494702022-09-14 15:29:04 +0700116private const RSL_IE_Body c_mr_conf_5_90 :=
Pau Espin Pedrolf7634dc2022-09-02 17:56:00 +0200117 valueof(RSL_IE_Body:{multirate_cfg := ts_RSL_MultirateCfg(true, 0, '00000100'B /* 5,90k */)});
118
Harald Welte21b46bd2017-12-17 19:46:32 +0100119/* per-BTS state which we keep */
Harald Welte96c94412017-12-09 03:12:45 +0100120type record BTS_State {
Harald Welte21b46bd2017-12-17 19:46:32 +0100121 /* component reference to the IPA_Client component used for RSL */
Harald Weltea5d2ab22017-12-09 14:21:42 +0100122 IPA_Client rsl
Harald Welte96c94412017-12-09 03:12:45 +0100123}
124
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200125/* Default list of counters for an 'msc' entity. */
126const CounterNameVals counternames_msc_mscpool := {
127 { "mscpool:subscr:new", 0 },
128 { "mscpool:subscr:known", 0 },
129 { "mscpool:subscr:reattach", 0 },
130 { "mscpool:subscr:attach_lost", 0 },
131 { "mscpool:subscr:paged", 0 }
132};
133
Neels Hofmeyrbf037052020-10-28 22:52:02 +0000134/* List of global mscpool counters, not related to a specific 'msc' entity. */
135const CounterNameVals counternames_bsc_mscpool := {
136 { "mscpool:subscr:no_msc", 0 }
137};
138
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000139/* Default list of counters for 'bsc' and 'bts' entities. */
140const CounterNameVals counternames_bsc_bts_handover := {
141 { "assignment:attempted", 0 },
142 { "assignment:completed", 0 },
143 { "assignment:stopped", 0 },
144 { "assignment:no_channel", 0 },
145 { "assignment:timeout", 0 },
146 { "assignment:failed", 0 },
147 { "assignment:error", 0 },
148
149 { "handover:attempted", 0 },
150 { "handover:completed", 0 },
151 { "handover:stopped", 0 },
152 { "handover:no_channel", 0 },
153 { "handover:timeout", 0 },
154 { "handover:failed", 0 },
155 { "handover:error", 0 },
156
157 { "intra_cell_ho:attempted", 0 },
158 { "intra_cell_ho:completed", 0 },
159 { "intra_cell_ho:stopped", 0 },
160 { "intra_cell_ho:no_channel", 0 },
161 { "intra_cell_ho:timeout", 0 },
162 { "intra_cell_ho:failed", 0 },
163 { "intra_cell_ho:error", 0 },
164
165 { "intra_bsc_ho:attempted", 0 },
166 { "intra_bsc_ho:completed", 0 },
167 { "intra_bsc_ho:stopped", 0 },
168 { "intra_bsc_ho:no_channel", 0 },
169 { "intra_bsc_ho:timeout", 0 },
170 { "intra_bsc_ho:failed", 0 },
171 { "intra_bsc_ho:error", 0 },
172
173 { "interbsc_ho_out:attempted", 0 },
174 { "interbsc_ho_out:completed", 0 },
175 { "interbsc_ho_out:stopped", 0 },
176 { "interbsc_ho_out:timeout", 0 },
177 { "interbsc_ho_out:failed", 0 },
178 { "interbsc_ho_out:error", 0 },
179
180 { "interbsc_ho_in:attempted", 0 },
181 { "interbsc_ho_in:completed", 0 },
182 { "interbsc_ho_in:stopped", 0 },
183 { "interbsc_ho_in:no_channel", 0 },
184 { "interbsc_ho_in:timeout", 0 },
185 { "interbsc_ho_in:failed", 0 },
186 { "interbsc_ho_in:error", 0 }
187};
188
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100189const CounterNameVals counternames_bts_handover := {
190 { "incoming_intra_bsc_ho:attempted", 0 },
191 { "incoming_intra_bsc_ho:completed", 0 },
192 { "incoming_intra_bsc_ho:stopped", 0 },
193 { "incoming_intra_bsc_ho:no_channel", 0 },
194 { "incoming_intra_bsc_ho:timeout", 0 },
195 { "incoming_intra_bsc_ho:failed", 0 },
196 { "incoming_intra_bsc_ho:error", 0 }
197};
198
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200199/* Set of all System Information received during one RSL port's startup.
200 * Note that some System Information may be sent on RSL, but lacking actual SI data, to indicate that the BTS should not
201 * broadcast that SI type. That will be reflected as 'omit' here.
202 */
203type record SystemInformationConfig {
204 SystemInformationType1 si1 optional,
205 SystemInformationType2 si2 optional,
206 SystemInformationType2bis si2bis optional,
207 SystemInformationType2ter si2ter optional,
Neels Hofmeyrad132f22020-07-08 02:20:16 +0200208 SI2quaterRestOctetsList si2quater optional,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200209 SystemInformationType3 si3 optional,
210 SystemInformationType4 si4 optional,
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100211 SystemInformationType13 si13 optional,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200212 SystemInformationType5 si5 optional,
213 SystemInformationType5bis si5bis optional,
214 SystemInformationType5ter si5ter optional,
215 SystemInformationType6 si6 optional
216};
217
218const SystemInformationConfig SystemInformationConfig_omit := {
219 si1 := omit,
220 si2 := omit,
221 si2bis := omit,
222 si2ter := omit,
223 si2quater := omit,
224 si3 := omit,
225 si4 := omit,
226 si13 := omit,
227 si5 := omit,
228 si5bis := omit,
229 si5ter := omit,
230 si6 := omit
231};
232
233/* tr_EUTRAN_CellDesc with defaults used in BSC_Tests.ttcn */
234template EUTRAN_CellDesc tr_EUTRAN_CellDesc_default(template (present) uint16_t e_arfcn := ?,
235 template uint3_t meas_bw := 3)
236:= tr_EUTRAN_CellDesc(e_arfcn := e_arfcn,
237 meas_bw_presence := '1'B,
238 meas_bw := meas_bw);
239
240/* tr_EUTRAN_NeighbourCells with defaults used in BSC_Tests.ttcn */
Harald Welte65e419a2020-08-21 12:38:33 +0200241template EUTRAN_NeighbourCells tr_EUTRAN_NeighbourCells_default(template (present) EUTRAN_CellDescs cell_desc_list := { tr_EUTRAN_CellDesc_default },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200242 template uint3_t prio := 3,
243 template (present) uint5_t thresh_high := 20,
244 template uint5_t thresh_low := 10,
245 template uint5_t qrxlevmin := 22)
246:= tr_EUTRAN_NeighbourCells(
247 cell_desc_list := cell_desc_list,
248 prio_presence := '1'B,
249 prio := prio,
250 thresh_high := thresh_high,
251 thresh_low_presence := '1'B,
252 thresh_low := thresh_low,
253 qrxlevmin_presence := '1'B,
254 qrxlevmin := qrxlevmin);
255
256template SystemInformationConfig SystemInformationConfig_default := {
257 si1 := {
258 cell_chan_desc := '8FB38000000000000000000000000000'O,
259 rach_control := {
260 max_retrans := RACH_MAX_RETRANS_7,
261 tx_integer := '1001'B,
262 cell_barr_access := false,
263 re_not_allowed := true,
264 acc := '0000010000000000'B
265 },
266 rest_octets := ?
267 },
268 si2 := {
269 bcch_freq_list := '00000000000000000000000000000000'O,
270 ncc_permitted := '11111111'B,
271 rach_control := {
272 max_retrans := RACH_MAX_RETRANS_7,
273 tx_integer := '1001'B,
274 cell_barr_access := false,
275 re_not_allowed := true,
276 acc := '0000010000000000'B
277 }
278 },
279 si2bis := omit,
280 si2ter := {
281 extd_bcch_freq_list := '8E320000000000000000000000000800'O,
282 rest_octets := ?
283 },
284 si2quater := {
285 tr_SI2quaterRestOctets_EUTRAN( repeated_neigh_cells := { tr_EUTRAN_NeighbourCells_default } )
286 },
287 si3 := {
288 cell_id := 0,
289 lai := {
290 mcc_mnc := '001F01'H,
291 lac := 1
292 },
293 ctrl_chan_desc := {
294 msc_r99 := true,
295 att := true,
296 bs_ag_blks_res := 1,
297 ccch_conf := CCHAN_DESC_1CCCH_COMBINED,
298 si22ind := false,
299 cbq3 := CBQ3_IU_MODE_NOT_SUPPORTED,
300 spare := '00'B,
301 bs_pa_mfrms := 3,
302 t3212 := 30
303 },
304 cell_options := {
305 dn_ind := false,
306 pwrc := false,
307 dtx := MS_SHALL_USE_UL_DTX,
308 radio_link_tout_div4 := 7
309 },
310 cell_sel_par := {
311 cell_resel_hyst_2dB := 2,
312 ms_txpwr_max_cch := 7,
313 acs := '0'B,
314 neci := true,
315 rxlev_access_min := 0
316 },
317 rach_control := {
318 max_retrans := RACH_MAX_RETRANS_7,
319 tx_integer := '1001'B,
320 cell_barr_access := false,
321 re_not_allowed := true,
322 acc := '0000010000000000'B
323 },
324 rest_octets := {
325 sel_params := {
326 presence := '0'B,
327 params := omit
328 },
329 pwr_offset := {
330 presence := '0'B,
331 offset := omit
332 },
333 si_2ter_ind := '1'B,
334 early_cm_ind := '0'B,
335 sched_where := {
336 presence := '0'B,
337 where := omit
338 },
339 gprs_ind := {
340 presence := '1'B,
341 ind := {
342 ra_colour := 0,
343 si13_pos := '0'B
344 }
345 },
346 umts_early_cm_ind := '1'B,
347 si2_quater_ind := {
348 presence := '1'B,
349 ind := '0'B
350 },
351 iu_mode_ind := omit,
352 si21_ind := {
353 presence := '0'B,
354 pos := omit
355 }
356 }
357 },
358 si4 := {
359 lai := {
360 mcc_mnc := '001F01'H,
361 lac := 1
362 },
363 cell_sel_par := {
364 cell_resel_hyst_2dB := 2,
365 ms_txpwr_max_cch := 7,
366 acs := '0'B,
367 neci := true,
368 rxlev_access_min := 0
369 },
370 rach_control := {
371 max_retrans := RACH_MAX_RETRANS_7,
372 tx_integer := '1001'B,
373 cell_barr_access := false,
374 re_not_allowed := true,
375 acc := '0000010000000000'B
376 },
Neels Hofmeyr74083c22020-07-29 00:43:01 +0200377 cbch_chan_desc := {
378 iei := '64'O,
379 v := {
380 chan_nr := {
381 u := {
382 sdcch4 := {
383 tag := '001'B,
384 sub_chan := 2
385 }
386 },
387 tn := 0
388 },
389 tsc := 2,
390 h := false,
391 arfcn := 871,
392 maio_hsn := omit
393 }
394 },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200395 cbch_mobile_alloc := omit,
396 rest_octets := {
397 sel_params := {
398 presence := '0'B,
399 params := omit
400 },
401 pwr_offset := {
402 presence := '0'B,
403 offset := omit
404 },
405 gprs_ind := {
406 presence := '1'B,
407 ind := {
408 ra_colour := 0,
409 si13_pos := '0'B
410 }
411 },
412 s_presence := '0'B,
413 s := omit
414 }
415 },
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100416 si13 := {
417 rest_octets := {
418 presence := '1'B,
419 bcch_change_mark := ?,
420 si_change_field := '0000'B,
421 presence2 := '0'B,
422 si13_change_mark := omit,
423 gprs_ma := omit,
424 zero := '0'B, /* PBCCH not present in cell */
425 rac := 0,
426 spgc_ccch_sup := '0'B,
427 priority_access_thr := '110'B,
428 network_control_order := '00'B,
429 gprs_cell_opts := {
430 nmo := '01'B,
431 t3168 := '011'B,
432 t3192 := '010'B,
433 drx_timer_max := '011'B,
434 access_burst_type := '0'B,
435 control_ack_type := '1'B,
436 bs_cv_max := 15,
437 pan_presence := '1'B,
438 pan_dec := 1,
439 pan_inc := 1,
440 pan_max := '111'B,
441 ext_info_presence := ?,
442 ext_info_length := *,
443 ext_info := *
444 },
445 gprs_pwr_ctrl_params := {
446 alpha := 0,
447 t_avg_w := '10000'B,
448 t_avg_t := '10000'B,
449 pc_meas_chan := '0'B,
450 n_avg_i := '1000'B
451 }
452 }
453 },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200454 si5 := {
455 bcch_freq_list := '10000000000000000000000000000000'O
456 },
457 si5bis := omit,
458 si5ter := {
459 extd_bcch_freq_list := '9E050020000000000000000000000000'O
460 },
461 si6 := {
462 cell_id := 0,
463 lai := {
464 mcc_mnc := '001F01'H,
465 lac := 1
466 },
467 cell_options := {
468 dtx_ext := '1'B,
469 pwrc := false,
470 dtx := '01'B,
471 radio_link_timeout := '0111'B
472 },
473 ncc_permitted := '11111111'B,
Vadim Yanitskiy348b07c2022-03-10 17:11:22 +0300474 rest_octets := {
475 pch_nch_info := ?,
476 vbs_vgcs_options := ?,
477 dtm_support := '0'B,
478 rac := omit,
479 max_lapdm := omit,
480 band_ind := '0'B /* C0 ARFCN indicates 1800 band */
481 }
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200482 }
483 };
484
485
486/* List of all the System Information received on all RSL ports */
487type record of SystemInformationConfig SystemInformationConfig_list;
488
489function f_sysinfo_dec_raw(inout SystemInformationConfig si, RSL_Message rsl)
490{
491 var RSL_IE_Body sysinfo_type_ie;
492 var RSL_IE_SysinfoType si_type;
493 var octetstring data;
494
495 if (f_rsl_find_ie(rsl, RSL_IE_SYSINFO_TYPE, sysinfo_type_ie) == false) {
496 setverdict(fail, "Cannot find RSL_IE_SYSINFO_TYPE");
497 mtc.stop;
498 }
499 si_type := sysinfo_type_ie.sysinfo_type;
500
501 if (rsl.msg_type == RSL_MT_BCCH_INFO) {
502 var RSL_IE_Body bcch_ie;
503 if (f_rsl_find_ie(rsl, RSL_IE_FULL_BCCH_INFO, bcch_ie)) {
504 data := bcch_ie.other.payload;
505 }
506 } else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
507 var RSL_IE_Body l3_ie;
508 if (f_rsl_find_ie(rsl, RSL_IE_L3_INFO, l3_ie)) {
509 data := l3_ie.l3_info.payload;
510 }
511 } else {
512 setverdict(fail, "Don't understand this System Information message");
513 mtc.stop;
514 }
515
516 var boolean handled := false;
517
518 if (rsl.msg_type == RSL_MT_BCCH_INFO) {
519 handled := true;
520
521 if (si_type == RSL_SYSTEM_INFO_1) {
522 if (not isbound(data)) {
523 si.si1 := omit;
524 } else {
525 si.si1 := dec_SystemInformation(data).payload.si1;
526 }
527 } else if (si_type == RSL_SYSTEM_INFO_2) {
528 if (not isbound(data)) {
529 si.si2 := omit;
530 } else {
531 si.si2 := dec_SystemInformation(data).payload.si2;
532 }
533 } else if (si_type == RSL_SYSTEM_INFO_2bis) {
534 if (not isbound(data)) {
535 si.si2bis := omit;
536 } else {
537 si.si2bis := dec_SystemInformation(data).payload.si2bis;
538 }
539 } else if (si_type == RSL_SYSTEM_INFO_2ter) {
540 if (not isbound(data)) {
541 si.si2ter := omit;
542 } else {
543 si.si2ter := dec_SystemInformation(data).payload.si2ter;
544 }
545 } else if (si_type == RSL_SYSTEM_INFO_2quater) {
546 if (not isbound(data)) {
547 si.si2quater := {};
548 } else {
549 var SystemInformationType2quater decoded := dec_SystemInformation(data).payload.si2quater;
550 /* this is a *record* of SI2quaterRestOctets! (multiplexed) */
551 si.si2quater[decoded.rest_octets.si2quater_index] := decoded.rest_octets;
552 }
553 } else if (si_type == RSL_SYSTEM_INFO_3) {
554 if (not isbound(data)) {
555 si.si3 := omit;
556 } else {
557 si.si3 := dec_SystemInformation(data).payload.si3;
558 }
559 } else if (si_type == RSL_SYSTEM_INFO_4) {
560 if (not isbound(data)) {
561 si.si4 := omit;
562 } else {
563 si.si4 := dec_SystemInformation(data).payload.si4;
564 }
565 } else if (si_type == RSL_SYSTEM_INFO_13) {
566 if (not isbound(data)) {
567 si.si13 := omit;
568 } else {
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100569 si.si13 := dec_SystemInformation(data).payload.si13;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200570 }
571 } else {
572 handled := false;
573 }
574 } else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
575 handled := true;
576
577 if (si_type == RSL_SYSTEM_INFO_5) {
578 if (not isbound(data)) {
579 si.si5 := omit;
580 } else {
581 si.si5 := dec_SystemInformation(data).payload.si5;
582 }
583 } else if (si_type == RSL_SYSTEM_INFO_5bis) {
584 if (not isbound(data)) {
585 si.si5bis := omit;
586 } else {
587 si.si5bis := dec_SystemInformation(data).payload.si5bis;
588 }
589 } else if (si_type == RSL_SYSTEM_INFO_5ter) {
590 if (not isbound(data)) {
591 si.si5ter := omit;
592 } else {
593 si.si5ter := dec_SystemInformation(data).payload.si5ter;
594 }
595 } else if (si_type == RSL_SYSTEM_INFO_6) {
596 if (not isbound(data)) {
597 si.si6 := omit;
598 } else {
599 si.si6 := dec_SystemInformation(data).payload.si6;
600 }
601 } else {
602 handled := false;
603 }
604 }
605
606 if (not handled) {
607 setverdict(fail, "Unexpected SI type in ", rsl.msg_type, " message: ", si_type);
608 }
609}
610
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +0100611friend function gen_l3_valid_payload(hexstring imsi := ''H) return octetstring {
612 var octetstring l3_payload;
613 if (lengthof(imsi) == 0) {
614 imsi := f_rnd_imsi('00101'H);
615 }
616 l3_payload := enc_PDU_ML3_MS_NW(valueof(ts_LU_REQ(LU_Type_IMSI_Attach, ts_MI_LV(ts_MI_IMSI(imsi)))));
617 return l3_payload;
618}
619
Harald Weltea4ca4462018-02-09 00:17:14 +0100620type component test_CT extends CTRL_Adapter_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600621 /* Array of per-BTS/TRX state */
622 var BTS_State bts[NUM_BTS][NUM_TRX];
Harald Welte89ab1912018-02-23 18:56:29 +0100623 /* RSL common Channel Port (for RSL_Emulation) */
624 port RSL_CCHAN_PT RSL_CCHAN[NUM_BTS];
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600625 /* array of per-BTS/TRX RSL test ports */
626 port IPA_RSL_PT IPA_RSL[NUM_BTS][NUM_TRX];
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100627 port IPA_CODEC_PT IPA; /* Required for compilation of TC_rsl_unknown_unit_id() */
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +0200628 /* CTRL muxed over IPA in SCCPlite conn BSC<->MSC (or BSC-NAT) */
629 port IPA_CTRL_PT SCCPLITE_IPA_CTRL;
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200630 /* Configure/manage IPA_Emulation per-BTS/TRX port: */
631 port IPA_CFG_PT IPA_CFG_PORT[NUM_BTS][NUM_TRX];
Harald Weltea5d2ab22017-12-09 14:21:42 +0100632
Pau Espin Pedrol3c630532022-10-20 19:00:11 +0200633 var MGCP_Emulation_CT vc_MGCP[NUM_MGW];
634 var integer g_nr_mgw; /* number of vc_MGCP to initialize */
Harald Weltebc03c762018-02-12 18:09:38 +0100635 port TELNETasp_PT BSCVTY;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100636
Daniel Willmannebdecc02020-08-12 15:30:17 +0200637 /* StatsD */
638 var StatsD_Checker_CT vc_STATSD;
639
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200640 var RAN_Adapter g_bssap[NUM_MSC];
Harald Welte47cd0e32020-08-21 12:39:11 +0200641 var BSSAP_LE_Adapter g_bssap_le;
Harald Weltea4ca4462018-02-09 00:17:14 +0100642 /* for old legacy-tests only */
643 port BSSAP_CODEC_PT BSSAP;
Harald Welte47cd0e32020-08-21 12:39:11 +0200644 port BSSAP_LE_CODEC_PT BSSAP_LE;
Harald Weltea4ca4462018-02-09 00:17:14 +0100645
Harald Welte21b46bd2017-12-17 19:46:32 +0100646 /* are we initialized yet */
Harald Welte28d943e2017-11-25 15:00:50 +0100647 var boolean g_initialized := false;
Harald Welte21b46bd2017-12-17 19:46:32 +0100648
Neels Hofmeyr38632aa2023-04-05 03:50:51 +0200649 var boolean g_handler_mode := false;
650
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200651 /* Osmux is enabled through VTY */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200652 var boolean g_osmux_enabled_cn := false;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +0200653 var boolean g_osmux_enabled_bts := false;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200654
Pau Espin Pedrolc675b612020-01-09 19:55:40 +0100655 /*Configure T(tias) over VTY, seconds */
656 var integer g_bsc_sccp_timer_ias := 7 * 60;
657 /*Configure T(tiar) over VTY, seconds */
658 var integer g_bsc_sccp_timer_iar := 15 * 60;
659
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +0200660 /* global test case guard timer (actual timeout value is set in f_init()) */
Harald Welteae026692017-12-09 01:03:01 +0100661 timer T_guard := 30.0;
662
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200663 var CounterNameValsList g_ctr_msc;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000664 var CounterNameValsList g_ctr_bsc;
665 var CounterNameValsList g_ctr_bts;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200666
667 /* System Information bytes as received during RSL startup, for each RSL[idx]. */
668 var SystemInformationConfig_list g_system_information := {};
Harald Welte28d943e2017-11-25 15:00:50 +0100669}
670
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200671type record of charstring phys_chan_configs;
Harald Welte28d943e2017-11-25 15:00:50 +0100672modulepar {
Harald Welte21b46bd2017-12-17 19:46:32 +0100673 /* IP address at which the BSC can be reached */
Harald Welte696ddb62017-12-08 14:01:43 +0100674 charstring mp_bsc_ip := "127.0.0.1";
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100675 /* port number to which to establish the IPA OML connections */
676 integer mp_bsc_oml_port := 3002;
Harald Welte21b46bd2017-12-17 19:46:32 +0100677 /* port number to which to establish the IPA RSL connections */
Harald Welte696ddb62017-12-08 14:01:43 +0100678 integer mp_bsc_rsl_port := 3003;
Harald Welte21b46bd2017-12-17 19:46:32 +0100679 /* port number to which to establish the IPA CTRL connection */
Harald Welte96c94412017-12-09 03:12:45 +0100680 integer mp_bsc_ctrl_port := 4249;
Daniel Willmannebdecc02020-08-12 15:30:17 +0200681 /* port number to which to listen for STATSD metrics */
682 integer mp_bsc_statsd_port := 8125;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100683 /* IP address at which the test binds */
684 charstring mp_test_ip := "127.0.0.1";
Harald Weltea4ca4462018-02-09 00:17:14 +0100685
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200686 RAN_Configurations mp_bssap_cfg := {
687 {
688 transport := BSSAP_TRANSPORT_AoIP,
689 sccp_service_type := "mtp3_itu",
690 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
691 own_pc := 185, /* 0.23.1 first MSC emulation */
692 own_ssn := 254,
693 peer_pc := 187, /* 0.23.3 osmo-bsc */
694 peer_ssn := 254,
695 sio := '83'O,
Harald Weltecb0cc432020-06-21 19:42:31 +0200696 rctx := 1
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200697 },
698 {
699 transport := BSSAP_TRANSPORT_AoIP,
700 sccp_service_type := "mtp3_itu",
701 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
702 own_pc := 2, /* 0.0.2 second MSC emulation */
703 own_ssn := 254,
704 peer_pc := 187, /* 0.23.3 osmo-bsc */
705 peer_ssn := 254,
706 sio := '83'O,
707 rctx := 2
708 },
709 {
710 transport := BSSAP_TRANSPORT_AoIP,
711 sccp_service_type := "mtp3_itu",
712 sctp_addr := { 23907, "127.0.0.1", 2905, "127.0.0.1" },
713 own_pc := 3, /* 0.0.3 third MSC emulation */
714 own_ssn := 254,
715 peer_pc := 187, /* 0.23.3 osmo-bsc */
716 peer_ssn := 254,
717 sio := '83'O,
718 rctx := 3
719 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100720 };
Pau Espin Pedrol58cf6822019-05-28 18:11:33 +0200721
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200722 /* Must match per BTS config in osmo-bsc.cfg */
723 phys_chan_configs phys_chan_config := {
724 "CCCH+SDCCH4+CBCH",
725 "TCH/F",
726 "TCH/F",
727 "TCH/F",
728 "TCH/F",
Vadim Yanitskiy343c9eb2021-07-16 18:36:01 +0600729 "TCH/H",
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200730 "PDCH",
731 "PDCH"
732 };
733
Harald Welte47cd0e32020-08-21 12:39:11 +0200734 BSSAP_LE_Configuration mp_bssap_le_cfg := {
735 sccp_service_type := "mtp3_itu",
736 sctp_addr := { 23908, "127.0.0.1", 2905, "127.0.0.1" },
Neels Hofmeyrac086c12020-09-18 23:46:42 +0200737 own_pc := 190, /* 0.23.6 SMLC emulation */
Harald Welte47cd0e32020-08-21 12:39:11 +0200738 own_ssn := 252, /* SMLC side SSN */
739 peer_pc := 187, /* 0.23.3 osmo-bsc */
740 peer_ssn := 250, /* BSC side SSN */
741 sio := '83'O,
742 rctx := 6
743 };
Neels Hofmeyrcfe44062020-10-15 02:28:08 +0200744 boolean mp_enable_lcs_tests := true;
Harald Welte47cd0e32020-08-21 12:39:11 +0200745
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100746 /* Value set in osmo-bsc.cfg "ms max power" */
747 uint8_t mp_exp_ms_power_level := 7;
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600748
749 /* Whether to check for memory leaks */
750 boolean mp_verify_talloc_count := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100751}
752
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200753friend function f_gen_test_hdlr_pars(integer bssap_idx := 0) return TestHdlrParams {
Philipp Maier48604732018-10-09 15:00:37 +0200754
755 var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200756 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier48604732018-10-09 15:00:37 +0200757 pars.aoip := true;
758 } else {
759 pars.aoip := false;
760 }
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100761 pars.exp_ms_power_level := mp_exp_ms_power_level;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200762 pars.mscpool.bssap_idx := bssap_idx;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600763 pars.expect_tsc := c_BtsParams[0].tsc;
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300764 pars.imsi := f_rnd_imsi('00101'H);
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +0100765 pars.imei := f_rnd_imei('00101'H);
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300766
767 log(testcasename(), ": using IMSI ", pars.imsi);
Neels Hofmeyrb5b7a6e2021-06-04 19:03:45 +0200768
Philipp Maier48604732018-10-09 15:00:37 +0200769 return pars;
770}
771
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200772/* Convenience functions for rate counters using g_ctr_msc. */
773
774private function f_ctrs_msc_init(integer mscs_count := NUM_MSC, CounterNameVals counternames := counternames_msc_mscpool) runs on test_CT {
775 g_ctr_msc := f_counter_name_vals_get_n(IPA_CTRL, "msc", mscs_count, counternames);
776 log("initial msc rate counters: ", g_ctr_msc);
777}
778
779private function f_ctrs_msc_add(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr9656e922020-06-30 01:27:01 +0200780 f_counter_name_vals_list_add(g_ctr_msc, msc_nr, countername, val);
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200781}
782
783/* f_ctrs_msc_init();
784 * f_do_thing(on_msc := 0);
785 * f_do_thing(on_msc := 0);
786 * f_do_other(on_msc := 1);
787 * f_ctrs_msc_add(0, "thing", 2);
788 * f_ctrs_msc_add(1, "other");
789 * f_ctrs_msc_verify();
790 */
791private function f_ctrs_msc_verify() runs on test_CT {
792 log("verifying msc rate counters: ", g_ctr_msc);
793 f_counter_name_vals_expect_n(IPA_CTRL, "msc", g_ctr_msc);
794}
795
796/* convenience: f_ctrs_msc_add() and f_ctrs_msc_verify() in one call.
797 * f_ctrs_msc_init();
798 * f_do_thing(on_msc := 0);
799 * f_do_thing(on_msc := 0);
800 * f_do_thing(on_msc := 0);
801 * f_ctrs_msc_expect(0, "thing", 3);
802 */
803private function f_ctrs_msc_expect(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
804 f_ctrs_msc_add(msc_nr, countername, val);
805 f_ctrs_msc_verify();
806}
807
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000808/* Convenience functions for rate counters using g_ctr_bts, always also including g_ctr_bsc. */
809
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100810private function f_ctrs_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000811 g_ctr_bts := f_counter_name_vals_get_n(IPA_CTRL, "bts", bts_count, counternames);
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100812 log("initial bts rate counters: ", g_ctr_bts);
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100813}
814
815function f_ctrs_bsc_and_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
816 f_ctrs_bts_init(bts_count, counternames);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000817 f_ctrs_bsc_init(counternames);
818}
819
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100820private function f_ctrs_bsc_and_bts_handover_init(integer bts_count := NUM_BTS) runs on test_CT {
821 var CounterNameVals bts_names := counternames_bsc_bts_handover & counternames_bts_handover;
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100822 f_ctrs_bts_init(bts_count, bts_names);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100823 f_ctrs_bsc_init(counternames_bsc_bts_handover);
824}
825
826private function f_ctrs_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000827 f_counter_name_vals_list_add(g_ctr_bts, bts_nr, countername, val);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100828}
829
830private function f_ctrs_bsc_and_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
831 f_ctrs_bts_add(bts_nr, countername, val);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000832 f_ctrs_bsc_add(countername, val);
833}
834
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100835function f_ctrs_bts_verify() runs on test_CT {
836 f_counter_name_vals_expect_n(IPA_CTRL, "bts", g_ctr_bts);
837}
838
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000839/* f_ctrs_bsc_and_bts_init();
840 * f_do_thing(on_bts := 0);
841 * f_do_thing(on_bts := 0);
842 * f_do_other(on_bts := 1);
843 * f_ctrs_bsc_and_bts_add(0, "thing", 2);
844 * f_ctrs_bsc_and_bts_add(1, "other");
845 * f_ctrs_bsc_and_bts_verify();
846 */
847private function f_ctrs_bsc_and_bts_verify() runs on test_CT {
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100848 f_ctrs_bts_verify();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000849 f_ctrs_bsc_verify();
850}
851
852/* convenience: f_ctrs_bsc_and_bts_add() and f_ctrs_bsc_and_bts_verify() in one call.
853 * f_ctrs_bsc_and_bts_init();
854 * f_do_thing(on_bts := 0);
855 * f_do_thing(on_bts := 0);
856 * f_do_thing(on_bts := 0);
857 * f_ctrs_bsc_and_bts_expect(0, "thing", 3);
858 */
859private function f_ctrs_bsc_and_bts_expect(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
860 f_ctrs_bsc_and_bts_add(bts_nr, countername, val);
861 f_ctrs_bsc_and_bts_verify();
862}
863
864
865/* Convenience functions for rate counters using g_ctr_bsc. */
866
867private function f_ctrs_bsc_init(CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
868 g_ctr_bsc := f_counter_name_vals_get_n(IPA_CTRL, "bsc", 1, counternames);
869 log("initial bsc rate counters: ", g_ctr_bsc);
870}
871
872private function f_ctrs_bsc_add(charstring countername, integer val := 1) runs on test_CT {
873 f_counter_name_vals_list_add(g_ctr_bsc, 0, countername, val);
874}
875
876/* f_ctrs_bsc_init();
877 * f_do_thing();
878 * f_do_thing();
879 * f_do_other();
880 * f_ctrs_bsc_add("thing", 2);
881 * f_ctrs_bsc_add("other");
882 * f_ctrs_bsc_verify();
883 */
884private function f_ctrs_bsc_verify() runs on test_CT {
885 f_counter_name_vals_expect_n(IPA_CTRL, "bsc", g_ctr_bsc);
886}
887
888/* convenience: f_ctrs_bsc_add() and f_ctrs_bsc_verify() in one call.
889 * f_ctrs_bsc_init();
890 * f_do_thing();
891 * f_ctrs_bsc_expect("thing", 1);
892 */
893private function f_ctrs_bsc_expect(charstring countername, integer val := 1) runs on test_CT {
894 f_ctrs_bsc_add(countername, val);
895 f_ctrs_bsc_verify();
896}
897
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200898
Oliver Smith39f53072022-10-27 14:44:04 +0200899friend function f_shutdown_helper(boolean ho := false) runs on test_CT {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100900 /* Run the subscr and conn leak test only when the VTY is initialized */
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600901 if (BSCVTY.checkstate("Mapped") and mp_verify_talloc_count) {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100902 f_verify_talloc_count(BSCVTY, {"struct bsc_subscr", "struct gsm_subscriber_connection"});
903 }
904
Oliver Smith39f53072022-10-27 14:44:04 +0200905 /* Reset handover related configuration */
906 if (ho) {
907 f_bts_0_cfg(BSCVTY,
908 {"no neighbors",
909 "neighbor-list mode manual-si5",
910 "neighbor-list add arfcn 100",
911 "neighbor-list add arfcn 200",
912 "si5 neighbor-list add arfcn 10",
913 "si5 neighbor-list add arfcn 20",
914 "handover algorithm 1"});
915 }
916
Daniel Willmann637ef6c2018-07-25 10:49:09 +0200917 all component.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100918 setverdict(pass);
Daniel Willmannafce8662018-07-06 23:11:32 +0200919 mtc.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100920}
921
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200922private function f_legacy_bssap_reset(integer bssap_idx := 0) runs on test_CT {
Harald Weltea4ca4462018-02-09 00:17:14 +0100923 var BSSAP_N_UNITDATA_ind ud_ind;
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200924 var boolean reset_received := false;
Harald Weltea4ca4462018-02-09 00:17:14 +0100925 timer T := 5.0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200926 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200927 ts_BSSMAP_Reset(0, g_osmux_enabled_cn)));
Harald Weltea4ca4462018-02-09 00:17:14 +0100928 T.start;
929 alt {
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200930 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[bssap_idx].sccp_addr_own, g_bssap[bssap_idx].sccp_addr_peer,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200931 tr_BSSMAP_ResetAck(g_osmux_enabled_cn))) {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200932 log("BSSMAP: Received RESET-ACK in response to RESET, we're ready to go!");
Harald Weltea4ca4462018-02-09 00:17:14 +0100933 }
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200934 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200935 log("BSSMAP: Respoding to inbound RESET with RESET-ACK");
Harald Weltea4ca4462018-02-09 00:17:14 +0100936 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200937 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200938 reset_received := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100939 repeat;
940 }
941 [] BSSAP.receive { repeat; }
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200942 [] T.timeout {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200943 log("BSSMAP: Timeout waiting for RESET-ACK after sending RESET");
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200944 /* If we received a RESET after ours was sent, it
945 may be a race condition where the other peer beacame
946 available after we sent it, but we are in a desired
947 state anyway, so go forward. */
948 if (not reset_received) {
949 setverdict(fail);
950 }
951 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100952 }
Harald Welte28d943e2017-11-25 15:00:50 +0100953}
954
Harald Welteae026692017-12-09 01:03:01 +0100955type record IPA_Client {
Harald Welte21b46bd2017-12-17 19:46:32 +0100956 /* IPA Emulation component reference */
Harald Welteae026692017-12-09 01:03:01 +0100957 IPA_Emulation_CT vc_IPA,
Harald Welte21b46bd2017-12-17 19:46:32 +0100958 /* Unit-ID and other CCM parameters to use for IPA client emulation */
Harald Welteae026692017-12-09 01:03:01 +0100959 IPA_CCM_Parameters ccm_pars,
Harald Welte21b46bd2017-12-17 19:46:32 +0100960 /* String identifier for this IPA Client */
Harald Welte624f9632017-12-16 19:26:04 +0100961 charstring id,
Harald Welte21b46bd2017-12-17 19:46:32 +0100962 /* Associated RSL Emulation Component (if any). Only used in "Handler mode" */
Harald Welte624f9632017-12-16 19:26:04 +0100963 RSL_Emulation_CT vc_RSL optional
Harald Welte28d943e2017-11-25 15:00:50 +0100964}
965
Harald Welte21b46bd2017-12-17 19:46:32 +0100966/*! Start the IPA/RSL related bits for one IPA_Client.
967 * \param clnt IPA_Client for which to establish
968 * \param bsc_host IP address / hostname of the BSC
969 * \param bsc_port TCP port number of the BSC
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600970 * \param idx BTS/TRX index values
Harald Welte21b46bd2017-12-17 19:46:32 +0100971 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600972function f_ipa_rsl_start(inout IPA_Client clnt, charstring bsc_host, PortNumber bsc_port,
973 BtsTrxIdx idx := {0, 0}, boolean handler_mode := false)
Harald Welte28d943e2017-11-25 15:00:50 +0100974runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +0100975 timer T := 10.0;
976
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600977 clnt.id := "IPA-BTS" & int2str(idx.bts) & "-TRX" & int2str(idx.trx) & "-RSL";
Harald Welte71389132021-12-09 21:58:18 +0100978 clnt.vc_IPA := IPA_Emulation_CT.create(clnt.id & "-IPA") alive;
Harald Welteae026692017-12-09 01:03:01 +0100979 clnt.ccm_pars := c_IPA_default_ccm_pars;
980 clnt.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600981 clnt.ccm_pars.unit_id := int2str(1234 + idx.bts) & "/0/" & int2str(idx.trx);
Harald Welte624f9632017-12-16 19:26:04 +0100982 if (handler_mode) {
Harald Welte71389132021-12-09 21:58:18 +0100983 clnt.vc_RSL := RSL_Emulation_CT.create(clnt.id & "-RSL") alive;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600984 connect(clnt.vc_RSL:CCHAN_PT, self:RSL_CCHAN[idx.bts]);
Harald Welte624f9632017-12-16 19:26:04 +0100985 }
Harald Welteae026692017-12-09 01:03:01 +0100986
987 map(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200988 connect(clnt.vc_IPA:CFG_PORT, self:IPA_CFG_PORT[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100989 if (handler_mode) {
990 connect(clnt.vc_IPA:IPA_RSL_PORT, clnt.vc_RSL:IPA_PT);
991 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600992 connect(clnt.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100993 }
Harald Welteae026692017-12-09 01:03:01 +0100994
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600995 var integer local_port := 10000 + idx.bts * 1000 + idx.trx;
996 clnt.vc_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", local_port, clnt.ccm_pars));
Harald Welte624f9632017-12-16 19:26:04 +0100997 if (handler_mode) {
998 clnt.vc_RSL.start(RSL_Emulation.main());
999 return;
1000 }
Harald Welteae026692017-12-09 01:03:01 +01001001
1002 /* wait for IPA RSL link to connect and send ID ACK */
1003 T.start;
1004 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001005 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) {
Harald Welteae026692017-12-09 01:03:01 +01001006 T.stop;
Harald Welteae026692017-12-09 01:03:01 +01001007 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001008 [] IPA_RSL[idx.bts][idx.trx].receive(ASP_IPA_Event:?) { repeat }
1009 [] IPA_RSL[idx.bts][idx.trx].receive { repeat }
Harald Welteae026692017-12-09 01:03:01 +01001010 [] T.timeout {
Harald Welte96c94412017-12-09 03:12:45 +01001011 setverdict(fail, "Timeout RSL waiting for ASP_IPA_EVENT_ID_ACK");
Daniel Willmannafce8662018-07-06 23:11:32 +02001012 mtc.stop;
Harald Welteae026692017-12-09 01:03:01 +01001013 }
1014 }
1015}
1016
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001017function f_ipa_rsl_stop(inout IPA_Client clnt, BtsTrxIdx idx := {0, 0}) runs on test_CT {
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001018 var IPL4asp_Types.Result res := {
1019 errorCode := omit,
1020 connId := omit,
1021 os_error_code := omit,
1022 os_error_text := omit
1023 };
1024
Harald Welte12055472018-03-17 20:10:08 +01001025 if (not isbound(clnt) or not isbound(clnt.vc_IPA)) {
1026 return;
1027 }
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001028
1029 /* Alive components don't finish sockets (TCP FIN) when they are
1030 * stopped. Hence, we need to manually call close() on them to make sure
1031 * the IUT knows about it. */
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001032 f_ipa_cfg_disconnect(IPA_CFG_PORT[idx.bts][idx.trx], res);
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001033
Harald Welte12055472018-03-17 20:10:08 +01001034 clnt.vc_IPA.stop;
1035 if (isbound(clnt.vc_RSL)) {
1036 clnt.vc_RSL.stop;
1037 }
1038}
1039
Harald Welte21b46bd2017-12-17 19:46:32 +01001040/* Wait for the OML connection to be brought up by the external osmo-bts-omldummy */
Harald Weltea5d2ab22017-12-09 14:21:42 +01001041function f_wait_oml(integer bts_nr, charstring status, float secs_max) runs on test_CT {
1042 timer T := secs_max;
1043 T.start;
1044 while (true) {
1045 if (f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-connection-state") == status) {
1046 T.stop;
Harald Weltebd868bd2017-12-10 18:28:40 +01001047 /* the 'degraded' state exists from OML connection time, and we have to wait
1048 * until all MO's are initialized */
1049 T.start(1.0);
1050 T.timeout;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001051 return;
1052 }
Harald Weltef0d6ac62017-12-17 17:02:21 +01001053 f_sleep(0.1);
Harald Weltea5d2ab22017-12-09 14:21:42 +01001054 if (not T.running) {
Max99253902018-11-16 17:57:39 +01001055 setverdict(fail, "Timeout waiting for BTS" & int2str(bts_nr) & " oml-connection-state ", status);
Daniel Willmannafce8662018-07-06 23:11:32 +02001056 mtc.stop;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001057 }
1058 }
1059}
1060
Harald Welte21b46bd2017-12-17 19:46:32 +01001061/* global altstep for global guard timer; also takes care of responding RESET witH RESET-ACK */
Harald Welteae026692017-12-09 01:03:01 +01001062altstep as_Tguard() runs on test_CT {
Harald Welte60e823a2017-12-10 14:10:59 +01001063 var BSSAP_N_UNITDATA_ind ud_ind;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001064 [] T_guard.timeout {
1065 setverdict(fail, "Timeout of T_guard");
Daniel Willmannafce8662018-07-06 23:11:32 +02001066 mtc.stop;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001067 }
Harald Welte60e823a2017-12-10 14:10:59 +01001068 /* always respond with RESET ACK to RESET */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001069 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Harald Welte60e823a2017-12-10 14:10:59 +01001070 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001071 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Harald Welte69c1c262017-12-13 21:02:08 +01001072 repeat;
Harald Welte60e823a2017-12-10 14:10:59 +01001073 }
Harald Welte28d943e2017-11-25 15:00:50 +01001074}
1075
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001076altstep no_bssmap_reset() runs on test_CT {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001077 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001078 setverdict(fail, "unexpected BSSMAP Reset");
Daniel Willmannafce8662018-07-06 23:11:32 +02001079 mtc.stop;
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001080 }
1081}
1082
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001083function f_init_mgcp(integer mgw_nr, charstring id) runs on test_CT {
1084 id := id & "-MGCP-" & int2str(mgw_nr);
Daniel Willmann191e0d92018-01-17 12:44:35 +01001085
1086 var MGCPOps ops := {
1087 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
1088 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
1089 };
1090 var MGCP_conn_parameters mgcp_pars := {
1091 callagent_ip := mp_bsc_ip,
Harald Welte9e4273e2018-01-29 22:01:22 +01001092 callagent_udp_port := -1,
Daniel Willmann191e0d92018-01-17 12:44:35 +01001093 mgw_ip := mp_test_ip,
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001094 mgw_udp_port := 2427 + mgw_nr,
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02001095 /* Enable it for SCCPlite, since we have 2 MGCP sockets towards MGW (UDP one +
Pau Espin Pedrol36eeaf72022-10-20 16:50:31 +02001096 the one with MGCP over IPA forwarded from MSC one) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001097 multi_conn_mode := (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER)
Daniel Willmann191e0d92018-01-17 12:44:35 +01001098 };
1099
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001100 vc_MGCP[mgw_nr] := MGCP_Emulation_CT.create(id) alive;
1101 vc_MGCP[mgw_nr].start(MGCP_Emulation.main(ops, mgcp_pars, id));
Daniel Willmann191e0d92018-01-17 12:44:35 +01001102}
1103
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001104/* Enable or disable (current default) Osmux. When enabling, BSSMAP Reset
1105 * contains extra IE (OsmuxSupport) and osmo-bsc will handle AssignReq with
1106 * OsmuxCID IE.
1107 */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001108private function f_vty_allow_osmux_cn(boolean allow) runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001109 f_vty_enter_cfg_msc(BSCVTY, 0);
1110 if (allow) {
1111 f_vty_transceive(BSCVTY, "osmux on");
1112 } else {
1113 f_vty_transceive(BSCVTY, "osmux off");
1114 }
1115 f_vty_transceive(BSCVTY, "exit");
1116 f_vty_transceive(BSCVTY, "exit");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001117}
1118
Max2253c0b2018-11-06 19:28:05 +01001119function f_init_vty(charstring id := "foo") runs on test_CT {
Harald Welte94e0c342018-04-07 11:33:23 +02001120 if (BSCVTY.checkstate("Mapped")) {
1121 /* skip initialization if already executed once */
1122 return;
1123 }
Harald Weltebc03c762018-02-12 18:09:38 +01001124 map(self:BSCVTY, system:BSCVTY);
1125 f_vty_set_prompts(BSCVTY);
1126 f_vty_transceive(BSCVTY, "enable");
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01001127 f_cs7_inst_0_cfg(BSCVTY, {"sccp-timer ias " & int2str(g_bsc_sccp_timer_ias),
1128 "sccp-timer iar " & int2str(g_bsc_sccp_timer_iar)});
Harald Weltebc03c762018-02-12 18:09:38 +01001129}
1130
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +02001131friend function f_logp(TELNETasp_PT pt, charstring log_msg)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001132{
1133 // log on TTCN3 log output
1134 log(log_msg);
1135 // log in stderr log
Neels Hofmeyr8bdafe52021-12-14 17:25:48 +01001136 if (pt.checkstate("Mapped")) {
1137 f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
1138 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001139}
1140
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001141private function f_sysinfo_seen(integer rsl_idx, RSL_Message rsl) runs on test_CT
1142{
1143 if (rsl_idx >= lengthof(g_system_information)) {
1144 g_system_information[rsl_idx] := SystemInformationConfig_omit
1145 }
1146 f_sysinfo_dec_raw(g_system_information[rsl_idx], rsl);
1147}
1148
1149altstep as_catch_RSL_sysinfo(integer rsl_idx) runs on test_CT {
1150 var ASP_RSL_Unitdata rx_rsl_ud;
1151
1152 /* For handler_mode := false, receiving the RSL bootstrap messages directly on IPA_RSL */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001153 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001154 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1155 repeat;
1156 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001157 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001158 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1159 repeat;
1160 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001161 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001162 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1163 repeat;
1164 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001165 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001166 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1167 repeat;
1168 }
1169
1170 /* For handler_mode := true, receiving the RSL bootstrap messages via RSL_Emulation */
1171 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
1172 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1173 repeat;
1174 }
1175 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
1176 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1177 repeat;
1178 }
1179 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
1180 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1181 repeat;
1182 }
1183 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
1184 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1185 repeat;
1186 }
1187}
1188
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001189/* TODO: use BooleanList from COMMON/src/General_Types.ttcn */
1190private type record of boolean my_BooleanList;
1191
1192private function f_vty_msc_allow_attach(TELNETasp_PT pt, my_BooleanList allow_attach_list)
1193{
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001194 var charstring config := f_vty_transceive_ret(pt, "show running-config");
1195
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001196 for (var integer msc_nr := 0; msc_nr < sizeof(allow_attach_list); msc_nr := msc_nr+1) {
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001197 if (f_strstr(config, "\nmsc " & int2str(msc_nr) & "\n") < 0) {
1198 /* There is no 'msc N' for this msc_nr in the running config, so don't create an empty msc by
1199 * stepping into that config node. */
1200 log("msc ", msc_nr, " is not configured, skipping");
1201 continue;
1202 }
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001203 f_vty_enter_cfg_msc(pt, msc_nr);
1204 if (allow_attach_list[msc_nr]) {
1205 /* strict := false: ignore if osmo-bsc does not support this config option (latest build) */
1206 f_vty_transceive(pt, "allow-attach", strict := false);
1207 } else {
1208 f_vty_transceive(pt, "no allow-attach", strict := false);
1209 }
1210 f_vty_transceive(pt, "exit");
1211 f_vty_transceive(pt, "exit");
1212 }
1213}
1214
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02001215private function f_bssap_idx_init(integer bssap_idx) runs on test_CT {
1216 /* Call a function of our 'parent component' RAN_Adapter_CT to start the
1217 * MSC-side BSSAP emulation */
1218 if (g_handler_mode) {
1219 var RanOps ranops := MSC_RanOps;
1220 ranops.use_osmux := g_osmux_enabled_cn;
1221 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", ranops);
1222 connect(self:SCCPLITE_IPA_CTRL, g_bssap[bssap_idx].vc_RAN:CTRL_CLIENT);
1223 f_ran_adapter_start(g_bssap[bssap_idx]);
1224 } else {
1225 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", omit);
1226 connect(self:BSSAP, g_bssap[bssap_idx].vc_SCCP:SCCP_SP_PORT);
1227 f_ran_adapter_start(g_bssap[bssap_idx]);
1228 f_legacy_bssap_reset();
1229 }
1230}
1231
1232private function f_bssap_idx_disconnect(integer bssap_idx) runs on test_CT {
1233 f_ran_adapter_cleanup(g_bssap[bssap_idx]);
1234}
1235
Harald Welte21b46bd2017-12-17 19:46:32 +01001236/* global initialization function
1237 * \param nr_bts Number of BTSs we should start/bring up
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001238 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false).
1239 * \param nr_msc Number of virtual MSCs to bring up to connect to osmo-bsc.
1240 */
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001241function f_init(integer nr_bts := NUM_BTS, boolean handler_mode := false,
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001242 integer nr_msc := 1, integer nr_mgw := 1, float guard_timeout := 30.0) runs on test_CT {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001243 var integer bssap_idx;
Harald Welte28d943e2017-11-25 15:00:50 +01001244
Harald Welteae026692017-12-09 01:03:01 +01001245 if (g_initialized) {
1246 return;
Harald Welte28d943e2017-11-25 15:00:50 +01001247 }
Harald Welteae026692017-12-09 01:03:01 +01001248 g_initialized := true;
1249
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +02001250 T_guard.start(guard_timeout);
Daniel Willmanne68f9272018-11-27 15:15:28 +01001251 activate(as_Tguard());
1252
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001253 f_init_vty("VirtMSC");
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001254 f_vty_allow_osmux_cn(g_osmux_enabled_cn);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001255
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001256 var my_BooleanList allow_attach := { false, false, false };
Daniel Willmannebdecc02020-08-12 15:30:17 +02001257 f_init_statsd("VirtMSC", vc_STATSD, mp_test_ip, mp_bsc_statsd_port);
1258
Neels Hofmeyr9db8e0e2021-08-23 20:45:58 +02001259 /* Make sure each MSC's internal state is "DISCONNECTED" at first */
1260 for (bssap_idx := 0; bssap_idx < NUM_MSC; bssap_idx := bssap_idx+1) {
1261 f_vty_transceive(BSCVTY, "msc " & int2str(bssap_idx) & " bssmap reset", strict := false);
1262 }
1263
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02001264 g_handler_mode := handler_mode;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001265 for (bssap_idx := 0; bssap_idx < nr_msc; bssap_idx := bssap_idx+1) {
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001266 allow_attach[bssap_idx] := true;
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02001267 f_bssap_idx_init(bssap_idx);
Harald Welte67089ee2018-01-17 22:19:03 +01001268 }
Harald Welted5833a82018-05-27 16:52:56 +02001269
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02001270 if (mp_enable_lcs_tests) {
1271 if (handler_mode) {
1272 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", SMLC_BssapLeOps);
1273 } else {
1274 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", omit);
1275 connect(self:BSSAP_LE, g_bssap_le.vc_SCCP:SCCP_SP_PORT);
1276 }
1277 f_bssap_le_adapter_start(g_bssap_le);
Harald Welte47cd0e32020-08-21 12:39:11 +02001278 }
Harald Welte47cd0e32020-08-21 12:39:11 +02001279
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001280 /* start the test with exactly all enabled MSCs allowed to attach */
1281 f_vty_msc_allow_attach(BSCVTY, allow_attach);
1282
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01001283 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Harald Welte28d943e2017-11-25 15:00:50 +01001284
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001285 g_nr_mgw := nr_mgw;
1286 for (var integer i := 0; i < g_nr_mgw; i := i+1) {
1287 f_init_mgcp(i, "VirtMGW");
1288 }
Daniel Willmann191e0d92018-01-17 12:44:35 +01001289
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001290 for (var integer i := 0; i < nr_bts; i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001291 f_init_bts(i, c_BtsParams[i].trx_num, handler_mode);
Harald Welte696ddb62017-12-08 14:01:43 +01001292 }
Neels Hofmeyr9c0f9c82022-01-23 01:20:28 +01001293
1294 /* Emit a marker to appear in the SUT's own logging output */
1295 f_logp(BSCVTY, testcasename() & "() start");
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001296}
Harald Welte696ddb62017-12-08 14:01:43 +01001297
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001298function f_init_bts(integer bts_idx := 0,
1299 integer trx_num := NUM_TRX_CFG,
1300 boolean handler_mode := false)
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001301runs on test_CT {
1302 /* wait until osmo-bts-omldummy has respawned */
1303 f_wait_oml(bts_idx, "degraded", 5.0);
1304
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001305 /* start RSL connection(s) */
1306 for (var integer trx_idx := 0; trx_idx < trx_num; trx_idx := trx_idx + 1) {
1307 f_ipa_rsl_start(bts[bts_idx][trx_idx].rsl,
1308 mp_bsc_ip, mp_bsc_rsl_port,
1309 {bts_idx, trx_idx}, handler_mode);
1310 }
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001311 /* wait until BSC tells us "connected" */
1312 f_wait_oml(bts_idx, "connected", 5.0);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001313
1314 /* Set up BTS with VTY commands: */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01001315 f_vty_enter_cfg_bts(BSCVTY, bts_idx);
1316 if (g_osmux_enabled_bts) {
1317 f_vty_transceive(BSCVTY, "osmux on");
1318 } else {
1319 f_vty_transceive(BSCVTY, "osmux off");
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001320 }
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01001321 f_vty_transceive(BSCVTY, "end");
Harald Welte28d943e2017-11-25 15:00:50 +01001322}
1323
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001324function f_init_bts_and_check_sysinfo(integer bts_idx := 0,
1325 integer trx_num := NUM_TRX_CFG,
1326 boolean handler_mode := false,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001327 template SystemInformationConfig expect_si)
1328runs on test_CT {
1329 var default sysinfo := activate(as_catch_RSL_sysinfo(bts_idx));
1330
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001331 f_init_bts(bts_idx, trx_num, handler_mode);
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001332
1333 /* Give some time to (hopefully/most likely) collect all system informations from RSL startup.
1334 * We could stop as soon as all expected SI are received, but then we might miss SI that we don't expect and
1335 * that might be sent afterwards. So rather give a generous timeout and be quite sure to catch all SI.
1336 */
1337 f_sleep(5.0);
1338 log("RSL ", bts_idx, " SYSTEM INFORMATION: ", g_system_information[bts_idx]);
1339
1340 deactivate(sysinfo);
1341
1342 if (match(g_system_information[bts_idx], expect_si)) {
1343 setverdict(pass);
1344 } else {
1345 log("RSL ", bts_idx, ": EXPECTED SI: ", expect_si);
1346 log("RSL ", bts_idx, ": GOT SI: ", g_system_information[bts_idx]);
1347 setverdict(fail, "received SI does not match expectations");
1348 return;
1349 }
1350}
1351
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001352/* expect to receive a RSL message matching a specified template on a given BTS / TRX */
1353function f_exp_ipa_rx(template (present) RSL_Message t_rx,
1354 BtsTrxIdx idx := {0, 0},
1355 float Tval := 2.0)
Harald Welteae026692017-12-09 01:03:01 +01001356runs on test_CT return RSL_Message {
1357 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001358 timer T := Tval;
Harald Welteae026692017-12-09 01:03:01 +01001359
1360 T.start;
1361 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001362 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Harald Welteae026692017-12-09 01:03:01 +01001363 T.stop;
1364 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001365 [] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
Harald Welteb2917702017-12-10 15:48:52 +01001366 [] T.timeout {
1367 setverdict(fail, "Timeout expecting ", t_rx);
Daniel Willmannafce8662018-07-06 23:11:32 +02001368 mtc.stop;
Harald Welteb2917702017-12-10 15:48:52 +01001369 }
Harald Welteae026692017-12-09 01:03:01 +01001370 }
1371 return rx_rsl_ud.rsl;
1372}
1373
Harald Welte21b46bd2017-12-17 19:46:32 +01001374/* helper function to transmit RSL on a given BTS/stream */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001375function f_ipa_tx(template (value) RSL_Message t_tx,
1376 BtsTrxIdx idx := {0, 0},
1377 IpaStreamId sid := IPAC_PROTO_RSL_TRX0)
Harald Welteae026692017-12-09 01:03:01 +01001378runs on test_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001379 IPA_RSL[idx.bts][idx.trx].send(ts_ASP_RSL_UD(t_tx, sid));
Harald Welteae026692017-12-09 01:03:01 +01001380}
1381
1382
Harald Welte4003d112017-12-09 22:35:39 +01001383/* verify we get a CHAN_ACT after CHAN RQD */
Harald Welteae026692017-12-09 01:03:01 +01001384testcase TC_chan_act_noreply() runs on test_CT {
1385 var BSSAP_N_UNITDATA_ind ud_ind;
Harald Welte930d0a72018-03-22 22:08:40 +01001386 var RSL_Message rsl_unused;
Harald Welte28d943e2017-11-25 15:00:50 +01001387
Harald Welte89d42e82017-12-17 16:42:41 +01001388 f_init(1);
Harald Welte28d943e2017-11-25 15:00:50 +01001389
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001390 f_ipa_tx(ts_RSL_CHAN_RQD('23'O, 23));
1391 rsl_unused := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001392 f_shutdown_helper();
Harald Welte28d943e2017-11-25 15:00:50 +01001393}
1394
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001395const CounterNameVals counternames_bts_chreq := {
1396 { "chreq:total", 0 },
1397 { "chreq:attempted_emerg", 0 },
1398 { "chreq:attempted_call", 0 },
1399 { "chreq:attempted_location_upd", 0 },
1400 { "chreq:attempted_pag", 0 },
1401 { "chreq:attempted_pdch", 0 },
1402 { "chreq:attempted_other", 0 },
1403 { "chreq:attempted_unknown", 0 },
1404 { "chreq:successful", 0 },
1405 { "chreq:successful_emerg", 0 },
1406 { "chreq:successful_call", 0 },
1407 { "chreq:successful_location_upd", 0 },
1408 { "chreq:successful_pag", 0 },
1409 { "chreq:successful_pdch", 0 },
1410 { "chreq:successful_other", 0 },
1411 { "chreq:successful_unknown", 0 },
1412 { "chreq:no_channel", 0 },
1413 { "chreq:max_delay_exceeded", 0 }
1414};
1415
1416/* verify the "chreq:*" counters */
1417private function f_chan_act_counter(OCT1 ra, charstring chreq_ctr_suffix) runs on test_CT
1418{
1419 var GsmFrameNumber fn := 23;
1420
1421 f_logp(BSCVTY, "f_chan_act_counter(" & chreq_ctr_suffix & ")");
1422
1423 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001424 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn));
1425 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001426 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1427
1428 f_ctrs_bts_add(0, "chreq:total");
1429 f_ctrs_bts_add(0, "chreq:attempted_" & chreq_ctr_suffix);
1430 f_ctrs_bts_verify();
1431
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001432 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
1433 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001434
1435 f_ctrs_bts_add(0, "chreq:successful");
1436 f_ctrs_bts_add(0, "chreq:successful_" & chreq_ctr_suffix);
1437 f_ctrs_bts_verify();
1438
1439 /* test is done, release RSL Conn Fail Ind to clean up */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001440 f_ipa_tx(ts_RSL_CONN_FAIL_IND(chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1441 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
1442 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001443 f_sleep(1.0);
1444}
1445
Harald Welte4003d112017-12-09 22:35:39 +01001446testcase TC_chan_act_counter() runs on test_CT {
1447 var BSSAP_N_UNITDATA_ind ud_ind;
1448 var integer chreq_total;
Harald Welte930d0a72018-03-22 22:08:40 +01001449 var RSL_Message rsl_unused;
Harald Welte4003d112017-12-09 22:35:39 +01001450
Harald Welte89d42e82017-12-17 16:42:41 +01001451 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001452
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001453 f_vty_allow_emerg_bts(true, 0);
1454
1455 f_ctrs_bts_init(1, counternames_bts_chreq);
1456
1457 /* emergency call: RA & 0xe0 == 0xa0 --> CHREQ_T_EMERG_CALL */
1458 f_chan_act_counter('a3'O, "emerg");
1459
1460 /* voice TCH/H: RA & 0xf0 == 0x40 --> CHREQ_T_VOICE_CALL_TCH_H */
1461 f_chan_act_counter('43'O, "call");
1462
1463 /* LU: RA & 0xf0 == 0x00 --> CHREQ_T_LOCATION_UPD */
1464 f_chan_act_counter('03'O, "location_upd");
1465
1466 /* Paging: RA & 0xf0 == 0x20 --> CHREQ_T_PAG_R_TCH_F */
1467 f_chan_act_counter('23'O, "pag");
1468 /* Paging: RA & 0xf0 == 0x30 --> CHREQ_T_PAG_R_TCH_FH */
1469 f_chan_act_counter('33'O, "pag");
1470
1471 /* LU: RA & 0xfc == 0x78 --> CHREQ_T_PDCH_TWO_PHASE */
1472 /* no PCU, so PDCH not allowed. Skip this test for now. */
1473 /* f_chan_act_counter('7b'O, "pdch"); */
1474
1475 /* LU: RA & 0xf0 == 0x10 --> CHREQ_T_SDCCH */
1476 f_chan_act_counter('13'O, "other");
Harald Welte4003d112017-12-09 22:35:39 +01001477
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001478 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001479}
1480
Harald Welteae026692017-12-09 01:03:01 +01001481/* CHAN RQD -> CHAN ACT -> CHAN ACT ACK -> RF CHAN REL */
Philipp Maier9c60a622020-07-09 15:08:46 +02001482private function f_TC_chan_act_ack_noest(OCT1 ra := '23'O) runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +01001483 var RSL_Message rx_rsl;
1484
Harald Welteae026692017-12-09 01:03:01 +01001485 /* Send CHAN RQD and wait for allocation; acknowledge it */
Philipp Maier9c60a622020-07-09 15:08:46 +02001486 var RslChannelNr chan_nr := f_chreq_act_ack(ra);
Harald Welteae026692017-12-09 01:03:01 +01001487
1488 /* expect BSC to disable the channel again if there's no RLL EST IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001489 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := T3101_MAX);
Harald Welteae026692017-12-09 01:03:01 +01001490
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001491 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001492}
1493
Philipp Maier9c60a622020-07-09 15:08:46 +02001494/* Normal variant */
1495testcase TC_chan_act_ack_noest() runs on test_CT {
Philipp Maieraf58db22020-08-12 17:24:40 +02001496 f_init(1);
Philipp Maier9c60a622020-07-09 15:08:46 +02001497 f_TC_chan_act_ack_noest();
1498}
1499
1500/* Emergency call variant */
1501testcase TC_chan_act_ack_noest_emerg() runs on test_CT {
1502 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
Philipp Maieraf58db22020-08-12 17:24:40 +02001503 f_init(1);
1504 f_vty_allow_emerg_bts(true, 0);
Philipp Maier9c60a622020-07-09 15:08:46 +02001505 f_TC_chan_act_ack_noest(ra := 'A5'O);
1506}
1507
Philipp Maier606f07d2020-08-12 17:21:58 +02001508/* Emergency call variant, but emergency calls are not allowed */
1509testcase TC_chan_rqd_emerg_deny() runs on test_CT {
1510 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
1511
1512 var RSL_Message rx_rsl;
1513 var GsmRrMessage rr;
1514
1515 f_init(1);
1516 f_vty_allow_emerg_bts(false, 0);
1517
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001518 IPA_RSL[0][0].clear;
1519 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier606f07d2020-08-12 17:21:58 +02001520
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001521 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Philipp Maier606f07d2020-08-12 17:21:58 +02001522 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
1523 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1524 setverdict(pass);
1525 } else {
1526 setverdict(fail, "immediate assignment not rejected");
1527 }
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01001528
1529 f_shutdown_helper();
Philipp Maier606f07d2020-08-12 17:21:58 +02001530}
1531
Harald Welteae026692017-12-09 01:03:01 +01001532/* Test behavior if MSC never answers to CR */
1533testcase TC_chan_act_ack_est_ind_noreply() runs on test_CT {
Harald Weltef77aef62018-01-28 15:35:42 +01001534 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
1535 var IpaStreamId sid := IPAC_PROTO_RSL_TRX0;
Harald Welteae026692017-12-09 01:03:01 +01001536 var RSL_Message rx_rsl;
Harald Weltef77aef62018-01-28 15:35:42 +01001537 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001538 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welteae026692017-12-09 01:03:01 +01001539
Harald Welte89d42e82017-12-17 16:42:41 +01001540 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001541
1542 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001543 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001544
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001545 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welteae026692017-12-09 01:03:01 +01001546
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001547 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload)));
Harald Welteae026692017-12-09 01:03:01 +01001548
1549 /* expect BSC to disable the channel again if there's no response from MSC */
Harald Weltef77aef62018-01-28 15:35:42 +01001550 /* MS waits 20s (T3210) at LU; 10s (T3230) at CM SERV REQ and 5s (T3220) AT detach */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001551 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001552 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001553}
1554
1555/* Test behavior if MSC answers with CREF to CR */
1556testcase TC_chan_act_ack_est_ind_refused() runs on test_CT {
1557 var BSSAP_N_CONNECT_ind rx_c_ind;
1558 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001559 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welteae026692017-12-09 01:03:01 +01001560
Harald Welte89d42e82017-12-17 16:42:41 +01001561 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001562
1563 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001564 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001565
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001566 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welteae026692017-12-09 01:03:01 +01001567
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001568 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Harald Welteae026692017-12-09 01:03:01 +01001569 BSSAP.send(ts_BSSAP_DISC_req(rx_c_ind.connectionId, 0));
1570
1571 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001572 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001573 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001574}
1575
Harald Welte618ef642017-12-14 14:58:20 +01001576/* CHAN RQD -> CHAN ACT -> CHAN ACT NACK -> RF CHAN REL */
1577testcase TC_chan_act_nack() runs on test_CT {
1578 var RSL_Message rx_rsl;
1579 var integer chact_nack;
1580
Harald Welte89d42e82017-12-17 16:42:41 +01001581 f_init(1);
Harald Welte618ef642017-12-14 14:58:20 +01001582
1583 chact_nack := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack");
1584
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001585 f_ipa_tx(ts_RSL_CHAN_RQD('33'O, 33));
1586 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Harald Welte618ef642017-12-14 14:58:20 +01001587 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1588
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001589 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte618ef642017-12-14 14:58:20 +01001590
1591 /* wait for some time to hope the NACK arrives before the CTRL GET below */
1592 f_sleep(0.5);
1593
1594 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack", chact_nack+1);
1595
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001596 f_shutdown_helper();
Harald Welte618ef642017-12-14 14:58:20 +01001597}
1598
Harald Welte799c97b2017-12-14 17:50:30 +01001599/* Test for channel exhaustion due to RACH overload */
1600testcase TC_chan_exhaustion() runs on test_CT {
1601 var ASP_RSL_Unitdata rsl_ud;
1602 var integer i;
1603 var integer chreq_total, chreq_nochan;
1604
Harald Welte89d42e82017-12-17 16:42:41 +01001605 f_init(1);
Harald Welte799c97b2017-12-14 17:50:30 +01001606
1607 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
1608 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
1609
Neels Hofmeyr85fa37f2021-10-06 13:50:38 +02001610 /* GSM 44.018 Table 9.1.8.2:
Pau Espin Pedrolfe200d72018-12-10 12:41:04 +01001611 * RA = '33'O -> Establishment cause = 0011xxxx (MS dual rate capable and asks for "TCH/H or TCH/F").
1612 * With current setup, expect 4xSDCCH + 4xTCH/F + 1xTCH/H to succeed */
Philipp Maiercb6cc482018-03-26 13:08:00 +02001613 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolfe200d72018-12-10 12:41:04 +01001614 var RslChannelNr chan_nr := f_chreq_act_ack('33'O, i);
Harald Welte799c97b2017-12-14 17:50:30 +01001615 }
1616
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001617 IPA_RSL[0][0].clear;
Harald Welte799c97b2017-12-14 17:50:30 +01001618
Harald Weltedd8cbf32018-01-28 12:07:52 +01001619 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001620 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
Harald Welte799c97b2017-12-14 17:50:30 +01001621
1622 /* now expect additional channel activations to fail */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001623 f_ipa_tx(ts_RSL_CHAN_RQD('42'O, 42));
Harald Welte799c97b2017-12-14 17:50:30 +01001624
1625 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001626 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV))) {
Harald Welte799c97b2017-12-14 17:50:30 +01001627 setverdict(fail, "Received CHAN ACT ACK without resources?!?");
1628 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001629 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) -> value rsl_ud {
Harald Welte799c97b2017-12-14 17:50:30 +01001630 var GsmRrMessage rr;
1631 /* match on IMM ASS REJ */
1632 rr := dec_GsmRrMessage(rsl_ud.rsl.ies[1].body.full_imm_ass_info.payload);
1633 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1634 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001635 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS+1);
Harald Welte799c97b2017-12-14 17:50:30 +01001636 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel",
1637 chreq_nochan+1);
1638 setverdict(pass);
1639 } else {
1640 repeat;
1641 }
1642 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001643 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte799c97b2017-12-14 17:50:30 +01001644 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001645 f_shutdown_helper();
Harald Welte799c97b2017-12-14 17:50:30 +01001646}
1647
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001648/* Test channel deactivation due to silence from MS */
1649testcase TC_chan_deact_silence() runs on test_CT {
1650 var RslChannelNr chan_nr;
1651
1652 f_init(1);
1653
1654 /* Request for a dedicated channel */
1655 chan_nr := f_chreq_act_ack('23'O);
1656
1657 /* Wait some time until the channel is released */
1658 f_sleep(2.0);
1659
1660 /* Expect CHANnel RELease */
1661 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001662 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001663 log("Received CHANnel RELease");
1664 setverdict(pass);
1665 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001666 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001667 /* See OS#3709, OsmoBSC should not send Immediate
1668 * Assignment Reject since a dedicated channel was
1669 * already allocated, and Immediate Assignment was
1670 * already sent. */
1671 setverdict(fail, "Unexpected Immediate Assignment!");
1672 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001673 [] IPA_RSL[0][0].receive {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001674 setverdict(fail, "Unexpected RSL message!");
1675 }
1676 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001677 f_shutdown_helper();
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001678}
1679
Harald Weltecfe2c962017-12-15 12:09:32 +01001680/***********************************************************************
1681 * Assignment Testing
1682 ***********************************************************************/
1683
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02001684/* Verify that the BSC refuses any BSSAP connection from the MSC (They are all BSC->MSC direction,
1685 * except for the inter-BSC handover, MT side) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001686testcase TC_outbound_connect(integer bssap_idx := 0) runs on test_CT {
Harald Welte89d42e82017-12-17 16:42:41 +01001687 f_init(1);
Harald Weltecfe2c962017-12-15 12:09:32 +01001688
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001689 BSSAP.send(ts_BSSAP_CONNECT_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
1690 2342, ts_BSSMAP_AssignmentReq));
Harald Weltecfe2c962017-12-15 12:09:32 +01001691 BSSAP.receive(tr_BSSAP_DISC_ind(2342, ?, ?));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001692 f_shutdown_helper();
Harald Weltecfe2c962017-12-15 12:09:32 +01001693}
1694
Harald Welte16a4adf2017-12-14 18:54:01 +01001695/* Test behavior if MSC answers with CREF to CR */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001696testcase TC_assignment_cic_only(integer bssap_idx := 0) runs on test_CT {
Harald Welte16a4adf2017-12-14 18:54:01 +01001697 var BSSAP_N_CONNECT_ind rx_c_ind;
1698 var RSL_Message rx_rsl;
1699 var DchanTuple dt;
1700
Harald Welte89d42e82017-12-17 16:42:41 +01001701 f_init(1);
Harald Welte16a4adf2017-12-14 18:54:01 +01001702
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001703 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001704 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte17b27da2018-05-25 20:33:53 +02001705 /* send assignment without AoIP IEs */
1706 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(ts_BSSMAP_IE_CIC(0, 1))));
1707 } else {
Pau Espin Pedrol35609792023-01-03 16:56:59 +01001708 /* Send assignment without CIC in IPA case */
Harald Welte17b27da2018-05-25 20:33:53 +02001709 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
1710 valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
1711 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(omit, tla)));
1712 }
Harald Welte16a4adf2017-12-14 18:54:01 +01001713 alt {
1714 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1715 setverdict(fail, "AoIP BSC cannot accept ASSIGNMENT without AoIP Transport IE");
1716 }
Harald Welte235ebf12017-12-15 14:18:16 +01001717 /* TODO: Actually expect GSM0808_CAUSE_REQ_A_IF_TYPE_NOT_SUPP */
Harald Welte16a4adf2017-12-14 18:54:01 +01001718 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1719 setverdict(pass);
1720 }
1721 [] BSSAP.receive { repeat; }
1722 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001723 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001724 f_shutdown_helper();
Harald Welte16a4adf2017-12-14 18:54:01 +01001725}
1726
Harald Welteed848512018-05-24 22:27:58 +02001727/* generate an assignment request for either AoIP or SCCPlite */
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001728function f_gen_ass_req(boolean osmux_enabled := false, integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4") return PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001729 var PDU_BSSAP ass_cmd;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001730 var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001731 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welteed848512018-05-24 22:27:58 +02001732 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001733 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001734 if (osmux_enabled) {
1735 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla, osmux_cid));
1736 } else {
1737 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla));
1738 }
Harald Welteed848512018-05-24 22:27:58 +02001739 } else {
1740 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrol096d73d2019-06-06 12:49:17 +02001741 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(cic, omit));
Harald Welteed848512018-05-24 22:27:58 +02001742 }
1743 return ass_cmd;
1744}
1745
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02001746function f_gen_handover_req(integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4",
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001747 template (value) BSSMAP_IE_CellIdentifier cell_id_source := ts_CellID_LAC_CI(1, 1),
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001748 template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit,
1749 template (omit) TestHdlrEncrParams enc := omit) return PDU_BSSAP {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001750 var PDU_BSSAP ho_req;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001751
1752 var BSSMAP_IE_EncryptionInformation encryptionInformation :=
1753 valueof(ts_BSSMAP_IE_EncrInfo('0000000000000000'O,'01'O));
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03001754 var template (omit) BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := omit;
1755 var template (omit) BSSMAP_IE_KC128 kc128 := omit;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001756 if (ispresent(enc)) {
1757 var TestHdlrEncrParams v_enc := valueof(enc);
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01001758 encryptionInformation := valueof(ts_BSSMAP_IE_EncrInfo(v_enc.enc_key, v_enc.enc_alg_permitted));
1759 if (ispresent(v_enc.enc_alg_chosen)) {
1760 chosenEncryptionAlgorithm := valueof(
1761 ts_BSSMAP_IE_ChosenEncryptionAlgorithm(int2oct(enum2int(
1762 f_cipher_mode_bssmap_to_rsl(v_enc.enc_alg_chosen)), 1)));
1763 }
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001764 if (ispresent(v_enc.enc_kc128)) {
1765 kc128 := ts_BSSMAP_IE_Kc128(v_enc.enc_kc128);
1766 }
1767 }
1768
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001769 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001770 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001771 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001772 ho_req := valueof(ts_BSSMAP_HandoverRequest(omit, tla,
1773 cell_id_source := cell_id_source,
1774 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001775 encryptionInformation := encryptionInformation,
1776 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
Neels Hofmeyr9fe13202022-03-04 00:05:43 +01001777 kC128 := kc128,
1778 /* on AoIP, allow "all" codecs (until we add more concise
1779 * tests) */
1780 codecList := ts_BSSMAP_IE_CodecList(
1781 {ts_CodecAMR_F, ts_CodecAMR_H,
1782 ts_CodecEFR, ts_CodecFR, ts_CodecHR})));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001783 } else {
1784 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001785 ho_req := valueof(ts_BSSMAP_HandoverRequest(cic, omit,
1786 cell_id_source := cell_id_source,
1787 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001788 encryptionInformation := encryptionInformation,
1789 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
1790 kC128 := kc128));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001791 }
1792 return ho_req;
1793}
1794
Harald Welteed848512018-05-24 22:27:58 +02001795/* generate an assignment complete template for either AoIP or SCCPlite */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001796function f_gen_exp_compl(integer bssap_idx := 0)
1797runs on MSC_ConnHdlr return template PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001798 var template PDU_BSSAP exp_compl;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001799 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001800 var template BSSMAP_IE_Osmo_OsmuxCID exp_osmux_cid := omit;
1801 if (g_pars.use_osmux_cn) {
1802 var template (present) INT1 exp_cid := ?;
1803 if (isbound(g_media.mgcp_conn[0].local_osmux_cid) and isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1804 exp_cid := (g_media.mgcp_conn[0].local_osmux_cid, g_media.mgcp_conn[1].local_osmux_cid);
1805 } else if (isbound(g_media.mgcp_conn[0].local_osmux_cid)) {
1806 exp_cid := g_media.mgcp_conn[0].local_osmux_cid;
1807 } else if (isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1808 exp_cid := g_media.mgcp_conn[1].local_osmux_cid;
1809 }
1810 exp_osmux_cid := tr_OsmuxCID(exp_cid);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001811 }
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001812 exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, exp_osmux_cid);
Harald Welteed848512018-05-24 22:27:58 +02001813 } else {
1814 /* CIC is optional "*" as the MSC allocated it */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001815 exp_compl := tr_BSSMAP_AssignmentComplete(*, omit, omit);
Harald Welteed848512018-05-24 22:27:58 +02001816 }
1817 return exp_compl;
1818}
1819
Harald Welte235ebf12017-12-15 14:18:16 +01001820/* Run everything required up to sending a caller-specified assignment command and expect response */
1821function f_assignment_exp(PDU_BSSAP ass_cmd, template PDU_BSSAP exp, charstring fail_text)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001822runs on test_CT return DchanTuple {
Harald Welte235ebf12017-12-15 14:18:16 +01001823 var BSSAP_N_CONNECT_ind rx_c_ind;
1824 var RSL_Message rx_rsl;
1825 var DchanTuple dt;
1826
Harald Welte89d42e82017-12-17 16:42:41 +01001827 f_init(1);
Harald Welte235ebf12017-12-15 14:18:16 +01001828
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001829 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte235ebf12017-12-15 14:18:16 +01001830 /* send assignment without AoIP IEs */
1831 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
1832 alt {
1833 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1834 if (ischosen(exp.pdu.bssmap.assignmentComplete)) {
1835 setverdict(pass);
1836 } else {
1837 setverdict(fail, fail_text);
1838 }
1839 }
1840 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1841 if (ischosen(exp.pdu.bssmap.assignmentFailure)) {
1842 setverdict(pass);
1843 } else {
1844 setverdict(fail, fail_text);
1845 }
1846 }
1847 [] BSSAP.receive { repeat; }
1848 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001849 return dt;
Harald Welte235ebf12017-12-15 14:18:16 +01001850}
Oliver Smithdd002752023-02-21 13:35:00 +01001851
Oliver Smithcb617912023-04-18 11:29:10 +02001852private function f_tc_assignment_csd(charstring data_rate_str, OCT1 data_rate) runs on MSC_ConnHdlr {
Oliver Smithdd002752023-02-21 13:35:00 +01001853 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welteed848512018-05-24 22:27:58 +02001854 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Oliver Smithbc392a82023-04-17 14:06:42 +02001855 var SDP_FIELD_PayloadType pt_csd := PT_CSD;
Oliver Smithdd002752023-02-21 13:35:00 +01001856
Harald Welte235ebf12017-12-15 14:18:16 +01001857 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smithdd002752023-02-21 13:35:00 +01001858 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecCSData}));
1859
Oliver 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();
1873}
Oliver Smithcb617912023-04-18 11:29:10 +02001874private function f_tc_assignment_csd_all(charstring id) runs on MSC_ConnHdlr {
1875 /* Data rates that require multi-slot HSCSD assignment are not tested
1876 * on purpuse (not supported): T_32k0, T_28k8 */
1877 f_tc_assignment_csd("T_14k4", GSM0808_DATA_RATE_TRANSP_14k4);
1878 f_tc_assignment_csd("T_9k6", GSM0808_DATA_RATE_TRANSP_9k6);
1879 f_tc_assignment_csd("T_4k8", GSM0808_DATA_RATE_TRANSP_4k8);
1880 f_tc_assignment_csd("T_2k4", GSM0808_DATA_RATE_TRANSP_2k4);
1881 f_tc_assignment_csd("T_1k2", GSM0808_DATA_RATE_TRANSP_1k2);
1882 f_tc_assignment_csd("T_600", GSM0808_DATA_RATE_TRANSP_600);
1883 f_tc_assignment_csd("T_1200_75", GSM0808_DATA_RATE_TRANSP_1200_75);
1884}
Oliver Smithdd002752023-02-21 13:35:00 +01001885testcase TC_assignment_csd() runs on test_CT {
1886 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.10.0 */
1887 var MSC_ConnHdlr vc_conn;
1888 var TestHdlrParams pars := f_gen_test_hdlr_pars();
1889 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
1890
Oliver Smithcb617912023-04-18 11:29:10 +02001891 f_init(1, true, guard_timeout := 90.0);
Oliver Smithdd002752023-02-21 13:35:00 +01001892 f_sleep(1.0);
Oliver Smithcb617912023-04-18 11:29:10 +02001893 vc_conn := f_start_handler(refers(f_tc_assignment_csd_all), pars);
Oliver Smithdd002752023-02-21 13:35:00 +01001894 vc_conn.done;
1895 } else {
1896 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
1897 var PDU_BSSAP ass_cmd := f_gen_ass_req();
1898 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
1899 //exp_fail.pdu.bssmap.assignmentFailure.cause.causeValue := int2bit(enum2int(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL), 7);
1900 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for CSD");
1901 f_perform_clear_test_ct(dt);
1902 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001903 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001904}
1905
1906testcase TC_assignment_ctm() runs on test_CT {
1907 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001908 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001909 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
1910 //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 +01001911 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
1912 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001913 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001914}
1915
Harald Welte4003d112017-12-09 22:35:39 +01001916type record DchanTuple {
1917 integer sccp_conn_id,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001918 RslChannelNr rsl_chan_nr,
1919 BtsTrxIdx idx
Harald Weltea5d2ab22017-12-09 14:21:42 +01001920}
1921
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +02001922type record of DchanTuple DchanTuples;
1923
Harald Welted6939652017-12-13 21:02:46 +01001924/* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001925private function f_chreq_act_ack(OCT1 ra := '23'O,
1926 GsmFrameNumber fn := 23,
1927 BtsTrxIdx idx := {0, 0})
Harald Welted6939652017-12-13 21:02:46 +01001928runs on test_CT return RslChannelNr {
1929 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001930 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
1931 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Harald Welted6939652017-12-13 21:02:46 +01001932 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001933 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10), idx);
1934 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Harald Welted6939652017-12-13 21:02:46 +01001935 return chan_nr;
1936}
1937
Harald Welte4003d112017-12-09 22:35:39 +01001938/* helper function to establish a dedicated channel via BTS and MSC */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001939function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1940 BtsTrxIdx idx := {0, 0})
Harald Welte4003d112017-12-09 22:35:39 +01001941runs on test_CT return DchanTuple {
1942 var BSSAP_N_CONNECT_ind rx_c_ind;
Harald Welte4003d112017-12-09 22:35:39 +01001943 var DchanTuple dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001944
Harald Welte4003d112017-12-09 22:35:39 +01001945 /* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001946 dt.rsl_chan_nr := f_chreq_act_ack(ra, fn, idx);
Harald Welte4003d112017-12-09 22:35:39 +01001947
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001948 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 +01001949
1950 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1951 dt.sccp_conn_id := rx_c_ind.connectionId;
1952 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1953
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001954 dt.idx := idx;
Harald Welte4003d112017-12-09 22:35:39 +01001955 return dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001956}
1957
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001958/* 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 +06001959function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1960 BtsTrxIdx idx := {0, 0})
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001961runs on test_CT return DchanTuple {
1962 var BSSAP_N_CONNECT_ind rx_c_ind;
1963 var DchanTuple dt;
1964
1965 /* Send CHAN RQD */
1966 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001967 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001968
1969 /* The dyn TS first deactivates PDCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001970 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 +02001971 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001972 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001973
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001974 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001975 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1976
1977 /* Now activates the signalling channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001978 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10), idx);
1979 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001980
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001981 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 +02001982
1983 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1984 dt.sccp_conn_id := rx_c_ind.connectionId;
1985 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1986
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001987 dt.idx := idx;
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001988 return dt;
1989}
1990
Harald Welte641fcbe2018-06-14 10:58:35 +02001991/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001992private function f_exp_chan_rel_and_clear(DchanTuple dt)
1993runs on test_CT {
Harald Welte641fcbe2018-06-14 10:58:35 +02001994 var RSL_Message rx_rsl;
1995 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001996 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 +02001997 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001998 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), dt.idx);
Harald Welte641fcbe2018-06-14 10:58:35 +02001999
2000 /* expect Clear Complete from BSC */
2001 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2002
2003 /* MSC disconnects as instructed. */
2004 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2005}
2006
Harald Welte4003d112017-12-09 22:35:39 +01002007/* Test behavior of channel release after unilateral RLL REL IND (DISC from MS) */
2008testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002009 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002010 var DchanTuple dt;
Harald Welte96c94412017-12-09 03:12:45 +01002011
Harald Welte89d42e82017-12-17 16:42:41 +01002012 f_init(1);
Harald Welte96c94412017-12-09 03:12:45 +01002013
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002014 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002015
2016 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002017 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Harald Welte4003d112017-12-09 22:35:39 +01002018
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002019 /* expect Clear Request on MSC side */
2020 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2021
2022 /* Instruct BSC to clear channel */
2023 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2024 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2025
Harald Welte4003d112017-12-09 22:35:39 +01002026 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002027 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002028
2029 /* wait for SCCP emulation to do its job */
2030 f_sleep(1.0);
Harald Welte4003d112017-12-09 22:35:39 +01002031
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002032 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002033}
2034
2035/* Test behavior of channel release after CONN FAIL IND from BTS */
2036testcase TC_chan_rel_conn_fail() runs on test_CT {
2037 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002038 var DchanTuple dt;
2039
Harald Welte89d42e82017-12-17 16:42:41 +01002040 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002041
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002042 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002043
Vadim Yanitskiy01d0a902022-12-14 22:41:42 +07002044 /* Sending CONN FAIL IND immediately may trigger a race condition.
2045 * Give the BSC some time to process a new SCCP connection (OS#5823). */
2046 f_sleep(0.2);
2047
Harald Welte4003d112017-12-09 22:35:39 +01002048 /* simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002049 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte4003d112017-12-09 22:35:39 +01002050 /* TODO: different cause values? */
2051
Harald Welte4003d112017-12-09 22:35:39 +01002052 /* expect Clear Request from BSC */
2053 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2054
2055 /* Instruct BSC to clear channel */
2056 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2057 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2058
Harald Welte6ff76ea2018-01-28 13:08:01 +01002059 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002060 f_exp_chan_rel_and_clear(dt);
Harald Welte4003d112017-12-09 22:35:39 +01002061
2062 /* wait for SCCP emulation to do its job */
2063 f_sleep(1.0);
2064
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002065 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002066}
2067
Harald Welte99f3ca02018-06-14 13:40:29 +02002068/* Test behavior of early CONN FAIL IND from BTS (before EST IND!) */
2069/* See also https://www.osmocom.org/issues/3182 */
2070testcase TC_early_conn_fail() runs on test_CT {
2071 var RSL_Message rx_rsl;
2072 var DchanTuple dt;
2073
2074 f_init(1);
2075
2076 /* BTS->BSC: Send CHAN RQD and wait for allocation; acknowledge it */
Harald Weltec46ea3c2020-10-10 18:46:12 +02002077 dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_ra_cs(), 23);
Harald Welte99f3ca02018-06-14 13:40:29 +02002078
2079 /* BTS->BSC: simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002080 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002081
2082 /* BTS->BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002083 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002084
2085 /* BTS<-BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002086 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002087
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002088 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002089}
2090
2091/* Test behavior of late CONN FAIL IND from BTS (ater REL IND!) */
2092/* See also https://www.osmocom.org/issues/3182 */
2093testcase TC_late_conn_fail() runs on test_CT {
2094 var RSL_Message rx_rsl;
2095 var DchanTuple dt;
2096
2097 f_init(1);
2098
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002099 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99f3ca02018-06-14 13:40:29 +02002100
2101 /* BSC<-MSC: Instruct BSC to clear connection */
2102 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(0)));
2103
2104 /* BTS->BSC: expect BSC to deactivate SACCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002105 rx_rsl := f_exp_ipa_rx(tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002106
2107 /* BTS->BSC: simulate a late CONN FAIL IND from BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002108 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002109
2110 /* BTS<-BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002111 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002112 /* BTS->BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002113 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002114
2115 /* BSC->MSC: expect Clear Complete from BSC */
2116 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2117
2118 /* BSC<-MSC: MSC disconnects as requested. */
2119 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2120
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002121 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002122}
2123
Oliver Smithaf03bef2021-08-24 15:34:51 +02002124private function f_TC_stats_conn_fail(charstring id) runs on MSC_ConnHdlr {
2125 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
2126 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2127
2128 f_statsd_reset();
2129
Oliver Smith15890b42023-03-08 14:12:28 +01002130 /* Establish SDCCH (invalid DataIndicator for exp_fail) */
Oliver Smithaf03bef2021-08-24 15:34:51 +02002131 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smith15890b42023-03-08 14:12:28 +01002132 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := 'ff'O;
Oliver Smithaf03bef2021-08-24 15:34:51 +02002133 f_establish_fully(ass_cmd, exp_fail);
2134
2135 /* Expect stats to be 0 */
2136 var StatsDExpects expect := {
2137 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
2138 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
2139 };
2140 f_statsd_expect(expect);
2141
2142 /* Simulate CONN FAIL IND on SDCCH */
2143 RSL.send(ts_ASP_RSL_UD(
2144 ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
2145 IPAC_PROTO_RSL_TRX0));
2146
Neels Hofmeyr58be48a2021-09-07 18:39:21 +02002147 f_sleep(1.0);
2148
Oliver Smithaf03bef2021-08-24 15:34:51 +02002149 /* Expect stats to be 1 */
2150 expect := {
2151 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
2152 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
2153 };
2154 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002155 BSSAP.receive(tr_BSSMAP_ClearRequest);
2156 f_perform_clear();
Oliver Smithaf03bef2021-08-24 15:34:51 +02002157}
2158testcase TC_stats_conn_fail() runs on test_CT {
2159 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2160 var MSC_ConnHdlr vc_conn;
2161
2162 f_init(1, true);
2163 f_sleep(1.0);
2164
2165 vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
2166 vc_conn.done;
2167
2168 f_shutdown_helper();
2169}
2170
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002171function f_expect_chan_rel(RslChannelNr rsl_chan_nr,
2172 BtsTrxIdx idx := {0, 0},
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002173 boolean expect_deact_sacch := true,
2174 boolean expect_rr_chan_rel := true,
2175 boolean expect_rll_rel_req := true,
Harald Welte99787102019-02-04 10:41:36 +01002176 boolean handle_rll_rel := true,
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002177 template CellSelIndValue expect_cells := omit,
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002178 template (present) RR_Cause expect_rr_cause := ?
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002179 ) runs on test_CT {
Harald Welte91d54a52018-01-28 15:35:07 +01002180
2181 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002182 var boolean got_deact_sacch := false;
2183 var boolean got_rr_chan_rel := false;
2184 var boolean got_rll_rel_req := false;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002185 var ASP_RSL_Unitdata ud;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002186 var RSL_IE_Body l3_ie;
2187 var PDU_ML3_NW_MS l3;
2188 var RR_Cause got_cause;
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002189 log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
2190 " expect_rll_rel_req=", expect_rll_rel_req);
Harald Welte91d54a52018-01-28 15:35:07 +01002191 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002192 [] 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 +01002193 got_deact_sacch := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002194 repeat;
2195 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002196 [] 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 +01002197 got_rr_chan_rel := true;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002198
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002199 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2200 setverdict(fail, "cannot find L3");
2201 mtc.stop;
2202 }
2203 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2204
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002205 if (not istemplatekind(expect_cells, "omit")) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002206 var CellSelIndValue cells := dec_CellSelIndValue(
2207 l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
2208
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002209 log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
2210 if (match(cells, expect_cells)) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002211 setverdict(pass);
2212 } else {
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002213 log("EXPECTED CELLS: ", expect_cells);
2214 setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002215 }
2216 }
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002217
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002218 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2219 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2220 if (match(got_cause, expect_rr_cause)) {
2221 setverdict(pass);
2222 } else {
2223 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2224 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002225 }
Harald Welte99787102019-02-04 10:41:36 +01002226 repeat;
2227 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002228 [] 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 +01002229 got_rll_rel_req := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002230 /* FIXME: Why are we getting this for LinkID SACCH? */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002231 if (handle_rll_rel) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002232 f_ipa_tx(ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002233 }
Harald Welte91d54a52018-01-28 15:35:07 +01002234 repeat;
2235 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002236 [] 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 +01002237 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002238 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
Harald Welte91d54a52018-01-28 15:35:07 +01002239 }
2240 /* ignore any user data */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002241 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002242 repeat;
2243 }
2244 }
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002245
2246 log("f_expect_chan_rel() summary: got_deact_sacch=", got_deact_sacch, " got_rr_chan_rel=", got_rr_chan_rel,
2247 " got_rll_rel_req=", got_rll_rel_req);
2248
2249 if (expect_deact_sacch != got_deact_sacch) {
2250 setverdict(fail, "f_expect_chan_rel(): expect_deact_sacch=", expect_deact_sacch, " got_deact_sacch=", got_deact_sacch);
2251 }
2252 if (expect_rr_chan_rel != got_rr_chan_rel) {
2253 setverdict(fail, "f_expect_chan_rel(): expect_rr_chan_rel=", expect_rr_chan_rel, " got_rr_chan_rel=", got_rr_chan_rel);
2254 }
2255 if (expect_rll_rel_req != got_rll_rel_req) {
2256 setverdict(fail, "f_expect_chan_rel(): expect_rll_rel_req=", expect_rll_rel_req, " got_rll_rel_req=", got_rll_rel_req);
2257 }
Harald Welte91d54a52018-01-28 15:35:07 +01002258}
2259
Harald Welte4003d112017-12-09 22:35:39 +01002260/* Test behavior of channel release after hard Clear Command from MSC */
2261testcase TC_chan_rel_hard_clear() runs on test_CT {
2262 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002263 var DchanTuple dt;
Harald Welte4003d112017-12-09 22:35:39 +01002264
Harald Welte89d42e82017-12-17 16:42:41 +01002265 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002266
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002267 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002268
2269 /* Instruct BSC to clear channel */
2270 var BssmapCause cause := 0;
2271 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2272
2273 /* expect Clear Complete from BSC on A */
2274 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2275 /* release the SCCP connection */
2276 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2277 }
2278
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002279 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002280 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002281}
2282
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002283function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
2284 var BSSAP_N_DATA_ind rx_di;
2285 var DchanTuple dt;
2286
2287 f_init(1);
2288
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002289 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002290 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2291 /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
2292 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
2293
2294 /* Instruct BSC to clear channel */
2295 var BssmapCause cause := 0;
2296 if (tx_csfb_ind) {
2297 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2298 } else {
2299 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2300 }
2301
2302 /* expect Clear Complete from BSC on A */
2303 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2304 /* release the SCCP connection */
2305 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2306 }
2307
2308 /* 1 neighbor is added by default in osmo-bts.cfg and
2309 SystemInformationConfig_default, use that: */
2310 var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
2311
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002312 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 +02002313 f_shutdown_helper();
2314}
2315
2316/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
2317 from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
2318 PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2319 EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
2320 Indicator or not shouldn't matter at all. */
2321testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
2322 f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
2323}
2324
2325/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
2326 MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
2327 Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2328 EUTRAN neighbor list sent later on by BSC in RR Channel. */
2329testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
2330 f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
2331}
2332
2333/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
2334 MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
2335 Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
2336 CSFB Indicator should not be used anymore, and hence, there should be no
2337 EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
2338 Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
Harald Welte99787102019-02-04 10:41:36 +01002339testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
2340 var BSSAP_N_DATA_ind rx_di;
2341 var DchanTuple dt;
2342
2343 f_init(1);
2344
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002345 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99787102019-02-04 10:41:36 +01002346
2347 /* Instruct BSC to clear channel */
2348 var BssmapCause cause := 0;
2349 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2350
2351 /* expect Clear Complete from BSC on A */
2352 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2353 /* release the SCCP connection */
2354 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2355 }
2356
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002357 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002358 f_shutdown_helper();
Harald Welte99787102019-02-04 10:41:36 +01002359}
2360
Harald Welted8c36cd2017-12-09 23:05:31 +01002361/* Test behavior of channel release after hard RLSD from MSC */
2362testcase TC_chan_rel_hard_rlsd() runs on test_CT {
Harald Welted8c36cd2017-12-09 23:05:31 +01002363 var DchanTuple dt;
Harald Welted8c36cd2017-12-09 23:05:31 +01002364
Harald Welte89d42e82017-12-17 16:42:41 +01002365 f_init(1);
Harald Welted8c36cd2017-12-09 23:05:31 +01002366
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002367 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welted8c36cd2017-12-09 23:05:31 +01002368
2369 /* release the SCCP connection */
2370 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2371
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002372 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002373 f_shutdown_helper();
Harald Welted8c36cd2017-12-09 23:05:31 +01002374}
2375
Harald Welte550daf92018-06-11 19:22:13 +02002376/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
2377testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
2378 var DchanTuple dt;
2379
2380 f_init(1);
2381
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002382 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte550daf92018-06-11 19:22:13 +02002383
2384 /* release the SCCP connection */
2385 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2386
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002387 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002388 f_shutdown_helper();
Harald Welte550daf92018-06-11 19:22:13 +02002389}
2390
Harald Welte85804d42017-12-10 14:11:58 +01002391/* Test behavior of channel release after BSSMAP RESET from MSC */
2392testcase TC_chan_rel_a_reset() runs on test_CT {
Harald Welte85804d42017-12-10 14:11:58 +01002393 var DchanTuple dt;
Harald Welte85804d42017-12-10 14:11:58 +01002394
Harald Welte89d42e82017-12-17 16:42:41 +01002395 f_init(1);
Harald Welte85804d42017-12-10 14:11:58 +01002396
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002397 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte85804d42017-12-10 14:11:58 +01002398
2399 /* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002400 IPA_RSL[0][0].clear;
Harald Welte85804d42017-12-10 14:11:58 +01002401
2402 /* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002403 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 +01002404 interleave {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002405 [] 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 +01002406 [] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
2407 }
2408
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002409 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002410 f_shutdown_helper();
Harald Welte85804d42017-12-10 14:11:58 +01002411}
2412
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002413/* Verify T(iar) triggers and releases the channel */
2414testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
2415 var DchanTuple dt;
2416
2417 /* Set T(iar) in BSC low enough that it will trigger before other side
2418 has time to keep alive with a T(ias). Keep recommended ratio of
2419 T(iar) >= T(ias)*2 */
2420 g_bsc_sccp_timer_ias := 2;
2421 g_bsc_sccp_timer_iar := 5;
2422
2423 f_init(1);
2424
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002425 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002426 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002427 f_shutdown_helper();
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002428}
2429
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002430private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause,
2431 template (present) RR_Cause expect_rr_cause)
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002432runs on test_CT
2433{
2434 var DchanTuple dt;
2435
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002436 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002437 var BssmapCause cause := 0;
2438 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
2439 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2440 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2441 }
2442
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002443 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 +02002444}
2445
2446/* Test that Clear Command cause codes affect the RR Channel Release cause code */
2447testcase TC_chan_rel_rr_cause() runs on test_CT {
2448 f_init(1);
2449
2450 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
2451 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
2452 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
2453 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
2454 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
2455 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
Vadim Yanitskiye18aebb2021-01-03 13:10:43 +01002456
2457 f_shutdown_helper();
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002458}
2459
Harald Welte5cd20ed2017-12-13 21:03:20 +01002460/* Test behavior if RSL EST IND for non-active channel */
2461testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
2462 timer T := 2.0;
2463
Harald Welte89d42e82017-12-17 16:42:41 +01002464 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002465
Harald Welte5cd20ed2017-12-13 21:03:20 +01002466 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002467 var octetstring l3_payload := gen_l3_valid_payload();
2468 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002469
2470 T.start;
2471 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002472 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002473 setverdict(fail, "MSC received COMPL L3 for non-active lchan");
2474 }
2475 [] BSSAP.receive {}
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002476 [] IPA_RSL[0][0].receive {}
Harald Welte5cd20ed2017-12-13 21:03:20 +01002477 [] T.timeout {}
2478 }
2479
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002480 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002481}
2482
2483/* Test behavior if RSL EST IND for invalid SAPI */
2484testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
2485 var RslChannelNr chan_nr;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002486 var octetstring l3_payload;
Harald Welte5cd20ed2017-12-13 21:03:20 +01002487
Harald Welte89d42e82017-12-17 16:42:41 +01002488 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002489
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002490 chan_nr := f_chreq_act_ack();
2491 l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002492
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002493 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002494
2495 timer T := 2.0;
2496 T.start;
2497 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002498 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002499 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
2500 }
2501 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002502 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002503 [] T.timeout {}
2504 }
2505
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002506 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002507}
2508
2509/* Test behavior if RSL EST IND for invalid SAPI */
2510testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
2511 timer T := 2.0;
2512
Harald Welte89d42e82017-12-17 16:42:41 +01002513 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002514
2515 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002516 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002517
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002518 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002519
2520 T.start;
2521 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002522 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002523 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
2524 }
2525 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002526 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002527 [] T.timeout {}
2528 }
2529
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002530 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002531}
2532
2533/* Test behavior if RSL EST IND for invalid SACCH */
2534testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
2535 timer T := 2.0;
2536
Harald Welte89d42e82017-12-17 16:42:41 +01002537 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002538
2539 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002540 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002541
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002542 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002543
2544 T.start;
2545 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002546 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002547 setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
2548 }
2549 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002550 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002551 [] T.timeout {}
2552 }
2553
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002554 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002555}
2556
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002557/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
2558private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
2559 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
2560 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2561
2562 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
2563 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
2564
2565 f_establish_fully(ass_cmd, exp_compl);
2566
2567 /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
2568 RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
2569 /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
2570 BSSAP.receive(PDU_BSSAP:{
2571 discriminator := '1'B,
2572 spare := '0000000'B,
2573 dlci := 'C3'O,
2574 lengthIndicator := ?,
2575 pdu := { dtap := '0904'O }
2576 });
2577
2578 /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
2579 for (var integer i := 0; i < 32; i := i + 1) {
2580 var octetstring l3 := '09'O & f_rnd_octstring(14);
2581 var template (value) RslLinkId link_id;
2582 var template (value) OCT1 dlci;
2583
2584 if (i mod 2 == 0) {
2585 /* SAPI0 on FACCH or SDCCH */
2586 link_id := ts_RslLinkID_DCCH(0);
2587 dlci := '80'O;
2588 } else {
2589 /* SAPI3 on SACCH */
2590 link_id := ts_RslLinkID_SACCH(3);
2591 dlci := 'C3'O;
2592 }
2593
2594 /* Send MO message: RSL -> BSSAP */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002595 f_mo_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002596 /* Send MT message: BSSAP -> RSL */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002597 f_mt_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002598 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002599 f_perform_clear();
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002600}
2601testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
2602 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2603 var MSC_ConnHdlr vc_conn;
2604
2605 f_init(1, true);
2606 f_sleep(1.0);
2607
2608 vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
2609 vc_conn.done;
2610
2611 f_shutdown_helper();
2612}
2613
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002614private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002615 template (present) myBSSMAP_Cause cause := ?,
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002616 template (present) BIT2 cc := ?,
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002617 float T_val := 2.0)
2618runs on test_CT {
2619 var BSSAP_N_DATA_ind rx_di;
2620 timer T;
2621
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002622 var template (present) BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
2623 var template (present) PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002624
2625 T.start(T_val);
2626 alt {
2627 [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
2628 var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
2629 if (not match(rx_cause, tr_cause)) {
2630 setverdict(fail, "Rx unexpected Cause IE: ",
2631 rx_cause, " vs expected ", tr_cause);
2632 }
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002633
2634 /* Who ever on the earth decided to define this field as two separate bits?!? */
2635 var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
2636 & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
2637 if (not match(rx_cc, cc)) {
2638 setverdict(fail, "Rx unexpected Control Channel type: ",
2639 rx_cc, " vs expected ", cc);
2640 }
2641
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002642 setverdict(pass);
2643 }
2644 [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
2645 setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
2646 }
2647 [] T.timeout {
2648 setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
2649 }
2650 }
2651}
2652
2653/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
2654testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002655 var RSL_Message rx_rsl;
2656 var DchanTuple dt;
2657
2658 f_init(1);
2659
2660 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002661 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002662
2663 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002664 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 +07002665 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002666 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 +07002667
2668 /* MS sends unexpected RELease INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002669 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002670 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2671 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
2672
2673 /* Clean up the connection */
2674 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002675 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002676
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002677 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002678}
2679
2680/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
2681testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002682 var RSL_Message rx_rsl;
2683 var DchanTuple dt;
2684
2685 f_init(1);
2686
2687 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002688 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002689
2690 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002691 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 +07002692 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002693 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 +07002694
2695 /* BTS sends unexpected ERROR INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002696 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002697 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2698 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
2699
2700 /* Clean up the connection */
2701 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002702 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002703
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002704 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002705}
2706
2707/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
2708testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002709 var RSL_Message rx_rsl;
2710 var DchanTuple dt;
2711
2712 f_init(1);
2713
2714 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002715 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002716
2717 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002718 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 +07002719 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002720 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 +07002721
2722 /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
2723 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
2724
2725 /* Clean up the connection */
2726 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002727 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002728
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002729 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002730}
2731
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002732/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
2733testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002734 var RSL_Message rx_rsl;
2735 var DchanTuple dt;
2736
2737 f_init(1);
2738
2739 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002740 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002741
2742 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002743 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 +07002744 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002745 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 +07002746
2747 /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002748 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Pau Espin Pedrol121f27f2022-01-12 12:02:10 +01002749 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, '10'B);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002750
2751 /* Clean up the connection */
2752 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002753 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002754
2755 f_shutdown_helper();
2756}
2757
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002758testcase TC_si_default() runs on test_CT {
2759 f_init(0);
2760 f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002761 f_shutdown_helper();
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002762}
Harald Welte4003d112017-12-09 22:35:39 +01002763
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002764/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
2765 * the entire value range. This function provides the same EARFCN numbers for the same earfcn_index */
2766private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uint16_t
2767{
2768 select (earfcn_index) {
2769 case (0) {
2770 /* E-ARFCN 111 is already added in the osmo-bsc.cfg */
2771 return 111;
2772 }
2773 case (1) {
2774 return 1;
2775 }
2776 case (2) {
2777 return 0;
2778 }
2779 case (3) {
2780 return 65535;
2781 }
2782 case else {
2783 return 23 * (earfcn_index - 3);
2784 }
2785 }
2786}
2787
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002788function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
2789 template CellSelIndValue expect_cells := omit) runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002790
2791 f_init(0);
2792
2793 /* E-ARFCN 111 is already added in the osmo-bsc.cfg, so only add more arfcns if total_earfcns > 1 */
2794 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002795 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2796 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002797 }
2798
2799 f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
2800
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002801 if (not istemplatekind(expect_cells, "omit")) {
2802 /* Also check that RR Channel Release contains these EARFCNs.
2803 * (copied code from TC_chan_rel_hard_clear_csfb) */
2804 var BSSAP_N_DATA_ind rx_di;
2805 var DchanTuple dt;
2806
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002807 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrold0046312021-04-19 16:35:58 +02002808 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2809 * yet when generating the EUTRAN neigh list in RR CHannel Release) */
2810 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002811
2812 /* Instruct BSC to clear channel */
2813 var BssmapCause cause := 0;
2814 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2815
2816 /* expect Clear Complete from BSC on A */
2817 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2818 /* release the SCCP connection */
2819 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2820 }
2821
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002822 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := expect_cells);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002823 }
2824
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002825 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002826 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 +02002827 }
2828}
2829
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002830private function f_tr_si2quater_earfcns(integer count) return template SI2quaterRestOctetsList
2831{
2832 var template SI2quaterRestOctetsList si2quater := {};
2833 var integer si2quater_count := (count + 2) / 3;
2834
2835 for (var integer i := 0; i < count; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002836 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002837 var integer index := i / 3;
2838 var integer earfcn_index := i mod 3;
2839 if (index >= lengthof(si2quater)) {
2840 si2quater[index] := tr_SI2quaterRestOctets_EUTRAN(index := index, count := si2quater_count - 1);
2841 }
2842 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);
2843 }
2844
2845 return si2quater;
2846}
2847
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002848private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
2849{
2850 var template CellSelIndValue_EUTRAN_Descrs cells := {};
2851
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002852 /* the lte neighbors must match the config & vty to pass this test */
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002853 for (var integer i := 0; i < count; i := i + 1) {
2854 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002855 cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002856 }
2857
2858 return tr_CellSelIndValue_EUTRAN(cells);
2859}
2860
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002861private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
2862{
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002863 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrol8ab62e42020-12-18 16:19:11 +01002864 sic.si2quater := f_tr_si2quater_earfcns(n);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002865 var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
2866 f_test_si2quater(n, sic, cells);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002867}
2868
2869testcase TC_si2quater_2_earfcns() runs on test_CT {
2870 f_tc_si2quater_n_earfcns(2);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002871 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002872}
2873
2874testcase TC_si2quater_3_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002875 f_tc_si2quater_n_earfcns(3);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002876 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002877}
2878
2879testcase TC_si2quater_4_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002880 f_tc_si2quater_n_earfcns(4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002881 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002882}
2883
2884testcase TC_si2quater_5_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002885 f_tc_si2quater_n_earfcns(5);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002886 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002887}
2888
2889testcase TC_si2quater_6_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002890 f_tc_si2quater_n_earfcns(6);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002891 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002892}
2893
2894testcase TC_si2quater_12_earfcns() runs on test_CT {
2895 f_tc_si2quater_n_earfcns(12);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002896 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002897}
2898
2899testcase TC_si2quater_23_earfcns() runs on test_CT {
2900 f_tc_si2quater_n_earfcns(23);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002901 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002902}
2903
2904testcase TC_si2quater_32_earfcns() runs on test_CT {
2905 f_tc_si2quater_n_earfcns(32);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002906 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002907}
2908
2909testcase TC_si2quater_33_earfcns() runs on test_CT {
2910 f_tc_si2quater_n_earfcns(33);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002911 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002912}
2913
2914testcase TC_si2quater_42_earfcns() runs on test_CT {
2915 f_tc_si2quater_n_earfcns(42);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002916 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002917}
2918
2919testcase TC_si2quater_48_earfcns() runs on test_CT {
2920 f_tc_si2quater_n_earfcns(48);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002921 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002922}
2923
2924/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
2925 * 48 EARFCNs. */
2926testcase TC_si2quater_49_earfcns() runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002927 var template SystemInformationConfig sic := SystemInformationConfig_default;
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002928 sic.si2quater := f_tr_si2quater_earfcns(48); /* 48, not 49! */
2929 f_init(0);
2930
2931 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002932 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2933 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002934 }
2935
2936 /* The 49th EARFCN no longer fits, expect VTY error */
2937 f_vty_enter_cfg_bts(BSCVTY, 0);
2938 var charstring vty_error;
2939 vty_error := f_vty_transceive_ret(BSCVTY,
2940 "si2quater neighbor-list add earfcn 70 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3")
2941 f_vty_transceive(BSCVTY, "end");
2942
2943 if (f_strstr(vty_error, "Unable to add ARFCN 70") >= 0) {
2944 log("Got expected VTY error: ", vty_error);
2945 setverdict(pass);
2946 } else {
2947 setverdict(fail, "Expected the 49th EUTRAN ARFCN to be rejected by vty config, got: ", vty_error);
2948 }
2949
2950 f_init_bts_and_check_sysinfo(0, expect_si := sic);
2951
2952 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002953 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 +02002954 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002955 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002956}
2957
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002958private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
2959{
2960 var uint8_t count := 0;
2961 for (var integer i := 5; i < 16; i := i + 1) {
2962 if (acc[i] == '0'B) { /* the list marks barred, we count allowed */
2963 count := count + 1;
2964 }
2965 }
2966 return count;
2967}
2968
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002969private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return SystemInformationType1
2970{
2971 var ASP_RSL_Unitdata rx_rsl_ud;
2972 var SystemInformationType1 last_si1;
2973
2974 timer T := 30.0;
2975 T.start;
2976 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002977 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
2978 tr_RSL_BCCH_INFO,
2979 tr_RSL_NO_SACCH_FILL,
2980 tr_RSL_SACCH_FILL))) -> value rx_rsl_ud {
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002981 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
2982 if (g_system_information[rsl_idx].si1 == omit) {
2983 repeat;
2984 }
2985 last_si1 := g_system_information[rsl_idx].si1;
2986 g_system_information[rsl_idx].si1 := omit;
2987 T.stop;
2988 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002989 [] IPA_RSL[rsl_idx][0].receive { repeat; }
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002990 [] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
2991 }
2992 return last_si1;
2993}
2994
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002995/* verify ACC rotate feature */
2996testcase TC_si_acc_rotate() runs on test_CT {
2997 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002998 var SystemInformationType1 last_si1;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002999 var AccessControlClass acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003000 var uint8_t count;
3001 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3002
3003 f_init(0, guard_timeout := 60.0);
3004
3005 f_bts_0_cfg(BSCVTY, {"rach access-control-class 5 barred",
3006 "access-control-class-rotate 3",
3007 "access-control-class-rotate-quantum 1"});
3008
3009 /* Init and get first sysinfo */
3010 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3011
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003012 for (var integer i:= 0; i < 20; i := i + 1) {
3013 last_si1 := f_recv_next_si1(0);
3014 acc := last_si1.rach_control.acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003015 count := f_acc09_count_allowed(acc);
3016 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3017
3018 if (count != 3) {
3019 log("RSL: EXPECTED SI ACC len=3");
3020 setverdict(fail, "received SI does not match expectations");
3021 break;
3022 }
3023
3024 for (var integer j := 0; j < 10; j := j + 1) {
3025 if (acc[16 - 1 - j] == '0'B) { /* the list marks barred, we count allowed */
3026 times_allowed[j] := times_allowed[j] + 1;
3027 }
3028 }
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003029 }
3030
3031 for (var integer j := 0; j < 10; j := j + 1) {
3032 log("ACC", j, " allowed ", times_allowed[j], " times" );
3033 if (j != 5 and times_allowed[j] < 3) {
3034 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " < 1 times");
3035 } else if (j == 5 and times_allowed[j] > 0) {
3036 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " > 0 times");
3037 }
3038 }
3039
3040 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3041 "rach access-control-class 5 allowed"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003042 f_shutdown_helper();
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003043}
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02003044
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003045/* verify ACC startup ramp+rotate feature */
3046testcase TC_si_acc_ramp_rotate() runs on test_CT {
3047 var template SystemInformationConfig sic := SystemInformationConfig_default;
3048 var SystemInformationType1 last_si1;
3049 var AccessControlClass acc;
3050 var ASP_RSL_Unitdata rx_rsl_ud;
3051 var uint8_t count;
3052 var uint8_t prev_count;
3053 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3054
3055 f_init(0, guard_timeout := 80.0);
3056
3057 f_bts_0_cfg(BSCVTY, {"rach access-control-class 4 barred",
3058 "access-control-class-rotate 0",
3059 "access-control-class-rotate-quantum 1",
3060 "access-control-class-ramping",
3061 "access-control-class-ramping-step-interval 5",
3062 "access-control-class-ramping-step-size 5"});
3063
3064 /* Init and get first sysinfo */
3065 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3066 last_si1 := g_system_information[0].si1;
3067 acc := last_si1.rach_control.acc;
3068 count := f_acc09_count_allowed(acc);
3069 /* Adm subset size was set to 0 above, so wait until all ACC are barred */
3070 while (count > 0) {
3071 last_si1 := f_recv_next_si1(0);
3072 acc := last_si1.rach_control.acc;
3073 count := f_acc09_count_allowed(acc);
3074 log("RSL: wait len()=0: GOT SI1 ACC len=", count, ": ", acc);
3075 }
3076
3077 /* Increase adm subset size, we should see ramping start up */
3078 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10"});
3079 prev_count := 0;
3080 while (true) {
3081 last_si1 := f_recv_next_si1(0);
3082 acc := last_si1.rach_control.acc;
3083 count := f_acc09_count_allowed(acc);
3084 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3085
3086 if (prev_count > count) {
3087 setverdict(fail, "ACC allowed count dropped while expecting grow: ", prev_count, " -> ", count);
3088 break;
3089 }
3090
3091 if (count == 9) {
3092 break; /* Maximum reached (10 - 1 perm barred), done here */
3093 }
3094
3095 prev_count := count;
3096 }
3097
3098 setverdict(pass);
3099
3100 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3101 "rach access-control-class 4 allowed",
3102 "no access-control-class-ramping"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003103 f_shutdown_helper();
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003104}
3105
Harald Welte4003d112017-12-09 22:35:39 +01003106testcase TC_ctrl_msc_connection_status() runs on test_CT {
3107 var charstring ctrl_resp;
3108
Harald Welte89d42e82017-12-17 16:42:41 +01003109 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003110
3111 /* See https://osmocom.org/issues/2729 */
3112 f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003113 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01003114}
3115
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003116testcase TC_ctrl_msc0_connection_status() runs on test_CT {
3117 var charstring ctrl_resp;
3118
3119 f_init(1);
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003120
3121 f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003122 f_shutdown_helper();
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003123}
3124
Neels Hofmeyr0bc470d2021-08-21 13:37:13 +02003125/* Verify correct stats on the number of configured and connected MSCs */
3126private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
3127 g_pars := f_gen_test_hdlr_pars();
3128 var StatsDExpects expect := {
3129 { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
3130 { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
3131 };
3132 f_statsd_expect(expect);
3133}
3134
3135private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
3136{
3137 var MSC_ConnHdlr vc_conn;
3138
3139 f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
3140 f_sleep(1.0);
3141 vc_conn := f_start_handler(tc_fn);
3142 vc_conn.done;
3143
3144 /* Also verify stat exposed on CTRL interface */
3145 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
3146 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
3147
3148 f_shutdown_helper();
3149}
3150
3151/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
3152private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
3153 f_tc_stat_num_msc_connected_msc_connhdlr(1);
3154}
3155testcase TC_stat_num_msc_connected_1() runs on test_CT {
3156 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
3157}
3158
3159/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
3160private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
3161 f_tc_stat_num_msc_connected_msc_connhdlr(2);
3162}
3163testcase TC_stat_num_msc_connected_2() runs on test_CT {
3164 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
3165}
3166
3167/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
3168private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
3169 f_tc_stat_num_msc_connected_msc_connhdlr(3);
3170}
3171testcase TC_stat_num_msc_connected_3() runs on test_CT {
3172 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
3173}
3174
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003175/* Verify correct stats on the number of configured and connected MSCs */
3176private 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 +06003177 var integer num_trx_connected := 0;
3178 var integer num_trx_total := 0;
3179
3180 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3181 var integer trx_num := c_BtsParams[i].trx_num;
3182 num_trx_total := num_trx_total + trx_num;
3183 if (i < expect_num_bts_connected) {
3184 num_trx_connected := num_trx_connected + trx_num;
3185 }
3186 }
3187
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003188 var StatsDExpects expect := {
3189 { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
3190 { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3191 { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003192 { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := num_trx_connected, max := num_trx_connected },
3193 { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := num_trx_total, max := num_trx_total }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003194 };
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003195
3196 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003197 f_statsd_expect(expect);
3198}
3199
3200private 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 +06003201 var integer num_trx_connected := 0;
3202 var integer num_trx_total := 0;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003203 var MSC_ConnHdlr vc_conn;
3204
3205 f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
3206 f_sleep(1.0);
3207 vc_conn := f_start_handler(tc_fn);
3208 vc_conn.done;
3209
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003210 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3211 var integer trx_num := c_BtsParams[i].trx_num;
3212 num_trx_total := num_trx_total + trx_num;
3213 if (i < nr_bts) {
3214 num_trx_connected := num_trx_connected + trx_num;
3215 }
3216 }
3217
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003218 /* Also verify stat exposed on CTRL interface */
3219 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
3220 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 +06003221 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(num_trx_connected));
3222 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 +02003223
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003224 /* Verify rf_states exposed on CTRL interface */
3225 var charstring expect_net_rf_states := "";
3226 for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003227 var charstring expect_bts_rf_states := "";
3228
3229 for (var integer j := 0; j < c_BtsParams[i].trx_num; j := j + 1) {
3230 expect_bts_rf_states := expect_bts_rf_states &
3231 int2str(i) & "," & int2str(j) & ",";
3232 if (i < NUM_BTS) {
3233 /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
3234 expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
3235 } else {
3236 /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
3237 expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
3238 }
3239 /* The RF policy is still global in osmo-bsc, i.e. always "on" */
3240 expect_bts_rf_states := expect_bts_rf_states & "on,";
3241 if (i < nr_bts) {
3242 /* For BTS where RSL is connected, the RSL state will be "up" */
3243 expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
3244 } else {
3245 expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
3246 }
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003247 }
3248
3249 f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
3250 expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
3251 }
3252 f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
3253
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003254 f_shutdown_helper();
3255}
3256
3257/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
3258private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
3259 f_tc_stat_num_bts_connected_msc_connhdlr(1);
3260}
3261testcase TC_stat_num_bts_connected_1() runs on test_CT {
3262 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
3263}
3264
3265/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
3266private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
3267 f_tc_stat_num_bts_connected_msc_connhdlr(2);
3268}
3269testcase TC_stat_num_bts_connected_2() runs on test_CT {
3270 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
3271}
3272
3273/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
3274private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
3275 f_tc_stat_num_bts_connected_msc_connhdlr(3);
3276}
3277testcase TC_stat_num_bts_connected_3() runs on test_CT {
3278 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
3279}
3280
Harald Welte4003d112017-12-09 22:35:39 +01003281testcase TC_ctrl() runs on test_CT {
3282 var charstring ctrl_resp;
3283
Harald Welte89d42e82017-12-17 16:42:41 +01003284 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003285
3286 /* all below values must match the osmo-bsc.cfg config file used */
3287
Harald Welte6a129692018-03-17 17:30:14 +01003288 f_ctrl_get_exp(IPA_CTRL, "mcc", "001");
3289 f_ctrl_get_exp(IPA_CTRL, "mnc", "01");
Oliver Smith75aa0202019-08-19 14:17:50 +02003290 f_ctrl_get_exp(IPA_CTRL, "number-of-bts", "4");
Harald Welte4003d112017-12-09 22:35:39 +01003291
3292 var integer bts_nr := 0;
3293 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "location-area-code", "1");
3294 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "cell-identity", "0");
3295 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "oml-connection-state", "connected");
3296 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "gprs-mode", "gprs");
3297 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "rf_state", "operational,unlocked,on");
3298 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "arfcn", "871");
3299 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "max-power-reduction", "20");
3300
3301 var integer uptime := str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime"));
3302 f_sleep(2.0);
3303 if (str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime")) < uptime+1) {
3304 setverdict(fail, "oml-uptime not incrementing as expected");
3305 }
3306 /* TODO: Disconnect RSL, imply that OML is disconnected and check for uptime zero? */
3307
3308 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
3309
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003310 f_shutdown_helper();
Harald Welte96c94412017-12-09 03:12:45 +01003311}
3312
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003313/* Verify that Upon receival of SET "location", BSC forwards a TRAP
3314 "location-state" over the SCCPlite IPA conn */
3315testcase TC_ctrl_location() runs on test_CT {
3316 var MSC_ConnHdlr vc_conn;
3317 var integer bts_nr := 0;
3318
3319 f_init(1, true);
3320 f_sleep(1.0);
3321
3322 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234567,fix3d,0.340000,0.560000,0.780000");
3323 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3324 "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
3325
3326 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "1");
3327 f_sleep(2.0);
3328
3329 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234888,fix3d,0.350000,0.570000,0.790000");
3330 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3331 "1234888,fix3d,0.350000,0.570000,0.790000,operational,locked,off,001,01");
3332
3333 /* should match the one from config */
3334 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
3335
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003336 f_shutdown_helper();
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003337}
3338
Harald Welte6f521d82017-12-11 19:52:02 +01003339
3340/***********************************************************************
3341 * Paging Testing
3342 ***********************************************************************/
3343
3344type record Cell_Identity {
3345 GsmMcc mcc,
3346 GsmMnc mnc,
3347 GsmLac lac,
3348 GsmCellId ci
3349};
Harald Welte24135bd2018-03-17 19:27:53 +01003350private const Cell_Identity cid := { '001'H, '01'H, 1, 0 };
Stefan Sperling049a86e2018-03-20 15:51:00 +01003351private const Cell_Identity unknown_cid := { '678'H, 'f90'H, 1, 0 };
Harald Welte6f521d82017-12-11 19:52:02 +01003352
Harald Welte5d1a2202017-12-13 19:51:29 +01003353type set of integer BtsIdList;
3354
3355private function f_bts_in_list(integer bts_id, BtsIdList bts_ids) return boolean {
3356 for (var integer j := 0; j < sizeof(bts_ids); j := j + 1) {
3357 if (bts_id == bts_ids[j]) {
3358 return true;
3359 }
3360 }
3361 return false;
3362}
Harald Welte6f521d82017-12-11 19:52:02 +01003363
3364/* core paging test helper function; used by most paging test cases */
3365private function f_pageing_helper(hexstring imsi,
3366 template BSSMAP_FIELD_CellIdentificationList cid_list,
Harald Welte5d1a2202017-12-13 19:51:29 +01003367 BtsIdList bts_ids := { 0 },
Harald Welte6f521d82017-12-11 19:52:02 +01003368 template RSL_ChanNeeded rsl_chneed := omit,
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003369 template (omit) OCT4 tmsi := omit) runs on test_CT
Harald Welte6f521d82017-12-11 19:52:02 +01003370{
3371 var template BSSMAP_IE_ChannelNeeded bssmap_chneed;
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003372 var template MobileIdentityV mi;
Harald Welte6f521d82017-12-11 19:52:02 +01003373 var RSL_Message rx_rsl;
3374 var integer paging_group := hex2int(imsi[lengthof(imsi)-1]);
Harald Welte5d1a2202017-12-13 19:51:29 +01003375 var integer i;
Harald Welte6f521d82017-12-11 19:52:02 +01003376
3377 f_init();
Harald Welte6f521d82017-12-11 19:52:02 +01003378
3379 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Harald Weltec3068592018-03-17 19:55:31 +01003380 for (i := 0; i < NUM_BTS; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003381 IPA_RSL[i][0].clear;
Harald Welte5d1a2202017-12-13 19:51:29 +01003382 }
Harald Welte6f521d82017-12-11 19:52:02 +01003383
3384 if (isvalue(rsl_chneed)) {
3385 /* The values of 08.08 3.2.2.36 and 08.58 9.3.40 are luckily identical */
3386 bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
3387 } else {
3388 bssmap_chneed := omit;
3389 }
3390
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003391 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
3392 ts_BSSMAP_Paging(imsi, cid_list, tmsi, bssmap_chneed)));
Harald Welte6f521d82017-12-11 19:52:02 +01003393
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003394 if (not istemplatekind(tmsi, "omit")) {
3395 mi := t_MI_TMSI(tmsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003396 } else {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003397 mi := tr_MI_IMSI(imsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003398 }
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003399
Harald Welte5d1a2202017-12-13 19:51:29 +01003400 for (i := 0; i < sizeof(bts_ids); i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003401 rx_rsl := f_exp_ipa_rx(tr_RSL_PAGING_CMD(mi), idx := {bts_ids[i], 0});
Harald Welte5d1a2202017-12-13 19:51:29 +01003402 /* check channel type, paging group */
3403 if (rx_rsl.ies[1].body.paging_group != paging_group) {
3404 setverdict(fail, "Paging for wrong paging group");
3405 }
3406 if (ispresent(rsl_chneed) and
3407 rx_rsl.ies[3].body.chan_needed.chan_needed != valueof(rsl_chneed)) {
3408 setverdict(fail, "RSL Channel Needed != BSSMAP Channel Needed");
3409 }
Harald Welte6f521d82017-12-11 19:52:02 +01003410 }
Harald Welte2fccd982018-01-31 15:48:19 +01003411 f_sleep(2.0);
Harald Welte5d1a2202017-12-13 19:51:29 +01003412 /* do a quick check on all not-included BTSs if they received paging */
3413 for (i := 0; i < NUM_BTS; i := i + 1) {
3414 timer T := 0.1;
3415 if (f_bts_in_list(i, bts_ids)) {
3416 continue;
3417 }
3418 T.start;
3419 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003420 [] IPA_RSL[i][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003421 setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
3422 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003423 [] IPA_RSL[i][0].receive { repeat; }
Harald Welte5d1a2202017-12-13 19:51:29 +01003424 [] T.timeout { }
3425 }
Harald Welte6f521d82017-12-11 19:52:02 +01003426 }
3427
3428 setverdict(pass);
3429}
3430
Harald Welte5d1a2202017-12-13 19:51:29 +01003431const BtsIdList c_BtsId_all := { 0, 1, 2 };
Harald Welte751d3eb2018-01-31 15:51:06 +01003432const BtsIdList c_BtsId_none := { };
Harald Welte5d1a2202017-12-13 19:51:29 +01003433const BtsIdList c_BtsId_LAC1 := { 0, 1 };
3434const BtsIdList c_BtsId_LAC2 := { 2 };
3435
Harald Welte6f521d82017-12-11 19:52:02 +01003436/* PAGING by IMSI + TMSI */
3437testcase TC_paging_imsi_nochan() runs on test_CT {
3438 var BSSMAP_FIELD_CellIdentificationList cid_list;
3439 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Philipp Maier8c04b0a2018-02-23 13:48:48 +01003440 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, omit);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003441 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003442}
3443
3444/* PAGING by IMSI + TMSI */
3445testcase TC_paging_tmsi_nochan() runs on test_CT {
3446 var BSSMAP_FIELD_CellIdentificationList cid_list;
3447 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003448 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, 'A1B2C301'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003449 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003450}
3451
3452/* Paging with different "channel needed' values */
3453testcase TC_paging_tmsi_any() runs on test_CT {
3454 var BSSMAP_FIELD_CellIdentificationList cid_list;
3455 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003456 f_pageing_helper('001010100000002'H, cid_list, c_BtsId_all, RSL_CHANNEED_ANY, 'A1B2C302'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003457 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003458}
3459testcase TC_paging_tmsi_sdcch() runs on test_CT {
3460 var BSSMAP_FIELD_CellIdentificationList cid_list;
3461 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003462 f_pageing_helper('001010100000003'H, cid_list, c_BtsId_all, RSL_CHANNEED_SDCCH, 'A1B2C303'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003463 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003464}
3465testcase TC_paging_tmsi_tch_f() runs on test_CT {
3466 var BSSMAP_FIELD_CellIdentificationList cid_list;
3467 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003468 f_pageing_helper('001010000000004'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_F, 'A1B2C304'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003469 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003470}
3471testcase TC_paging_tmsi_tch_hf() runs on test_CT {
3472 var BSSMAP_FIELD_CellIdentificationList cid_list;
3473 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003474 f_pageing_helper('001010000000005'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_ForH, 'A1B2C305'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003475 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003476}
3477
3478/* Paging by CGI */
3479testcase TC_paging_imsi_nochan_cgi() runs on test_CT {
3480 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3481 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(cid.mcc, cid.mnc, cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003482 f_pageing_helper('001010000000006'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003483 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003484}
3485
3486/* Paging by LAC+CI */
3487testcase TC_paging_imsi_nochan_lac_ci() runs on test_CT {
3488 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3489 cid_list := { cIl_LAC_CI := { ts_BSSMAP_CI_LAC_CI(cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003490 f_pageing_helper('001010000000007'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003491 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003492}
3493
3494/* Paging by CI */
3495testcase TC_paging_imsi_nochan_ci() runs on test_CT {
3496 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3497 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003498 f_pageing_helper('001010000000008'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003499 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003500}
3501
3502/* Paging by LAI */
3503testcase TC_paging_imsi_nochan_lai() runs on test_CT {
3504 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3505 cid_list := { cIl_LAI := { ts_BSSMAP_CI_LAI(cid.mcc, cid.mnc, cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003506 f_pageing_helper('001010000000009'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003507 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003508}
3509
3510/* Paging by LAC */
3511testcase TC_paging_imsi_nochan_lac() runs on test_CT {
3512 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3513 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003514 f_pageing_helper('001010000000010'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003515 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003516}
3517
3518/* Paging by "all in BSS" */
3519testcase TC_paging_imsi_nochan_all() runs on test_CT {
3520 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3521 cid_list := { cIl_allInBSS := ''O };
Harald Welte5d1a2202017-12-13 19:51:29 +01003522 f_pageing_helper('001010000000011'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003523 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003524}
3525
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003526/* Paging by PLMN+LAC+RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003527testcase TC_paging_imsi_nochan_plmn_lac_rnc() runs on test_CT {
3528 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3529 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 +01003530 f_pageing_helper('001010000000012'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003531 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003532}
Harald Welte6f521d82017-12-11 19:52:02 +01003533
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003534/* Paging by RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003535testcase TC_paging_imsi_nochan_rnc() runs on test_CT {
3536 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3537 cid_list := { cIl_RNC := { int2oct(13, 2) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003538 f_pageing_helper('001010000000013'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003539 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003540}
3541
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003542/* Paging by LAC+RNC; We do not implement; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003543testcase TC_paging_imsi_nochan_lac_rnc() runs on test_CT {
3544 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3545 cid_list := { cIl_LAC_RNC := { ts_BSSMAP_CI_LAC_RNC(cid.lac, 14) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003546 f_pageing_helper('001010000000014'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003547 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003548}
3549
Harald Welte6f521d82017-12-11 19:52:02 +01003550/* Paging on multiple cells (multiple entries in list): Verify all of them page */
Harald Welte751d3eb2018-01-31 15:51:06 +01003551testcase TC_paging_imsi_nochan_lacs() runs on test_CT {
3552 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3553 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(1), ts_BSSMAP_CI_LAC(2) } };
3554 f_pageing_helper('001010000000015'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003555 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003556}
3557
3558/* Paging on empty list: Verify none of them page */
3559testcase TC_paging_imsi_nochan_lacs_empty() runs on test_CT {
3560 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3561 cid_list := { cIl_LAC := { } };
3562 f_pageing_helper('001010000000016'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003563 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003564}
3565
Stefan Sperling049a86e2018-03-20 15:51:00 +01003566/* Paging by CGI with unknown MCC/MNC: Verify nothing is paged. */
3567testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
3568 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3569 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(unknown_cid.mcc, unknown_cid.mnc, unknown_cid.lac, unknown_cid.ci) } };
3570 f_pageing_helper('001010000000006'H, cid_list, c_BtsId_none);
3571 f_shutdown_helper();
3572}
3573
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +01003574/* Send paging response containing invalid (wrongly formatted) MobileIdentity IE. */
3575testcase TC_paging_imsi_nochan_ci_resp_invalid_mi() runs on test_CT {
3576 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3577 var BSSAP_N_CONNECT_ind rx_c_ind;
3578 var DchanTuple dt;
3579 var octetstring rr_pag_resp := '06270003535992617965720000'O;
3580 /* { 06 27 } is { GSM48_PDISC_RR, GSM48_MT_RR_PAG_RESP }
3581 * see 3GPP TS 44.018, table 9.1.25.1
3582 * { 00 } or { 01 } is CKSN + Spare Half Octet, not important
3583 * { 03 53 59 92 } is Mobile Station Classmark
3584 * { 61 79 65 72 00 00 } is the invalid Mobile Identity IE (3GPP TS 24.008, 10.5.1.4),
3585 * Length is 0x61 (97 in decimal).
3586 */
3587
3588 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
3589 f_pageing_helper('001010000000008'H, cid_list, { 0 });
3590
3591 /* Send CHAN RQD and wait for allocation; acknowledge it */
3592 dt.rsl_chan_nr := f_chreq_act_ack();
3593 dt.idx := {0, 0};
3594
3595 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
3596 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), rr_pag_resp));
3597
3598 /* Expevct a CR with a matching Paging response on the A-Interface */
3599 timer T := 5.0;
3600 T.start;
3601 alt {
3602 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
3603 setverdict(pass);
3604 dt.sccp_conn_id := rx_c_ind.connectionId;
3605 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
3606 }
3607 [] BSSAP.receive {
3608 setverdict(fail, "Received unexpected message on A-Interface!");
3609 }
3610 [] T.timeout {
3611 setverdict(fail, "Received nothing on A-Interface!");
3612 }
3613 }
3614
3615 f_perform_clear_test_ct(dt);
3616 f_shutdown_helper();
3617}
3618
Harald Welte6f521d82017-12-11 19:52:02 +01003619/* Verify paging retransmission interval + count */
3620/* Verify paging stops after channel establishment */
Harald Welte6f521d82017-12-11 19:52:02 +01003621/* Test behavior under paging overload */
Harald Welteae026692017-12-09 01:03:01 +01003622
Harald Weltee65d40e2017-12-13 00:09:06 +01003623/* Verify PCH load */
3624testcase TC_paging_imsi_load() runs on test_CT {
3625 var BSSMAP_FIELD_CellIdentificationList cid_list;
3626 timer T := 4.0;
Harald Welte2caa1062018-03-17 18:19:05 +01003627 timer T_retrans := 1.0;
Harald Weltee65d40e2017-12-13 00:09:06 +01003628 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003629 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Weltee65d40e2017-12-13 00:09:06 +01003630
3631 /* tell BSC there is no paging space anymore */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003632 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte3b57ab52018-03-17 18:01:10 +01003633 f_sleep(0.2);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003634 IPA_RSL[0][0].clear;
Harald Weltee65d40e2017-12-13 00:09:06 +01003635
3636 /* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
3637 * there would be 8 retransmissions during 4 seconds */
3638 T.start;
Harald Welte2caa1062018-03-17 18:19:05 +01003639 T_retrans.start;
Harald Weltee65d40e2017-12-13 00:09:06 +01003640 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003641 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Weltee65d40e2017-12-13 00:09:06 +01003642 setverdict(fail, "Received PAGING after LOAD_IND(0)");
Daniel Willmannafce8662018-07-06 23:11:32 +02003643 mtc.stop;
Harald Weltee65d40e2017-12-13 00:09:06 +01003644 }
Harald Welte2caa1062018-03-17 18:19:05 +01003645 [] T_retrans.timeout {
3646 /* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003647 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte2caa1062018-03-17 18:19:05 +01003648 T_retrans.start;
3649 repeat;
3650 }
Harald Weltee65d40e2017-12-13 00:09:06 +01003651 [] T.timeout {
3652 setverdict(pass);
3653 }
3654 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003655
3656 f_shutdown_helper();
Harald Weltee65d40e2017-12-13 00:09:06 +01003657}
3658
Harald Welte235ebf12017-12-15 14:18:16 +01003659/* Verify Paging Counter */
Harald Welte1ff69992017-12-14 12:31:17 +01003660testcase TC_paging_counter() runs on test_CT {
3661 var BSSMAP_FIELD_CellIdentificationList cid_list;
3662 timer T := 4.0;
3663 var integer i;
3664 var integer paging_attempted_bsc;
3665 var integer paging_attempted_bts[NUM_BTS];
Oliver Smith8b343d32021-11-26 13:01:42 +01003666 var integer paging_expired_bsc;
Harald Welte1ff69992017-12-14 12:31:17 +01003667 var integer paging_expired_bts[NUM_BTS];
3668 cid_list := valueof(ts_BSSMAP_CIL_noCell);
3669
3670 f_init();
3671
3672 /* read counters before paging */
3673 paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003674 paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
Harald Welte1ff69992017-12-14 12:31:17 +01003675 for (i := 0; i < NUM_BTS; i := i+1) {
3676 paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
3677 paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
3678 }
3679
3680 f_pageing_helper('001230000000001'H, cid_list, c_BtsId_all);
3681
3682 /* expect the attempted pages on BSC and each BTSs to have incremented by one */
3683 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", paging_attempted_bsc+1);
3684 for (i := 0; i < NUM_BTS; i := i+1) {
3685 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted",
3686 paging_attempted_bts[i]+1);
3687 }
3688
3689 /* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
3690 f_sleep(12.0);
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003691 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
Harald Welte1ff69992017-12-14 12:31:17 +01003692 for (i := 0; i < NUM_BTS; i := i+1) {
3693 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
3694 paging_expired_bts[i]+1);
3695 }
Harald Welte1ff69992017-12-14 12:31:17 +01003696
Philipp Maier282ca4b2018-02-27 17:17:00 +01003697 f_shutdown_helper();
Harald Welte1ff69992017-12-14 12:31:17 +01003698}
3699
3700
Harald Welte10985002017-12-12 09:29:15 +01003701/* Verify paging stops after A-RESET */
3702testcase TC_paging_imsi_a_reset() runs on test_CT {
3703 var BSSMAP_FIELD_CellIdentificationList cid_list;
3704 timer T := 3.0;
3705 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003706 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Welte10985002017-12-12 09:29:15 +01003707
3708 /* Perform a BSSMAP Reset and wait for ACK */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003709 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 +01003710 alt {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003711 [] 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 +01003712 [] BSSAP.receive { repeat; }
3713 }
3714
Daniel Willmanncbef3982018-07-30 09:22:40 +02003715 /* Wait to avoid a possible race condition if a paging message is
3716 * received right before the reset ACK. */
3717 f_sleep(0.2);
3718
Harald Welte10985002017-12-12 09:29:15 +01003719 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Philipp Maier1e6b4422018-02-23 14:02:13 +01003720 for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003721 IPA_RSL[i][0].clear;
Philipp Maier1e6b4422018-02-23 14:02:13 +01003722 }
Harald Welte10985002017-12-12 09:29:15 +01003723
3724 /* Wait for 3 seconds if any more PAGING CMD are received on RSL */
3725 T.start;
3726 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003727 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte10985002017-12-12 09:29:15 +01003728 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003729 mtc.stop;
Harald Welte10985002017-12-12 09:29:15 +01003730 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003731 [] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003732 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003733 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003734 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003735 [] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003736 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003737 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003738 }
Harald Welte10985002017-12-12 09:29:15 +01003739 [] T.timeout {
3740 setverdict(pass);
3741 }
3742 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003743
3744 f_shutdown_helper();
Harald Welte10985002017-12-12 09:29:15 +01003745}
Harald Welteae026692017-12-09 01:03:01 +01003746
Philipp Maierf45824a2019-08-14 14:44:10 +02003747/* Verify how we handle unsolicited Paging Response. In case of an unsolicit
3748 * paging response we can not know which MSC is in charge, so we will blindly
3749 * pick the first configured MSC. This behavior is required in order to make
3750 * MT-CSFB calls working because in those cases the BSC can not know that the
3751 * MSC has already paged the subscriver via SGs. So any MT-CSFB call will look
3752 * like an unsolicited Paging Response to the MSC.
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003753 */
3754testcase TC_paging_resp_unsol() runs on test_CT {
3755
3756 f_init(1);
Philipp Maierf45824a2019-08-14 14:44:10 +02003757 timer T := 5.0;
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003758
3759 var BSSAP_N_CONNECT_ind rx_c_ind;
3760 var DchanTuple dt;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02003761 var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010008880018'H)));
Philipp Maierf45824a2019-08-14 14:44:10 +02003762 var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003763
3764 /* Send CHAN RQD and wait for allocation; acknowledge it */
3765 dt.rsl_chan_nr := f_chreq_act_ack();
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003766 dt.idx := {0, 0};
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003767
3768 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
Pau Espin Pedrole8a51012023-01-03 11:59:59 +01003769 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 +01003770
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003771
Philipp Maierf45824a2019-08-14 14:44:10 +02003772 /* Expevct a CR with a matching Paging response on the A-Interface */
3773 T.start;
3774 alt {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003775 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
Philipp Maierf45824a2019-08-14 14:44:10 +02003776 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003777 dt.sccp_conn_id := rx_c_ind.connectionId;
3778 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
Philipp Maierf45824a2019-08-14 14:44:10 +02003779 }
3780 [] BSSAP.receive {
3781 setverdict(fail, "Received unexpected message on A-Interface!");
3782 }
3783 [] T.timeout {
3784 setverdict(fail, "Received nothing on A-Interface!");
3785 }
3786 }
3787
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003788 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003789 f_shutdown_helper();
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003790}
3791
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003792/* Verify BSC can schedule N paging requests under one minute if BTS buffer is good enough */
3793function f_TC_paging_Nreq(integer num_subscribers, boolean send_pag_load_ind) runs on test_CT {
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003794 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003795 var Hexstrings imsis := {};
3796 var Booleans rx_paging_done := {};
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003797 var integer rx_paging_num := 0;
3798 var integer i;
3799 timer T_rx := 60.0;
3800 timer T_load_ind := 1.0;
3801
3802 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003803 imsis := imsis & {f_gen_imsi(i)};
3804 rx_paging_done := rx_paging_done & { false };
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003805 }
3806
3807 f_init(1, guard_timeout := 100.0);
3808
3809 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003810 IPA_RSL[0][0].clear;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003811 if (send_pag_load_ind) {
3812 /* Tell there's plenty of space at the BTS (UINT16_MAX): */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003813 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(65535));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003814 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003815
3816 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003817 /* Page on LAC-CI of BTS0: */
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003818 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 +02003819 ts_BSSMAP_Paging(imsis[i], valueof(ts_BSSMAP_CIL_LAC_CI({ts_BSSMAP_CI_LAC_CI(1, 0)})),
3820 omit, omit)));
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003821 }
3822
3823 T_rx.start;
3824 T_load_ind.start;
3825 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003826 [] 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 +02003827 var hexstring imsi := rx_rsl_ud.rsl.ies[2].body.ms_identity.mobileIdentityV.oddEvenInd_identity.imsi.digits;
3828 var hexstring imsi_suffix := substr(imsi, lengthof(imsi)-6, 6);
3829 var charstring imsi_str := hex2str(imsi_suffix);
3830 var integer imsi_idx := str2int(imsi_str);
3831 if (rx_paging_done[imsi_idx] == false) {
3832 rx_paging_done[imsi_idx] := true;
3833 rx_paging_num := rx_paging_num + 1;
Pau Espin Pedrolef7ef632022-04-25 13:34:57 +02003834 } else {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003835 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 +02003836 mtc.stop;
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003837 }
3838 if (rx_paging_num < num_subscribers) {
3839 repeat;
3840 }
3841 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003842 [] IPA_RSL[0][0].receive { repeat; }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003843 [] T_load_ind.timeout {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003844 log("[CCH Load Ind timer] received paging requests so far: ", rx_paging_num);
3845 if (send_pag_load_ind) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003846 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(40));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003847 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003848 T_load_ind.start;
3849 repeat;
3850 }
3851 [] T_rx.timeout {
3852 setverdict(fail, "Timeout expecting paging requests, so far ", rx_paging_num);
3853 mtc.stop;
3854 }
3855 }
3856
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003857 /* Drop OML connection to have all paging requests flushed: */
3858 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
3859
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003860 f_shutdown_helper();
3861}
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003862/* Verify BSC can schedule 500 paging requests under one minute if BTS buffer is good enough */
3863testcase TC_paging_500req() runs on test_CT {
3864 f_TC_paging_Nreq(500, true);
3865}
3866/* Same as TC_paging_500req, but without sending CCCH Load Indication, which
3867 * means BTS is always under CCH Load Threshold, aka capable of sending tons of requests.
3868 * Since No CCCH Load Ind, BSC uses a conservative estimation of BTS load, which
3869 * for current config yields ~8req/sec, so 480req/min maximum. */
3870testcase TC_paging_450req_no_paging_load_ind() runs on test_CT {
3871 f_TC_paging_Nreq(450, false);
3872}
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003873
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003874/* Test RSL link drop causes counter increment */
3875testcase TC_rsl_drop_counter() runs on test_CT {
3876 var integer rsl_fail;
3877
Harald Welte89d42e82017-12-17 16:42:41 +01003878 f_init(1);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003879
3880 rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
3881
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003882 f_ipa_rsl_stop(bts[0][0].rsl);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003883
3884 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
3885
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003886 f_shutdown_helper();
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003887}
3888
3889/* TODO: Test OML link drop causes counter increment */
3890
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003891/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
3892function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003893 var IPA_Client client;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003894 timer T := 10.0;
3895
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003896 client.id := "IPA-BTS0-TRX0-RSL";
3897 client.vc_IPA := IPA_Emulation_CT.create(client.id & "-IPA") alive;
3898 client.ccm_pars := c_IPA_default_ccm_pars;
3899 client.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
3900 client.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003901
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01003902 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003903
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003904 f_init_mgcp(0, "VirtMGW");
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003905
3906 /* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003907 map(client.vc_IPA:IPA_PORT, system:IPA);
3908 connect(client.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0][0]);
3909 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 +01003910
3911 /* wait for IPA OML link to connect and then disconnect */
3912 T.start;
3913 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003914 [] IPA_RSL[0][0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003915 T.stop;
3916 return true;
3917 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003918 [] IPA_RSL[0][0].receive { repeat }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003919 [] T.timeout {
Daniel Willmannafce8662018-07-06 23:11:32 +02003920 return false;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003921 }
3922 }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003923 return false;
3924}
3925
3926/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3927testcase TC_rsl_unknown_unit_id() runs on test_CT {
3928 if (f_ipa_unknown_unit_id(mp_bsc_rsl_port)) {
3929 setverdict(pass);
3930 } else {
3931 setverdict(fail, "Timeout RSL waiting for connection to close");
3932 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003933 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003934}
3935
3936
3937/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3938testcase TC_oml_unknown_unit_id() runs on test_CT {
3939 if (f_ipa_unknown_unit_id(mp_bsc_oml_port)) {
3940 setverdict(pass);
3941 } else {
3942 setverdict(fail, "Timeout OML waiting for connection to close");
3943 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003944 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003945}
3946
3947
Harald Weltec1a2fff2017-12-17 11:06:19 +01003948/***********************************************************************
Harald Welte6811d102019-04-14 22:23:14 +02003949 * "New world" test cases using RSL_Emulation + RAN_Emulation
Harald Weltec1a2fff2017-12-17 11:06:19 +01003950 ***********************************************************************/
3951
Harald Welte6811d102019-04-14 22:23:14 +02003952import from RAN_Emulation all;
Harald Welte47cd0e32020-08-21 12:39:11 +02003953import from BSSAP_LE_Emulation all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01003954import from RSL_Emulation all;
3955import from MSC_ConnectionHandler all;
3956
3957type function void_fn(charstring id) runs on MSC_ConnHdlr;
3958
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003959/* helper function to create and connect a MSC_ConnHdlr component
3960 * TODO: allow connecting to TRX1..N, not only TRX0 */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003961private 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 +02003962 connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003963 connect(vc_conn:RSL, bts[0][0].rsl.vc_RSL:CLIENT_PT);
3964 connect(vc_conn:RSL_PROC, bts[0][0].rsl.vc_RSL:RSL_PROC);
3965 if (isvalue(bts[1][0])) {
3966 connect(vc_conn:RSL1, bts[1][0].rsl.vc_RSL:CLIENT_PT);
3967 connect(vc_conn:RSL1_PROC, bts[1][0].rsl.vc_RSL:RSL_PROC);
Philipp Maier956a92f2018-02-16 10:58:07 +01003968 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003969 if (isvalue(bts[2][0])) {
3970 connect(vc_conn:RSL2, bts[2][0].rsl.vc_RSL:CLIENT_PT);
3971 connect(vc_conn:RSL2_PROC, bts[2][0].rsl.vc_RSL:RSL_PROC);
Neels Hofmeyr91401012019-07-11 00:42:35 +02003972 }
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003973 connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02003974 if (mp_enable_lcs_tests) {
3975 connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
3976 connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
3977 }
Daniel Willmannebdecc02020-08-12 15:30:17 +02003978 connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003979 connect(vc_conn:MGCP_PROC, vc_MGCP[mgwpool_idx]:MGCP_PROC);
3980 connect(vc_conn:MGCP, vc_MGCP[mgwpool_idx]:MGCP_CLIENT);
3981 connect(vc_conn:MGCP_MULTI, vc_MGCP[mgwpool_idx]:MGCP_CLIENT_MULTI);
Harald Welte336820c2018-05-31 20:34:52 +02003982}
3983
Neels Hofmeyrda436782021-07-20 22:09:06 +02003984function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
Harald Welte336820c2018-05-31 20:34:52 +02003985runs on test_CT return MSC_ConnHdlr {
3986 var charstring id := testcasename();
3987 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003988 var integer bssap_idx := 0;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003989 var integer mgwpool_idx := 0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003990 if (isvalue(pars)) {
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003991 var TestHdlrParams pars_val := valueof(pars);
3992 bssap_idx := pars_val.mscpool.bssap_idx;
3993 mgwpool_idx := pars_val.mgwpool_idx;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003994 }
Harald Welte336820c2018-05-31 20:34:52 +02003995 vc_conn := MSC_ConnHdlr.create(id);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003996 f_connect_handler(vc_conn, bssap_idx, mgwpool_idx);
Neels Hofmeyrda436782021-07-20 22:09:06 +02003997 return vc_conn;
3998}
3999
4000function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
4001runs on test_CT return MSC_ConnHdlr {
4002 var charstring id := testcasename();
Harald Weltea0630032018-03-20 21:09:55 +01004003 vc_conn.start(f_handler_init(fn, id, pars));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004004 return vc_conn;
4005}
4006
Neels Hofmeyrda436782021-07-20 22:09:06 +02004007function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
4008runs on test_CT return MSC_ConnHdlr {
4009 return f_start_handler_run(f_start_handler_create(pars), fn, pars);
4010}
4011
Harald Weltea0630032018-03-20 21:09:55 +01004012/* first function inside ConnHdlr component; sets g_pars + starts function */
4013private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
4014runs on MSC_ConnHdlr {
4015 if (isvalue(pars)) {
4016 g_pars := valueof(pars);
4017 }
4018 fn.apply(id);
4019}
4020
Oliver Smith26a3db72021-07-09 13:51:29 +02004021private function f_vty_encryption_a5(charstring options) runs on test_CT {
4022 f_vty_transceive(BSCVTY, "configure terminal");
4023 f_vty_transceive(BSCVTY, "network");
4024 f_vty_transceive(BSCVTY, "encryption a5 " & options);
4025 f_vty_transceive(BSCVTY, "exit");
4026 f_vty_transceive(BSCVTY, "exit");
4027}
4028
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004029const charstring VTY_A5_DEFAULT := "0 1 3";
4030
Oliver Smith26a3db72021-07-09 13:51:29 +02004031private function f_vty_encryption_a5_reset() runs on test_CT {
4032 /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004033 f_vty_encryption_a5(VTY_A5_DEFAULT);
Oliver Smith26a3db72021-07-09 13:51:29 +02004034}
4035
Harald Welte3c86ea02018-05-10 22:28:05 +02004036/* Establish signalling channel (non-assignment case) followed by cipher mode */
4037private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004038 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4039 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte3c86ea02018-05-10 22:28:05 +02004040 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Philipp Maier23000732018-05-18 11:25:37 +02004041 ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode := omit;
4042 ass_cmd.pdu.bssmap.assignmentRequest.aoIPTransportLayer := omit;
4043 exp_compl.pdu.bssmap.assignmentComplete.circuitIdentityCode := omit;
4044 exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
Harald Welte3c86ea02018-05-10 22:28:05 +02004045
Philipp Maier23000732018-05-18 11:25:37 +02004046 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004047 f_perform_clear();
Harald Welte3c86ea02018-05-10 22:28:05 +02004048}
4049testcase TC_ciph_mode_a5_0() runs on test_CT {
4050 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004051 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004052 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
4053
4054 f_init(1, true);
4055 f_sleep(1.0);
4056 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4057 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004058 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004059}
4060testcase TC_ciph_mode_a5_1() runs on test_CT {
4061 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004062 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004063 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
4064
4065 f_init(1, true);
4066 f_sleep(1.0);
4067 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4068 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004069 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004070}
Oliver Smith50b98122021-07-09 15:00:28 +02004071/* OS#4975: verify that A5/2 is preferred over A5/0 */
4072testcase TC_ciph_mode_a5_2_0() runs on test_CT {
4073 var MSC_ConnHdlr vc_conn;
4074 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4075
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004076 pars.encr := f_encr_params('05'O, '04'O); /* A5/0 and A5/2 (0x01|0x04)*/
Oliver Smith50b98122021-07-09 15:00:28 +02004077
4078 f_init(1, true);
4079 f_vty_encryption_a5("0 1 2 3");
4080 f_sleep(1.0);
4081 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4082 vc_conn.done;
4083 f_vty_encryption_a5_reset();
4084 f_shutdown_helper();
4085}
Oliver Smith1dff88d2021-07-09 08:45:51 +02004086/* OS#4975: verify that A5/1 is preferred over A5/2 */
4087testcase TC_ciph_mode_a5_2_1() runs on test_CT {
4088 var MSC_ConnHdlr vc_conn;
4089 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4090
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004091 pars.encr := f_encr_params('06'O, '02'O); /* A5/1 and A5/2 (0x02|0x04)*/
Oliver Smith1dff88d2021-07-09 08:45:51 +02004092
4093 f_init(1, true);
4094 f_vty_encryption_a5("1 2");
4095 f_sleep(1.0);
4096 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4097 vc_conn.done;
4098 f_vty_encryption_a5_reset();
4099 f_shutdown_helper();
4100}
Harald Welte3c86ea02018-05-10 22:28:05 +02004101testcase TC_ciph_mode_a5_3() runs on test_CT {
4102 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004103 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004104 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
4105
4106 f_init(1, true);
4107 f_sleep(1.0);
4108 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4109 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004110 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004111}
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004112/* Establish a Signalling channel with A5/4 encryption. */
4113testcase TC_ciph_mode_a5_4() runs on test_CT {
4114 var MSC_ConnHdlr vc_conn;
4115 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4116 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Harald Welte3c86ea02018-05-10 22:28:05 +02004117
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004118 f_init(1, true);
Oliver Smith26a3db72021-07-09 13:51:29 +02004119 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004120 f_sleep(1.0);
4121 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4122 vc_conn.done;
Oliver Smith26a3db72021-07-09 13:51:29 +02004123 f_vty_encryption_a5_reset();
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004124 f_shutdown_helper();
4125}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004126/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
4127private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
4128 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4129 var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
4130 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4131 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4132
4133 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004134 f_perform_clear();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004135}
4136testcase TC_assignment_aoip_tla_v6() runs on test_CT {
4137 var MSC_ConnHdlr vc_conn;
4138 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4139
4140 f_init(1, true);
4141 f_sleep(1.0);
4142 vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
4143 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004144 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004145}
4146
Harald Welte3c86ea02018-05-10 22:28:05 +02004147
4148/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
Harald Welte651fcdc2018-05-10 20:23:16 +02004149private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004150 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4151 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004152
Harald Welte552620d2017-12-16 23:21:36 +01004153 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4154 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte73cd2712017-12-17 00:44:52 +01004155
Harald Weltea0630032018-03-20 21:09:55 +01004156 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004157 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004158}
Harald Welte552620d2017-12-16 23:21:36 +01004159testcase TC_assignment_fr_a5_0() runs on test_CT {
4160 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004161 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004162 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
Harald Welte552620d2017-12-16 23:21:36 +01004163
Harald Welte89d42e82017-12-17 16:42:41 +01004164 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004165 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004166 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004167 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004168 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004169}
Harald Welte552620d2017-12-16 23:21:36 +01004170testcase TC_assignment_fr_a5_1() runs on test_CT {
Harald Weltec1a2fff2017-12-17 11:06:19 +01004171 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004172 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004173 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004174
Harald Welte89d42e82017-12-17 16:42:41 +01004175 f_init(1, true);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004176 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004177 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4178 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004179 f_shutdown_helper();
Harald Welte651fcdc2018-05-10 20:23:16 +02004180}
4181testcase TC_assignment_fr_a5_3() runs on test_CT {
4182 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004183 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004184 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004185
Harald Welte651fcdc2018-05-10 20:23:16 +02004186 f_init(1, true);
4187 f_sleep(1.0);
4188 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004189 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004190 f_shutdown_helper();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004191}
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004192/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
4193testcase TC_assignment_fr_a5_4() runs on test_CT {
4194 var MSC_ConnHdlr vc_conn;
4195 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4196 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
4197
4198 f_init(1, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02004199 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004200 f_sleep(1.0);
4201 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4202 vc_conn.done;
Oliver Smith7eabd312021-07-12 14:18:56 +02004203 f_vty_encryption_a5_reset();
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004204 f_shutdown_helper();
4205}
Harald Weltec1a2fff2017-12-17 11:06:19 +01004206
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +02004207/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
4208testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
4209 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4210 var MSC_ConnHdlr vc_conn;
4211
4212 f_init(1, true);
4213 f_sleep(1.0);
4214
4215 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
4216 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
4217 vc_conn.done;
4218 f_shutdown_helper();
4219}
4220
Harald Welte552620d2017-12-16 23:21:36 +01004221/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
4222private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004223 g_pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004224 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02004225 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004226
4227 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02004228 /* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
4229
Harald Weltea0630032018-03-20 21:09:55 +01004230 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004231 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004232}
Harald Welte552620d2017-12-16 23:21:36 +01004233testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
4234 var MSC_ConnHdlr vc_conn;
4235
Harald Welte89d42e82017-12-17 16:42:41 +01004236 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004237 f_sleep(1.0);
4238
Harald Welte8863fa12018-05-10 20:15:27 +02004239 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
Harald Welte552620d2017-12-16 23:21:36 +01004240 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004241 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004242}
4243
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004244private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
4245 var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
4246 var PDU_BSSAP exp_ass_req := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004247
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004248 exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4249 exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4250
4251 /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
4252
4253 var BSSMAP_FIELD_CodecType codecType;
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004254
4255 codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
4256 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
4257
4258 f_create_chan_and_exp();
4259 /* we should now have a COMPL_L3 at the MSC */
4260
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004261 /* Start ciphering, expect Cipher Mode Reject */
Neels Hofmeyr6c388f22021-06-11 02:36:56 +02004262 f_cipher_mode(g_pars.encr, exp_fail := true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004263 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004264}
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004265testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
4266 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004267 var MSC_ConnHdlr vc_conn;
4268
Harald Welte89d42e82017-12-17 16:42:41 +01004269 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004270 f_sleep(1.0);
4271
Neels Hofmeyr0588cad2021-06-11 01:38:18 +02004272 pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004273 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004274 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004275 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004276}
4277
4278
Harald Welte4532e0a2017-12-23 02:05:44 +01004279private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004280 g_pars := f_gen_test_hdlr_pars();
Harald Welte4532e0a2017-12-23 02:05:44 +01004281 var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
Philipp Maier48604732018-10-09 15:00:37 +02004282 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte4532e0a2017-12-23 02:05:44 +01004283 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004284
4285 f_statsd_reset();
Harald Weltea0630032018-03-20 21:09:55 +01004286 f_establish_fully(ass_cmd, exp_compl);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004287
4288 var StatsDExpects expect := {
Daniel Willmannc5398f72020-09-21 10:41:35 +02004289 { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
4290 { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
Daniel Willmannebdecc02020-08-12 15:30:17 +02004291 { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
4292 { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
4293 };
4294 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004295 f_perform_clear();
Harald Welte4532e0a2017-12-23 02:05:44 +01004296}
4297
4298testcase TC_assignment_sign() runs on test_CT {
4299 var MSC_ConnHdlr vc_conn;
4300
4301 f_init(1, true);
4302 f_sleep(1.0);
4303
Harald Welte8863fa12018-05-10 20:15:27 +02004304 vc_conn := f_start_handler(refers(f_tc_assignment_sign));
Harald Welte4532e0a2017-12-23 02:05:44 +01004305 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004306 f_shutdown_helper();
Harald Welte4532e0a2017-12-23 02:05:44 +01004307}
4308
Harald Welte60aa5762018-03-21 19:33:13 +01004309/***********************************************************************
4310 * Codec (list) testing
4311 ***********************************************************************/
4312
4313/* check if the given rsl_mode is compatible with the a_elem */
4314private function f_match_codec(BSSMAP_FIELD_CodecElement a_elem, RSL_IE_ChannelMode rsl_mode)
4315return boolean {
4316 select (a_elem.codecType) {
4317 case (GSM_FR) {
4318 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1))) {
4319 return true;
4320 }
4321 }
4322 case (GSM_HR) {
4323 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1))) {
4324 return true;
4325 }
4326 }
4327 case (GSM_EFR) {
4328 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2))) {
4329 return true;
4330 }
4331 }
4332 case (FR_AMR) {
4333 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3))) {
4334 return true;
4335 }
4336 }
4337 case (HR_AMR) {
4338 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3))) {
4339 return true;
4340 }
4341 }
4342 case else { }
4343 }
4344 return false;
4345}
4346
4347/* check if the given rsl_mode is compatible with the a_list */
4348private function f_match_codecs(BSSMAP_IE_SpeechCodecList a_list, RSL_IE_ChannelMode rsl_mode)
4349return boolean {
4350 for (var integer i := 0; i < sizeof(a_list); i := i+1) {
4351 if (f_match_codec(a_list.codecElements[i], rsl_mode)) {
4352 return true;
4353 }
4354 }
4355 return false;
4356}
4357
4358/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
Philipp Maier61f6b572018-07-06 14:03:38 +02004359function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
Harald Welte60aa5762018-03-21 19:33:13 +01004360return BSSMAP_IE_ChannelType {
4361 /* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
4362 var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
4363 select (a_elem.codecType) {
4364 case (GSM_FR) {
4365 ret.channelRateAndType := ChRate_TCHF;
4366 ret.speechId_DataIndicator := Spdi_TCHF_FR;
4367 }
4368 case (GSM_HR) {
4369 ret.channelRateAndType := ChRate_TCHH;
4370 ret.speechId_DataIndicator := Spdi_TCHH_HR;
4371 }
4372 case (GSM_EFR) {
4373 ret.channelRateAndType := ChRate_TCHF;
4374 ret.speechId_DataIndicator := Spdi_TCHF_EFR;
4375 }
4376 case (FR_AMR) {
4377 ret.channelRateAndType := ChRate_TCHF;
4378 ret.speechId_DataIndicator := Spdi_TCHF_AMR;
4379 }
4380 case (HR_AMR) {
4381 ret.channelRateAndType := ChRate_TCHH;
4382 ret.speechId_DataIndicator := Spdi_TCHH_AMR;
4383 }
4384 case else {
4385 setverdict(fail, "Unsupported codec ", a_elem);
Daniel Willmannafce8662018-07-06 23:11:32 +02004386 mtc.stop;
Harald Welte60aa5762018-03-21 19:33:13 +01004387 }
4388 }
4389 return ret;
4390}
4391
Harald Weltea63b9102018-03-22 20:36:16 +01004392private function f_rsl_chmod_tmpl_from_codec(BSSMAP_FIELD_CodecElement a_elem)
4393return template RSL_IE_Body {
4394 var template RSL_IE_Body mode_ie := {
4395 chan_mode := {
4396 len := ?,
4397 reserved := ?,
4398 dtx_d := ?,
4399 dtx_u := ?,
4400 spd_ind := RSL_SPDI_SPEECH,
4401 ch_rate_type := -,
Oliver Smith0033b122023-02-28 13:30:53 +01004402 u := { speech := - }
Harald Weltea63b9102018-03-22 20:36:16 +01004403 }
4404 }
4405
4406 select (a_elem.codecType) {
4407 case (GSM_FR) {
4408 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004409 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004410 }
4411 case (GSM_HR) {
4412 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004413 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004414 }
4415 case (GSM_EFR) {
4416 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004417 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM2;
Harald Weltea63b9102018-03-22 20:36:16 +01004418 }
4419 case (FR_AMR) {
4420 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004421 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004422 }
4423 case (HR_AMR) {
4424 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004425 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004426 }
4427 }
4428 return mode_ie;
4429}
4430
Harald Welte60aa5762018-03-21 19:33:13 +01004431type record CodecListTest {
4432 BSSMAP_IE_SpeechCodecList codec_list,
4433 charstring id
4434}
4435type record of CodecListTest CodecListTests
4436
4437private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004438 f_assignment_codec(id);
4439}
4440
4441private function f_assignment_codec(charstring id, boolean do_perform_clear := true) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02004442 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02004443 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welte60aa5762018-03-21 19:33:13 +01004444
4445 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004446 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte79f3f542018-05-25 20:02:37 +02004447 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4448 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
4449 g_pars.ass_codec_list.codecElements[0];
Philipp Maierd0e64b02019-03-13 14:15:23 +01004450 if (isvalue(g_pars.expect_mr_s0_s7)) {
4451 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
4452 g_pars.expect_mr_s0_s7;
4453 }
Harald Welte79f3f542018-05-25 20:02:37 +02004454 }
Harald Welte60aa5762018-03-21 19:33:13 +01004455 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4456 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
Harald Welte60aa5762018-03-21 19:33:13 +01004457 log("expecting ASS COMPL like this: ", exp_compl);
4458
4459 f_establish_fully(ass_cmd, exp_compl);
Harald Weltea63b9102018-03-22 20:36:16 +01004460
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004461 if (not g_pars.expect_channel_mode_modify) {
4462 /* Verify that the RSL-side activation actually matches our expectations */
4463 var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
Harald Weltea63b9102018-03-22 20:36:16 +01004464
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004465 var RSL_IE_Body mode_ie;
4466 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
4467 setverdict(fail, "Couldn't find CHAN_MODE IE");
Daniel Willmannafce8662018-07-06 23:11:32 +02004468 mtc.stop;
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004469 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004470 var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
4471 if (not match(mode_ie, t_mode_ie)) {
4472 log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
4473 setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004474 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004475
4476 var RSL_IE_Body mr_conf;
4477 if (g_pars.expect_mr_conf_ie != omit) {
4478 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
4479 setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
4480 mtc.stop;
4481 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004482 log("found RSL MR CONFIG IE: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004483
4484 if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
Vadim Yanitskiy8b189372022-09-14 17:31:17 +07004485 setverdict(fail, "RSL MR CONFIG IE does not match expectation. ",
4486 "Expected: ", g_pars.expect_mr_conf_ie, ", got: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004487 }
4488 } else {
4489 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
4490 log("found RSL MR CONFIG IE: ", mr_conf);
4491 setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
4492 mtc.stop;
4493 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004494 }
4495 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004496
4497 if (do_perform_clear) {
4498 f_perform_clear();
4499 }
Harald Welte60aa5762018-03-21 19:33:13 +01004500}
4501
Philipp Maierd0e64b02019-03-13 14:15:23 +01004502private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
4503
4504 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4505 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4506
4507 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004508 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maierd0e64b02019-03-13 14:15:23 +01004509 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4510 }
4511 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4512 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
4513 log("expecting ASS FAIL like this: ", exp_fail);
4514
4515 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004516 f_perform_clear();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004517}
4518
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004519const CounterNameVals counternames_bsc_bts_assignment := {
4520 { "assignment:attempted", 0 },
4521 { "assignment:completed", 0 },
4522 { "assignment:stopped", 0 },
4523 { "assignment:no_channel", 0 },
4524 { "assignment:timeout", 0 },
4525 { "assignment:failed", 0 },
4526 { "assignment:error", 0 }
4527};
4528
4529const CounterNameVals counternames_bts_assignment := {
4530 { "assignment:attempted_sign", 0 },
4531 { "assignment:attempted_speech", 0 },
4532 { "assignment:completed_sign", 0 },
4533 { "assignment:completed_speech", 0 },
4534 { "assignment:stopped_sign", 0 },
4535 { "assignment:stopped_speech", 0 },
4536 { "assignment:no_channel_sign", 0 },
4537 { "assignment:no_channel_speech", 0 },
4538 { "assignment:timeout_sign", 0 },
4539 { "assignment:timeout_speech", 0 },
4540 { "assignment:failed_sign", 0 },
4541 { "assignment:failed_speech", 0 },
4542 { "assignment:error_sign", 0 },
4543 { "assignment:error_speech", 0 }
4544};
4545
4546function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
4547 var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
4548 f_ctrs_bts_init(bts_count, bts_names);
4549 f_ctrs_bsc_init(counternames_bsc_bts_assignment);
4550}
4551
Harald Welte60aa5762018-03-21 19:33:13 +01004552testcase TC_assignment_codec_fr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004553 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004554 var MSC_ConnHdlr vc_conn;
4555
4556 f_init(1, true);
4557 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004558 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004559
4560 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004561 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004562 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004563
4564 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4565 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4566 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4567 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4568 f_ctrs_bts_verify();
4569
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004570 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004571}
4572
4573testcase TC_assignment_codec_hr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004574 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004575 var MSC_ConnHdlr vc_conn;
4576
4577 f_init(1, true);
4578 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004579 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004580
4581 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004582 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004583 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004584
4585 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4586 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4587 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4588 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4589 f_ctrs_bts_verify();
4590
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004591 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004592}
4593
4594testcase TC_assignment_codec_efr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004595 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004596 var MSC_ConnHdlr vc_conn;
4597
4598 f_init(1, true);
4599 f_sleep(1.0);
4600
4601 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004602 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004603 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004604 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004605}
4606
Philipp Maierd0e64b02019-03-13 14:15:23 +01004607/* Allow 5,90k only (current default config) */
4608private function f_allow_amr_rate_5_90k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004609 f_vty_cfg_msc(BSCVTY, 0, {
4610 "amr-config 12_2k forbidden",
4611 "amr-config 10_2k forbidden",
4612 "amr-config 7_95k forbidden",
4613 "amr-config 7_40k forbidden",
4614 "amr-config 6_70k forbidden",
4615 "amr-config 5_90k allowed",
4616 "amr-config 5_15k forbidden",
4617 "amr-config 4_75k forbidden"
4618 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004619}
4620
4621/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
4622 * ("Config-NB-Code = 1") */
4623private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004624 f_vty_cfg_msc(BSCVTY, 0, {
4625 "amr-config 12_2k allowed",
4626 "amr-config 10_2k forbidden",
4627 "amr-config 7_95k forbidden",
4628 "amr-config 7_40k allowed",
4629 "amr-config 6_70k forbidden",
4630 "amr-config 5_90k allowed",
4631 "amr-config 5_15k forbidden",
4632 "amr-config 4_75k allowed"
4633 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004634}
4635
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004636private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
4637 var charstring tch;
4638 if (fr) {
4639 tch := "tch-f";
4640 } else {
4641 tch := "tch-h";
4642 }
4643 f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
4644}
4645
4646/* Set the AMR start-mode for this TCH back to the default configuration. */
4647private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
4648 f_vty_amr_start_mode_set(fr, "auto");
4649}
4650
Harald Welte60aa5762018-03-21 19:33:13 +01004651testcase TC_assignment_codec_amr_f() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004652 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004653 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004654
4655 /* Note: This setups the codec configuration. The parameter payload in
4656 * mr_conf must be consistant with the parameter codecElements in pars
4657 * and also must match the amr-config in osmo-bsc.cfg! */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004658 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004659 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004660 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004661 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004662
Harald Welte60aa5762018-03-21 19:33:13 +01004663 f_init(1, true);
4664 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004665 f_vty_amr_start_mode_set(true, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004666 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004667
Harald Welte8863fa12018-05-10 20:15:27 +02004668 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004669 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004670
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004671 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4672 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4673 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4674 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4675 f_ctrs_bts_verify();
4676
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004677 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004678 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004679}
4680
4681testcase TC_assignment_codec_amr_h() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004682 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004683 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004684
4685 /* See note above */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004686 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004687 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004688 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004689 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004690
Harald Welte60aa5762018-03-21 19:33:13 +01004691 f_init(1, true);
4692 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004693 f_vty_amr_start_mode_set(false, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004694 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004695
Harald Welte8863fa12018-05-10 20:15:27 +02004696 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004697 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004698
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004699 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4700 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4701 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4702 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4703 f_ctrs_bts_verify();
4704
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004705 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004706 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004707}
4708
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004709/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
4710testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
4711 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4712 var MSC_ConnHdlr vc_conn;
4713
4714 f_init(1, true);
4715 f_sleep(1.0);
4716
4717 /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
4718 * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
4719 * expecting a Channel Mode Modify if the channel type is compatible. */
4720 f_disable_all_sdcch();
4721 f_disable_all_tch_h();
4722
4723 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4724 pars.expect_channel_mode_modify := true;
4725 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4726 vc_conn.done;
4727
4728 f_enable_all_sdcch();
4729 f_enable_all_tch();
4730 f_shutdown_helper();
4731}
4732
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004733/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
4734testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
4735 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4736 var MSC_ConnHdlr vc_conn;
4737
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004738 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4739 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
4740 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy36fe9582022-09-14 15:25:04 +07004741 pars.expect_mr_conf_ie := c_mr_conf_5_90;
4742 pars.expect_mr_conf_ie.multirate_cfg.icmi := false; /* expect ICMI=0, smod=00: */
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004743
4744 f_init(1, true);
4745 f_sleep(1.0);
4746
4747 /* First set nonzero start mode bits */
4748 f_vty_amr_start_mode_set(true, "4");
4749 /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
4750 * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
4751 * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
4752 f_vty_amr_start_mode_set(true, "auto");
4753
4754 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4755 vc_conn.done;
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004756
4757 /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
4758 f_vty_amr_start_mode_set(true, "1");
4759 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004760 f_shutdown_helper();
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004761}
4762
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004763function f_TC_assignment_codec_amr(boolean fr, RSL_IE_MultirateCfg mr_cfg,
4764 bitstring s8_s0, bitstring exp_s8_s0,
4765 charstring start_mode := "1")
Philipp Maierd0e64b02019-03-13 14:15:23 +01004766runs on test_CT {
4767
4768 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4769 var MSC_ConnHdlr vc_conn;
4770
Philipp Maierd0e64b02019-03-13 14:15:23 +01004771 if (fr) {
4772 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4773 } else {
4774 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4775 }
4776 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4777 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004778 pars.expect_mr_conf_ie := { multirate_cfg := mr_cfg };
Philipp Maierd0e64b02019-03-13 14:15:23 +01004779 pars.expect_mr_s0_s7 := exp_s8_s0;
4780
4781 f_init(1, true);
4782 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004783 f_vty_amr_start_mode_set(fr, start_mode);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004784 f_sleep(1.0);
4785
4786 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4787 vc_conn.done;
4788 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004789 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004790}
4791
4792function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
4793runs on test_CT {
4794
4795 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4796 var MSC_ConnHdlr vc_conn;
4797
4798 if (fr) {
4799 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4800 } else {
4801 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4802 }
4803 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4804 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4805
4806 f_init(1, true);
4807 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004808 f_vty_amr_start_mode_set(fr, "1");
Philipp Maierd0e64b02019-03-13 14:15:23 +01004809 f_sleep(1.0);
4810
4811 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
4812 vc_conn.done;
4813 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004814 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004815}
4816
Philipp Maierd0e64b02019-03-13 14:15:23 +01004817/* Set S1, we expect an AMR multirate configuration IE with all four rates
4818 * set. */
4819testcase TC_assignment_codec_amr_f_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004820 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4821 params := '20882208'O));
4822 f_TC_assignment_codec_amr(true, mr_cfg, '00000011'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004823 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004824}
4825
4826/* Set S1, we expect an AMR multirate configuration IE with the lower three
4827 * rates set. */
4828testcase TC_assignment_codec_amr_h_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004829 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4830 params := '208820'O));
4831 f_TC_assignment_codec_amr(false, mr_cfg, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004832 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004833}
4834
4835/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4836 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4837testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004838 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4839 params := '20882208'O));
4840 f_TC_assignment_codec_amr(true, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004841 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004842}
4843
4844/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4845 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4846testcase TC_assignment_codec_amr_h_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004847 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4848 params := '208820'O));
4849 f_TC_assignment_codec_amr(false, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004850 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004851}
4852
4853/* The following block of tests selects more and more rates until all four
4854 * possible rates are in the active set (full rate) */
4855testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004856 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4857 f_TC_assignment_codec_amr(true, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004858 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004859}
4860
4861testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004862 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4863 params := '2080'O));
4864 f_TC_assignment_codec_amr(true, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004865 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004866}
4867
4868testcase TC_assignment_codec_amr_f_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004869 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4870 params := '208820'O));
4871 f_TC_assignment_codec_amr(true, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004872 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004873}
4874
4875testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004876 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4877 params := '20882208'O));
4878 f_TC_assignment_codec_amr(true, mr_cfg, '10010101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004879 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004880}
4881
4882/* The following block of tests selects more and more rates until all three
4883 * possible rates are in the active set (half rate) */
4884testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004885 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4886 f_TC_assignment_codec_amr(false, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004887 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004888}
4889
4890testcase TC_assignment_codec_amr_h_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004891 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4892 params := '2080'O));
4893 f_TC_assignment_codec_amr(false, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004894 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004895}
4896
4897testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004898 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4899 params := '208820'O));
4900 f_TC_assignment_codec_amr(false, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004901 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004902}
4903
4904/* The following block tests what happens when the MSC does offer rate
4905 * configurations that are not supported by the BSC. Normally such situations
4906 * should not happen because the MSC gets informed by the BSC in advance via
4907 * the L3 COMPLETE message which rates are applicable. The MSC should not try
4908 * to offer rates that are not applicable anyway. */
4909
4910testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004911 /* Try to include 12,2k in into the active set even though the channel
4912 * is half rate only. The BSC is expected to remove the 12,0k */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004913 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4914 params := '208820'O));
4915 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004916 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004917}
4918
4919testcase TC_assignment_codec_amr_f_S01234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004920 /* See what happens when all rates are selected at once. Since then
4921 * Also S1 is selected, this setting will be prefered and we should
4922 * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004923 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4924 params := '20882208'O));
4925 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004926 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004927}
4928
4929testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004930 /* Same as above, but with S1 missing, the MSC is then expected to
4931 * select the currently supported rates, which are also 12.2k, 7,40k,
4932 * 5,90k, and 4,75k, into the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004933 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4934 params := '20882208'O));
4935 f_TC_assignment_codec_amr(true, mr_cfg, '11111101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004936 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004937}
4938
4939testcase TC_assignment_codec_amr_f_zero() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004940 /* Try to select no rates at all */
4941 f_TC_assignment_codec_amr_fail(true, '00000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004942 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004943}
4944
4945testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004946 /* Try to select only unsupported rates */
4947 f_TC_assignment_codec_amr_fail(true, '01101000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004948 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004949}
4950
4951testcase TC_assignment_codec_amr_h_S7() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004952 /* Try to select 12,2k for half rate */
4953 f_TC_assignment_codec_amr_fail(false, '10000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004954 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004955}
4956
Neels Hofmeyr21863562020-11-26 00:34:33 +00004957testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004958 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4959 codec_modes := '10010101'B,
4960 params := '20882208'O));
4961 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004962 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004963}
4964
4965testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004966 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4967 codec_modes := '00010101'B,
4968 params := '208820'O));
4969 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B,
Neels Hofmeyr21863562020-11-26 00:34:33 +00004970 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004971 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004972}
4973
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004974testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004975 /* "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 +07004976 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 3,
4977 codec_modes := '10010101'B,
4978 params := '20882208'O));
4979 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004980 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004981}
4982
4983testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004984 /* "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 +07004985 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 2,
4986 codec_modes := '00010101'B,
4987 params := '208820'O));
4988 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004989 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004990}
4991
Philipp Maierac09bfc2019-01-08 13:41:39 +01004992private function f_disable_all_tch_f() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004993 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 borken");
4994 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 borken");
4995 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 borken");
4996 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004997}
4998
4999private function f_disable_all_tch_h() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005000 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 borken");
5001 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005002}
5003
5004private function f_enable_all_tch() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005005 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 unused");
5006 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 unused");
5007 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 unused");
5008 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 unused");
5009 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 unused");
5010 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005011}
5012
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02005013private function f_disable_all_sdcch() runs on test_CT {
5014 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
5015 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
5016 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
5017 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
5018}
5019
5020private function f_enable_all_sdcch() runs on test_CT {
5021 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
5022 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
5023 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
5024 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
5025}
5026
Philipp Maierac09bfc2019-01-08 13:41:39 +01005027/* Allow HR only */
5028private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs on MSC_ConnHdlr {
5029 g_pars := f_gen_test_hdlr_pars();
5030 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5031 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5032 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5033 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5034 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5035 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5036 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005037 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005038}
5039
5040/* Allow FR only */
5041private function f_TC_assignment_codec_xr_exhausted_req_fr(charstring id) runs on MSC_ConnHdlr {
5042 g_pars := f_gen_test_hdlr_pars();
5043 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5044 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5045 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5046 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5047 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5048 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5049 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005050 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005051}
5052
5053/* Allow HR only (expect assignment failure) */
5054private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) runs on MSC_ConnHdlr {
5055 g_pars := f_gen_test_hdlr_pars();
5056 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5057 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5058 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5059 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5060 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5061 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5062 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005063 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005064}
5065
5066/* Allow FR only (expect assignment failure) */
5067private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) runs on MSC_ConnHdlr {
5068 g_pars := f_gen_test_hdlr_pars();
5069 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5070 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5071 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5072 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5073 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5074 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5075 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005076 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005077}
5078
5079/* Allow FR and HR, but prefer FR */
5080private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5081 g_pars := f_gen_test_hdlr_pars();
5082 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5083 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5084 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5085 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5086 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5087 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5088 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5089 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005090 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005091}
5092
5093/* Allow FR and HR, but prefer HR */
5094private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5095 g_pars := f_gen_test_hdlr_pars();
5096 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5097 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5098 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5099 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5100 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5101 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5102 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5103 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005104 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005105}
5106
5107/* Allow FR and HR, but prefer FR */
5108private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5109 g_pars := f_gen_test_hdlr_pars();
5110 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5111 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5112 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5113 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5114 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5115 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5116 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5117 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005118 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005119}
5120
5121/* Allow FR and HR, but prefer HR */
5122private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5123 g_pars := f_gen_test_hdlr_pars();
5124 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5125 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5126 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5127 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5128 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5129 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5130 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5131 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005132 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005133}
5134
5135/* Request a HR channel while all FR channels are exhausted, this is expected
5136 * to work without conflicts */
5137testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
5138 var MSC_ConnHdlr vc_conn;
5139 f_init(1, true);
5140 f_sleep(1.0);
5141 f_enable_all_tch();
5142 f_disable_all_tch_f();
5143 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
5144 vc_conn.done;
5145 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005146 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005147}
5148
5149/* Request a FR channel while all FR channels are exhausted, this is expected
5150 * to fail. */
5151testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
5152 var MSC_ConnHdlr vc_conn;
5153 f_init(1, true);
5154 f_sleep(1.0);
5155 f_enable_all_tch();
5156 f_disable_all_tch_f();
5157 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
5158 vc_conn.done;
5159 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005160 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005161}
5162
5163/* Request a FR (prefered) or alternatively a HR channel while all FR channels
5164 * are exhausted, this is expected to be resolved by selecting a HR channel. */
5165testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
5166 var MSC_ConnHdlr vc_conn;
5167 f_init(1, true);
5168 f_sleep(1.0);
5169 f_enable_all_tch();
5170 f_disable_all_tch_f();
5171 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
5172 vc_conn.done;
5173 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005174 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005175}
5176
5177/* Request a HR (prefered) or alternatively a FR channel while all FR channels
5178 * are exhausted, this is expected to work without conflicts. */
5179testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
5180 var MSC_ConnHdlr vc_conn;
5181 f_init(1, true);
5182 f_sleep(1.0);
5183 f_enable_all_tch();
5184 f_disable_all_tch_f();
5185 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
5186 vc_conn.done;
5187 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005188 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005189}
5190
5191/* Request a FR channel while all HR channels are exhausted, this is expected
5192 * to work without conflicts */
5193testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
5194 var MSC_ConnHdlr vc_conn;
5195 f_init(1, true);
5196 f_sleep(1.0);
5197 f_enable_all_tch();
5198 f_disable_all_tch_h();
5199 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
5200 vc_conn.done;
5201 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005202 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005203}
5204
5205/* Request a HR channel while all HR channels are exhausted, this is expected
5206 * to fail. */
5207testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
5208 var MSC_ConnHdlr vc_conn;
5209 f_init(1, true);
5210 f_sleep(1.0);
5211 f_enable_all_tch();
5212 f_disable_all_tch_h();
5213 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
5214 vc_conn.done;
5215 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005216 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005217}
5218
5219/* Request a HR (prefered) or alternatively a FR channel while all HR channels
5220 * are exhausted, this is expected to be resolved by selecting a FR channel. */
5221testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
5222 var MSC_ConnHdlr vc_conn;
5223 f_init(1, true);
5224 f_sleep(1.0);
5225 f_enable_all_tch();
5226 f_disable_all_tch_h();
5227 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
5228 vc_conn.done;
5229 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005230 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005231}
5232
5233/* Request a FR (prefered) or alternatively a HR channel while all HR channels
5234 * are exhausted, this is expected to work without conflicts. */
5235testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
5236 var MSC_ConnHdlr vc_conn;
5237 f_init(1, true);
5238 f_sleep(1.0);
5239 f_enable_all_tch();
5240 f_disable_all_tch_h();
5241 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
5242 vc_conn.done;
5243 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005244 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005245}
5246
5247/* Allow FR and HR, but prefer HR */
5248private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5249 g_pars := f_gen_test_hdlr_pars();
5250 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5251 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5252 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5253 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5254 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5255 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5256 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5257 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005258 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005259}
5260
5261/* Allow FR and HR, but prefer FR */
5262private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5263 g_pars := f_gen_test_hdlr_pars();
5264 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5265 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5266 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5267 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5268 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5269 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5270 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5271 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005272 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005273}
5274
5275/* Request a HR (prefered) or alternatively a FR channel, it is expected that
5276 * HR, which is the prefered type, is selected. */
5277testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
5278 var MSC_ConnHdlr vc_conn;
5279 f_init(1, true);
5280 f_sleep(1.0);
5281 f_enable_all_tch();
5282 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
5283 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005284 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005285}
5286
5287/* Request a FR (prefered) or alternatively a HR channel, it is expected that
5288 * FR, which is the prefered type, is selected. */
5289testcase TC_assignment_codec_req_fr_hr() runs on test_CT {
5290 var MSC_ConnHdlr vc_conn;
5291 f_init(1, true);
5292 f_sleep(1.0);
5293 f_enable_all_tch();
5294 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_fr_hr));
5295 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005296 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005297}
5298
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005299/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
5300private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
5301 g_pars := f_gen_test_hdlr_pars();
5302 g_pars.ra := '02'O; /* RA containing reason=LU */
5303
5304 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5305 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5306 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5307 var template uint3_t tsc := ?;
5308
5309 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5310 f_create_bssmap_exp(l3_enc);
5311 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5312 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5313
5314 /* we should now have a COMPL_L3 at the MSC */
5315 timer T := 10.0;
5316 T.start;
5317 alt {
5318 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5319 [] T.timeout {
5320 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5321 }
5322 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005323
5324 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005325}
5326testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
5327 var MSC_ConnHdlr vc_conn;
5328 f_init(1, true);
5329 f_sleep(1.0);
5330 f_disable_all_sdcch();
5331 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
5332 vc_conn.done;
5333 f_enable_all_sdcch();
5334 f_shutdown_helper();
5335}
5336
5337/* Request a signalling channel with all SDCCH exhausted, it is
5338 expected that no TCH will be selected for signalling and assigment will fail
5339 because it's dictated by VTY config */
5340testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
5341 var RSL_Message rsl_unused, rsl_msg;
5342 var GsmRrMessage rr;
5343 f_init(1, false);
5344 f_sleep(1.0);
5345 f_vty_allow_tch_for_signalling(false, 0);
5346 f_disable_all_sdcch();
5347
5348 /* RA containing reason=LU */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005349 f_ipa_tx(ts_RSL_CHAN_RQD('02'O, 2342));
5350 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005351 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
5352 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
5353 setverdict(fail, "Expected reject");
5354 }
5355
5356 f_vty_allow_tch_for_signalling(true, 0);
5357 f_enable_all_sdcch();
5358 f_shutdown_helper();
5359}
5360
5361/* Request a voice channel with all SDCCH exhausted, it is
5362 * expected that TCH channel will be allocated since the VTY option is only
5363 * aimed at signalling requests */
5364private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
5365 g_pars := f_gen_test_hdlr_pars();
5366 g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
5367
5368 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5369 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5370 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5371 var template uint3_t tsc := ?;
5372
5373 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5374 f_create_bssmap_exp(l3_enc);
5375 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5376 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5377
5378 /* we should now have a COMPL_L3 at the MSC */
5379 timer T := 10.0;
5380 T.start;
5381 alt {
5382 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5383 [] T.timeout {
5384 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5385 }
5386 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005387 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005388}
5389testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
5390 var MSC_ConnHdlr vc_conn;
5391 f_init(1, true);
5392 f_sleep(1.0);
5393 f_vty_allow_tch_for_signalling(false, 0);
5394 f_disable_all_sdcch();
5395
5396 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
5397 vc_conn.done;
5398
5399 f_vty_allow_tch_for_signalling(true, 0);
5400 f_enable_all_sdcch();
5401 f_shutdown_helper();
5402}
5403
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005404/* Test Osmux setup BSC<->MSC */
5405testcase TC_assignment_osmux_cn() runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005406 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5407 var MSC_ConnHdlr vc_conn;
5408
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005409 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5410 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5411 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiyb9bf00f2022-09-14 15:35:37 +07005412 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02005413 pars.use_osmux_cn := true;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005414
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02005415 g_osmux_enabled_cn := true;
5416 f_init(1, true);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005417 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005418 f_vty_amr_start_mode_set(false, "1");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005419
5420 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5421 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005422
5423 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01005424 f_shutdown_helper();
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005425}
5426
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005427/* Test Osmux setup BTS<->BSC */
5428testcase TC_assignment_osmux_bts() runs on test_CT {
5429 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5430 var MSC_ConnHdlr vc_conn;
5431
5432 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5433 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5434 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005435 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005436 pars.use_osmux_bts := true;
5437
5438 g_osmux_enabled_bts := true;
5439 f_init(1, true);
5440 f_sleep(1.0);
5441 f_vty_amr_start_mode_set(false, "1");
5442
5443 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5444 vc_conn.done;
5445
5446 f_vty_amr_start_mode_restore(false);
5447 f_shutdown_helper();
5448}
5449
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +02005450/* Test non-AMR codecs still work fine as RTP when Osmux is enabled BTS<->BSC<->MSC */
5451testcase TC_assignment_codec_hr_osmux_on() runs on test_CT {
5452 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5453 var MSC_ConnHdlr vc_conn;
5454
5455 g_osmux_enabled_cn := true;
5456 g_osmux_enabled_bts := true;
5457 f_init(1, true);
5458 f_sleep(1.0);
5459 f_ctrs_bsc_and_bts_assignment_init(1);
5460
5461 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5462 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5463 vc_conn.done;
5464
5465 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
5466 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
5467 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
5468 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
5469 f_ctrs_bts_verify();
5470
5471 f_shutdown_helper();
5472}
5473
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005474/* Test Osmux setup BTS<->BSC<->MSC */
5475testcase TC_assignment_osmux() runs on test_CT {
5476 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5477 var MSC_ConnHdlr vc_conn;
5478
5479 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5480 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5481 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005482 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005483 pars.use_osmux_cn := true;
5484 pars.use_osmux_bts := true;
5485
5486 g_osmux_enabled_cn := true;
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
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005499/* test the procedure of the MSC requesting a Classmark Update:
5500 * a) BSSMAP Classmark Request should result in RR CLASSMARK ENQUIRY,
5501 * b) L3 RR CLASSMARK CHANGE should result in BSSMAP CLASSMARK UPDATE */
Harald Welte898113b2018-01-31 18:32:21 +01005502private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005503 g_pars := f_gen_test_hdlr_pars();
5504
Harald Weltea0630032018-03-20 21:09:55 +01005505 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005506 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005507
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005508 BSSAP.send(ts_BSSMAP_ClassmarkRequest);
5509 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
5510
Harald Welte898113b2018-01-31 18:32:21 +01005511 f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
5512 BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
5513 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005514
5515 f_perform_clear();
Harald Welte898113b2018-01-31 18:32:21 +01005516}
5517testcase TC_classmark() runs on test_CT {
5518 var MSC_ConnHdlr vc_conn;
5519 f_init(1, true);
5520 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005521 vc_conn := f_start_handler(refers(f_tc_classmark));
Harald Welte898113b2018-01-31 18:32:21 +01005522 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005523 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005524}
5525
Harald Welteeddf0e92020-06-21 19:42:15 +02005526/* Send a CommonID from the simulated MSC and verify that the information is used to
5527 * fill BSC-internal data structures (specifically, bsc_subscr associated with subscr_conn) */
5528private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
5529 g_pars := f_gen_test_hdlr_pars();
5530 f_MscConnHdlr_init_vty();
5531
5532 f_create_chan_and_exp();
5533 /* we should now have a COMPL_L3 at the MSC */
Harald Welteeddf0e92020-06-21 19:42:15 +02005534
5535 /* Send CommonID */
5536 BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
5537
5538 /* Use VTY to verify that the IMSI of the subscr_conn is set */
5539 var charstring regex := "*(IMSI: " & hex2str(g_pars.imsi) & ")*";
5540 f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
5541
5542 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005543
5544 f_perform_clear();
Harald Welteeddf0e92020-06-21 19:42:15 +02005545}
5546testcase TC_common_id() runs on test_CT {
5547 var MSC_ConnHdlr vc_conn;
5548 f_init(1, true);
5549 f_sleep(1.0);
5550 vc_conn := f_start_handler(refers(f_tc_common_id));
5551 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005552 f_shutdown_helper();
Harald Welteeddf0e92020-06-21 19:42:15 +02005553}
5554
Harald Weltee3bd6582018-01-31 22:51:25 +01005555private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005556 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005557 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005558 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005559
Harald Weltee3bd6582018-01-31 22:51:25 +01005560 /* send the single message we want to send */
5561 f_rsl_send_l3(l3);
5562}
5563
5564private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr {
5565 timer T := sec;
5566 var PDU_BSSAP bssap;
Harald Welte898113b2018-01-31 18:32:21 +01005567 T.start;
5568 alt {
Harald Weltee3bd6582018-01-31 22:51:25 +01005569 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap {
5570 setverdict(fail, "Unexpected BSSMAP ", bssap);
Daniel Willmannafce8662018-07-06 23:11:32 +02005571 mtc.stop;
Harald Welte898113b2018-01-31 18:32:21 +01005572 }
5573 [] T.timeout {
5574 setverdict(pass);
5575 }
5576 }
5577}
5578
Harald Weltee3bd6582018-01-31 22:51:25 +01005579/* unsolicited ASSIGNMENT FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5580private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
5581 f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
5582 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005583 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005584}
Harald Welte898113b2018-01-31 18:32:21 +01005585testcase TC_unsol_ass_fail() runs on test_CT {
5586 var MSC_ConnHdlr vc_conn;
5587 f_init(1, true);
5588 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005589 vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
Harald Welte898113b2018-01-31 18:32:21 +01005590 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005591 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005592}
Harald Welte552620d2017-12-16 23:21:36 +01005593
Harald Welteea99a002018-01-31 20:46:43 +01005594
5595/* unsolicited ASSIGNMENT COMPLETE (without ASSIGN) from MS shouldn't bring BSC down */
5596private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005597 f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
5598 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005599 f_perform_clear();
Harald Welteea99a002018-01-31 20:46:43 +01005600}
5601testcase TC_unsol_ass_compl() runs on test_CT {
5602 var MSC_ConnHdlr vc_conn;
5603 f_init(1, true);
5604 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005605 vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
Harald Welteea99a002018-01-31 20:46:43 +01005606 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005607 f_shutdown_helper();
Harald Welteea99a002018-01-31 20:46:43 +01005608}
5609
5610
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005611/* unsolicited HANDOVER FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5612private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005613 f_est_single_l3(ts_RRM_HandoverFailure('00'O));
5614 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005615 f_perform_clear();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005616}
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005617testcase TC_unsol_ho_fail() runs on test_CT {
5618 var MSC_ConnHdlr vc_conn;
5619 f_init(1, true);
5620 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005621 vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005622 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005623 f_shutdown_helper();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005624}
5625
5626
Harald Weltee3bd6582018-01-31 22:51:25 +01005627/* short message from MS should be ignored */
5628private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005629 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005630 f_create_chan_and_exp();
Harald Weltee3bd6582018-01-31 22:51:25 +01005631 /* we should now have a COMPL_L3 at the MSC */
Harald Weltee3bd6582018-01-31 22:51:25 +01005632
5633 /* send short message */
5634 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
5635 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005636 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005637}
5638testcase TC_err_82_short_msg() runs on test_CT {
5639 var MSC_ConnHdlr vc_conn;
5640 f_init(1, true);
5641 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005642 vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
Harald Weltee3bd6582018-01-31 22:51:25 +01005643 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005644 f_shutdown_helper();
Harald Weltee3bd6582018-01-31 22:51:25 +01005645}
5646
5647
Harald Weltee9e02e42018-01-31 23:36:25 +01005648/* 24.008 8.4 Unknown message must trigger RR STATUS */
5649private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
5650 f_est_single_l3(ts_RRM_UL_REL('00'O));
5651 timer T := 3.0
5652 alt {
5653 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
5654 setverdict(pass);
5655 }
5656 [] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
Harald Welte458fd372018-03-21 11:26:23 +01005657 [] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
Harald Weltee9e02e42018-01-31 23:36:25 +01005658 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005659 f_perform_clear();
Harald Weltee9e02e42018-01-31 23:36:25 +01005660}
5661testcase TC_err_84_unknown_msg() runs on test_CT {
5662 var MSC_ConnHdlr vc_conn;
5663 f_init(1, true);
5664 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005665 vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
Harald Weltee9e02e42018-01-31 23:36:25 +01005666 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005667 f_shutdown_helper();
Harald Weltee9e02e42018-01-31 23:36:25 +01005668}
5669
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005670/***********************************************************************
5671 * Handover
5672 ***********************************************************************/
5673
Harald Welte94e0c342018-04-07 11:33:23 +02005674/* execute a "bts <0-255> trx <0-255> timeslot <0-7> " command on given Dchan */
5675private function f_vty_ts_action(charstring suffix, integer bts_nr, integer trx_nr, integer ts_nr)
5676runs on test_CT {
5677 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5678 " timeslot "&int2str(ts_nr)&" ";
5679 f_vty_transceive(BSCVTY, cmd & suffix);
5680}
5681
Harald Welte261af4b2018-02-12 21:20:39 +01005682/* 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 +07005683private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
5684 uint8_t bts_nr, uint8_t trx_nr,
5685 in RslChannelNr chan_nr)
5686{
Harald Welte261af4b2018-02-12 21:20:39 +01005687 /* FIXME: resolve those from component-global state */
5688 var integer ts_nr := chan_nr.tn;
5689 var integer ss_nr;
5690 if (ischosen(chan_nr.u.ch0)) {
5691 ss_nr := 0;
5692 } else if (ischosen(chan_nr.u.lm)) {
5693 ss_nr := chan_nr.u.lm.sub_chan;
5694 } else if (ischosen(chan_nr.u.sdcch4)) {
5695 ss_nr := chan_nr.u.sdcch4.sub_chan;
5696 } else if (ischosen(chan_nr.u.sdcch8)) {
5697 ss_nr := chan_nr.u.sdcch8.sub_chan;
5698 } else {
5699 setverdict(fail, "Invalid ChanNr ", chan_nr);
Daniel Willmannafce8662018-07-06 23:11:32 +02005700 mtc.stop;
Harald Welte261af4b2018-02-12 21:20:39 +01005701 }
5702
5703 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5704 " timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005705 f_vty_transceive(pt, cmd & suffix);
Harald Welte261af4b2018-02-12 21:20:39 +01005706}
5707
Neels Hofmeyr91401012019-07-11 00:42:35 +02005708/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
5709 * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor
5710 * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
5711 * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
5712 * pair, not really to a specific BTS number. */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005713private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
5714 in RslChannelNr chan_nr, uint8_t new_bts_nr)
5715{
5716 f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
Harald Welte261af4b2018-02-12 21:20:39 +01005717}
5718
5719/* intra-BSC hand-over between BTS0 and BTS1 */
5720private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02005721 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5722 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte261af4b2018-02-12 21:20:39 +01005723
5724 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5725 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5726
Harald Weltea0630032018-03-20 21:09:55 +01005727 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005728 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Harald Welte261af4b2018-02-12 21:20:39 +01005729
5730 var HandoverState hs := {
5731 rr_ho_cmpl_seen := false,
5732 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005733 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005734 expect_target_tsc := c_BtsParams[1].tsc
Harald Welte261af4b2018-02-12 21:20:39 +01005735 };
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005736 /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005737 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
Harald Welte261af4b2018-02-12 21:20:39 +01005738 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5739 f_rslem_suspend(RSL1_PROC);
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005740
5741 /* From the MGW perspective, a handover is is characterized by
5742 * performing one MDCX operation with the MGW. So we expect to see
5743 * one more MDCX during handover. */
5744 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5745
Harald Welte261af4b2018-02-12 21:20:39 +01005746 alt {
5747 [] as_handover(hs);
Harald Welte261af4b2018-02-12 21:20:39 +01005748 }
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005749
Philipp Maier4dae0652018-11-12 12:03:26 +01005750 /* Since this is an internal handover we expect the BSC to inform the
5751 * MSC about the event */
5752 BSSAP.receive(tr_BSSMAP_HandoverPerformed);
5753
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005754 /* Check the amount of MGCP transactions is still consistant with the
5755 * test expectation */
5756 f_check_mgcp_expectations()
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005757
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005758 var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
5759
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005760 /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
5761 * 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 +02005762 f_verify_encr_info(chan_act);
5763
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005764 f_chan_act_verify_tsc(chan_act, c_BtsParams[1].tsc);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005765
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005766 f_perform_clear(RSL1, RSL1_PROC);
5767
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005768 f_sleep(0.5);
Harald Welte261af4b2018-02-12 21:20:39 +01005769}
5770
5771testcase TC_ho_int() runs on test_CT {
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005772 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte261af4b2018-02-12 21:20:39 +01005773 var MSC_ConnHdlr vc_conn;
5774 f_init(2, true);
5775 f_sleep(1.0);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005776
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005777 pars.expect_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005778
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005779 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005780
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005781 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
Harald Welte261af4b2018-02-12 21:20:39 +01005782 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005783
5784 /* from f_establish_fully() */
5785 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5786 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5787 /* from handover */
5788 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5789 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5790 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5791 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005792 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5793 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005794 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005795 f_shutdown_helper(ho := true);
Harald Welte261af4b2018-02-12 21:20:39 +01005796}
Harald Weltee9e02e42018-01-31 23:36:25 +01005797
Oliver Smith7eabd312021-07-12 14:18:56 +02005798function 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 +02005799 var MSC_ConnHdlr vc_conn;
5800 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5801 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
5802
5803 f_init(2, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02005804 f_vty_encryption_a5(enc_a5);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005805 f_sleep(1.0);
5806
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005807 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005808
5809 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
5810 vc_conn.done;
5811
5812 /* from f_establish_fully() */
5813 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5814 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5815 /* from handover */
5816 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5817 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5818 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5819 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005820 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5821 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005822 f_ctrs_bsc_and_bts_verify();
Oliver Smith7eabd312021-07-12 14:18:56 +02005823 f_vty_encryption_a5_reset();
Oliver Smith39f53072022-10-27 14:44:04 +02005824 f_shutdown_helper(ho := true);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005825}
5826
5827testcase TC_ho_int_a5_0() runs on test_CT {
5828 f_tc_ho_int_a5('01'O);
5829}
5830
5831testcase TC_ho_int_a5_1() runs on test_CT {
5832 f_tc_ho_int_a5('02'O);
5833}
5834
5835testcase TC_ho_int_a5_3() runs on test_CT {
5836 f_tc_ho_int_a5('08'O);
5837}
5838
5839testcase TC_ho_int_a5_4() runs on test_CT {
Oliver Smith7eabd312021-07-12 14:18:56 +02005840 f_tc_ho_int_a5('10'O, "0 1 3 4");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005841}
5842
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005843/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
5844private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
5845 g_pars := f_gen_test_hdlr_pars();
5846 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5847 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005848
5849 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5850 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5851
5852 f_establish_fully(ass_cmd, exp_compl);
5853 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
5854
5855 var HandoverState hs := {
5856 rr_ho_cmpl_seen := false,
5857 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005858 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005859 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005860 };
5861 /* issue hand-over command on VTY */
5862 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
5863 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5864 f_rslem_suspend(RSL1_PROC);
5865
5866 /* From the MGW perspective, a handover is is characterized by
5867 * performing one MDCX operation with the MGW. So we expect to see
5868 * one more MDCX during handover. */
5869 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5870
5871 var RSL_Message rsl;
5872 var PDU_ML3_NW_MS l3;
5873 var RslChannelNr new_chan_nr;
5874 var GsmArfcn arfcn;
5875 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
5876 l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
5877 if (not ischosen(l3.msgs.rrm.handoverCommand)) {
5878 setverdict(fail, "Expected handoverCommand");
5879 mtc.stop;
5880 }
5881 }
5882 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
5883 new_chan_nr, arfcn);
5884
5885 f_rslem_register(0, new_chan_nr, RSL1_PROC);
5886
5887 /* resume processing of RSL DChan messages, which was temporarily suspended
5888 * before performing a hand-over */
5889 f_rslem_resume(RSL1_PROC);
5890 RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
5891
5892 f_sleep(1.0);
5893
5894 /* Handover fails because no HANDO DET appears on the new lchan,
5895 * and the old lchan reports a Radio Link Failure. */
5896 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
5897
5898 var PDU_BSSAP rx_clear_request;
5899 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5900 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5901 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5902
5903 var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
5904
5905 var MgcpCommand mgcp;
5906 interleave {
5907 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
5908 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005909 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005910 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005911 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005912 }
5913 [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005914 [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005915 RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005916 f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005917 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005918 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5919 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5920 }
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005921 }
5922
5923 f_sleep(0.5);
5924 setverdict(pass);
5925}
5926testcase TC_ho_int_radio_link_failure() runs on test_CT {
5927 var MSC_ConnHdlr vc_conn;
5928 f_init(2, true);
5929 f_sleep(1.0);
5930
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005931 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005932
5933 vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
5934 vc_conn.done;
5935
5936 /* from f_establish_fully() */
5937 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5938 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5939 /* from handover */
5940 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5941 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
5942 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5943 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005944 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5945 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005946 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005947 f_shutdown_helper(ho := true);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005948}
5949
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005950/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005951private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005952 var MgcpCommand mgcp;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005953 var template MgcpResponse mgcp_resp;
5954 var MGCP_RecvFrom mrf;
5955 var template MgcpMessage msg_resp;
5956 var template MgcpMessage msg_dlcx := {
5957 command := tr_DLCX()
5958 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005959
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005960 if (g_pars.aoip) {
5961 MGCP.receive(tr_DLCX()) -> value mgcp {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005962 log("Got first DLCX: ", mgcp);
5963 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005964 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005965
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005966 MGCP.receive(tr_DLCX()) -> value mgcp {
5967 log("Got second DLCX: ", mgcp);
5968 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
5969 };
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005970 } else {
5971 /* For SCCPLite, BSC doesn't handle the MSC-side */
5972 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
5973 log("Got first DLCX: ", mrf.msg.command);
5974 msg_resp := {
5975 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
5976 }
5977 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
5978 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005979 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005980}
5981
Oliver Smithc9a5f532022-10-21 11:32:23 +02005982private function f_ho_out_of_this_bsc(template (omit) BSSMAP_oldToNewBSSIEs exp_oldToNewBSSIEs := omit,
5983 boolean skip_meas_rep := false) runs on MSC_ConnHdlr {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005984
Oliver Smithc9a5f532022-10-21 11:32:23 +02005985 if (not skip_meas_rep) {
5986 var NcellReports neighbor_rep := {
5987 { rxlev := 20, bcch_freq := 0, bsic := 11 }
5988 };
5989 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
5990 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
5991 l3_mr, 0));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005992
Oliver Smithc9a5f532022-10-21 11:32:23 +02005993 BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
5994 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005995
5996 f_sleep(0.5);
5997 /* The MSC negotiates Handover Request and Handover Request Ack with
5998 * the other BSS and comes back with a BSSMAP Handover Command
5999 * containing an RR Handover Command coming from the target BSS... */
6000
6001 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6002 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6003 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6004 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6005 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6006
6007 /* expect the Handover Command to go out on RR */
6008 var RSL_Message rsl_ho_cmd
6009 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6010 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6011 var RSL_IE_Body rsl_ho_cmd_l3;
6012 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6013 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6014 setverdict(fail);
6015 } else {
6016 log("Found L3 Info: ", rsl_ho_cmd_l3);
6017 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6018 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6019 setverdict(fail);
6020 } else {
6021 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6022 setverdict(pass);
6023 }
6024 }
6025
6026 /* When the other BSS has reported a completed handover, this side is
6027 * torn down. */
6028
6029 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_HANDOVER_SUCCESSFUL;
6030 var BssmapCause cause := enum2int(cause_val);
6031 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6032
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006033 f_expect_dlcx_conns();
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006034
6035 interleave {
6036 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
6037 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
6038 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006039 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
6040 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
6041 }
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006042 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006043 setverdict(pass);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006044}
6045
6046private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
6047 g_pars := f_gen_test_hdlr_pars();
6048 var PDU_BSSAP ass_req := f_gen_ass_req();
6049 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6050 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6051 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6052 f_establish_fully(ass_req, exp_compl);
6053
6054 f_ho_out_of_this_bsc();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006055}
6056testcase TC_ho_out_of_this_bsc() runs on test_CT {
6057 var MSC_ConnHdlr vc_conn;
6058
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006059 f_init_vty();
6060 f_bts_0_cfg(BSCVTY,
6061 {"neighbor-list mode automatic",
6062 "handover 1",
6063 "handover algorithm 2",
6064 "handover2 window rxlev averaging 1",
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006065 "no neighbors",
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006066 "neighbor lac 99 arfcn 123 bsic any"});
6067 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6068
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006069 f_init(1, true);
6070 f_sleep(1.0);
6071
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006072 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006073
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006074 vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
6075 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006076
6077 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6078 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6079 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6080 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6081 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6082 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
6083 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006084 f_shutdown_helper(ho := true);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006085}
6086
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006087private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6088 template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
Vadim Yanitskiy2ef6a2f2020-10-08 23:17:32 +07006089 template (present) OCT1 dlci := ?,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006090 octetstring l3 := '0123456789'O)
6091runs on MSC_ConnHdlr {
Neels Hofmeyr43654812020-09-25 01:35:35 +02006092 /* The old lchan and conn should still be active. See that arbitrary L3
6093 * is still going through. */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006094 rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
Neels Hofmeyr43654812020-09-25 01:35:35 +02006095 var template PDU_BSSAP exp_data := {
6096 discriminator := '1'B,
6097 spare := '0000000'B,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006098 dlci := dlci,
6099 lengthIndicator := lengthof(l3),
Neels Hofmeyr43654812020-09-25 01:35:35 +02006100 pdu := {
6101 dtap := l3
6102 }
6103 };
6104 BSSAP.receive(exp_data);
6105 setverdict(pass);
6106}
6107
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006108private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6109 template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006110 template (value) OCT1 dlci := '00'O,
6111 octetstring l3 := '0123456789'O)
6112runs on MSC_ConnHdlr {
6113 BSSAP.send(PDU_BSSAP:{
6114 discriminator := '1'B,
6115 spare := '0000000'B,
6116 dlci := dlci,
6117 lengthIndicator := lengthof(l3),
6118 pdu := {
6119 dtap := l3
6120 }
6121 });
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006122 rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006123 setverdict(pass);
6124}
6125
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006126/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
6127 * simply never sends a BSSMAP Handover Command. */
6128private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006129 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006130
6131 var PDU_BSSAP ass_req := f_gen_ass_req();
6132 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6133 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6134 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6135 f_establish_fully(ass_req, exp_compl);
6136
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006137 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006138 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6139
6140 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6141
6142 /* osmo-bsc should time out 10 seconds after the handover started.
6143 * Let's give it a bit extra. */
6144 f_sleep(15.0);
6145
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006146 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006147 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006148 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006149}
6150testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
6151 var MSC_ConnHdlr vc_conn;
6152
6153 f_init(1, true);
6154 f_sleep(1.0);
6155
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006156 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006157
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006158 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
6159 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006160
6161 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6162 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6163 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6164 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6165 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6166 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6167 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006168 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006169}
6170
6171/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
6172 * RR Handover Failure. */
6173private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006174 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006175
6176 var PDU_BSSAP ass_req := f_gen_ass_req();
6177 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6178 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6179 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6180 f_establish_fully(ass_req, exp_compl);
6181
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006182 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006183 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6184
6185 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6186
6187 f_sleep(0.5);
6188 /* The MSC negotiates Handover Request and Handover Request Ack with
6189 * the other BSS and comes back with a BSSMAP Handover Command
6190 * containing an RR Handover Command coming from the target BSS... */
6191
6192 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6193 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6194 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6195 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6196 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6197
6198 /* expect the Handover Command to go out on RR */
6199 var RSL_Message rsl_ho_cmd
6200 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6201 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6202 var RSL_IE_Body rsl_ho_cmd_l3;
6203 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6204 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6205 setverdict(fail);
6206 } else {
6207 log("Found L3 Info: ", rsl_ho_cmd_l3);
6208 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6209 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6210 setverdict(fail);
6211 } else {
6212 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6213 setverdict(pass);
6214 }
6215 }
6216
6217 f_sleep(0.2);
6218 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
6219
6220 /* Should tell the MSC about the failure */
6221 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6222
6223 f_sleep(1.0);
6224
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006225 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006226 f_sleep(1.0);
6227
6228 setverdict(pass);
6229 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006230 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006231}
6232testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
6233 var MSC_ConnHdlr vc_conn;
6234
6235 f_init(1, true);
6236 f_sleep(1.0);
6237
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006238 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006239
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006240 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
6241 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006242
6243 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6244 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6245 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6246 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6247 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6248 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
6249 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006250 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006251}
6252
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006253/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
6254 * (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 +02006255 * and the lchan is released. */
6256private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006257 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006258
6259 var PDU_BSSAP ass_req := f_gen_ass_req();
6260 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6261 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6262 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6263 f_establish_fully(ass_req, exp_compl);
6264
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006265 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006266 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6267
6268 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6269
6270 f_sleep(0.5);
6271 /* The MSC negotiates Handover Request and Handover Request Ack with
6272 * the other BSS and comes back with a BSSMAP Handover Command
6273 * containing an RR Handover Command coming from the target BSS... */
6274
6275 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6276 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6277 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6278 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6279 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6280
6281 /* expect the Handover Command to go out on RR */
6282 var RSL_Message rsl_ho_cmd
6283 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6284 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6285 var RSL_IE_Body rsl_ho_cmd_l3;
6286 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6287 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6288 setverdict(fail);
6289 } else {
6290 log("Found L3 Info: ", rsl_ho_cmd_l3);
6291 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6292 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6293 setverdict(fail);
6294 } else {
6295 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6296 setverdict(pass);
6297 }
6298 }
6299
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006300 /* We get neither success nor failure report from the remote BSS. Eventually T8 times out and we run into 3GPP
6301 * TS 48.008 3.1.5.3.3 "Abnormal Conditions": Clear Request should go to the MSC, and RR should be released
6302 * after Clear Command */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006303
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006304 var PDU_BSSAP rx_clear_request;
Neels Hofmeyre1797aa2019-07-09 19:34:04 +02006305 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
6306 log("Got BSSMAP Clear Request");
6307 /* Instruct BSC to clear channel */
6308 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6309 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6310
6311 var MgcpCommand mgcp;
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006312 interleave {
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01006313 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
6314 log("Got Deact SACCH");
6315 }
Harald Welte924b6ea2019-02-04 01:05:34 +01006316 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
Neels Hofmeyr211169d2018-11-07 00:37:29 +01006317 log("Got RR Release");
6318 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02006319 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006320 log("Got RF Chan Rel");
6321 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02006322 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006323 }
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006324 }
6325
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006326 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006327 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006328 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006329
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006330 setverdict(pass);
6331 f_sleep(1.0);
6332}
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006333testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006334 var MSC_ConnHdlr vc_conn;
6335
6336 f_init(1, true);
6337 f_sleep(1.0);
6338
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006339 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006340
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006341 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006342 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006343
6344 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6345 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6346 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6347 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6348 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6349 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6350 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006351 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006352}
6353
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006354private 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 +01006355 var PDU_BSSAP rx_bssap;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006356 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6357 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6358 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6359 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6360 * before we get started. */
6361 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6362 f_rslem_register(0, new_chan_nr);
6363 g_chan_nr := new_chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06006364 var uint3_t expect_target_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006365 f_sleep(1.0);
6366
6367 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6368 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006369 var default as_media := activate(as_Media());
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006370
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01006371 var PDU_BSSAP ho_req := f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
6372 cell_id_source := g_pars.cell_id_source,
6373 oldToNewBSSIEs := oldToNewBSSIEs,
6374 enc := g_pars.encr);
6375 if (g_pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr) {
6376 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, ho_req));
6377 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6378 } else {
6379 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, omit));
6380 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6381 BSSAP.send(ho_req);
6382 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006383
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006384 alt {
6385 [] BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap {
6386 if (g_pars.expect_ho_fail) {
6387 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6388 "Expected Handover Request to fail, but got Handover Request Ack")
6389 }
6390 }
6391 [] BSSAP.receive(tr_BSSMAP_HandoverFailure) -> value rx_bssap {
6392 if (not g_pars.expect_ho_fail) {
6393 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6394 "Expected Handover Request to succeed, but got Handover Failure")
6395 }
6396 // TODO: evaluate correct cause value. But osmo-bsc doesn't seem to send meaningful causes yet!
6397 // For now just accept any cause.
6398 BSSAP.receive(tr_BSSMAP_ClearRequest);
6399 setverdict(pass);
6400 return;
6401 }
6402 }
6403
Oliver Smith7a8594a2023-02-13 14:30:49 +01006404 if (g_pars.expect_ho_fail_lchan_est) {
6405 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6406 setverdict(pass);
Oliver Smitha1cbec52023-02-21 12:44:12 +01006407
6408 /* When we let MGCP MDCX run into a timeout, it's still in the
6409 * queue and additionally after BSSAP HandoverFailure, two DLCX
Oliver Smith30eb8822023-03-06 12:31:53 +01006410 * get sent (for AoIP, for SCCPlite one DLCX). */
Oliver Smitha1cbec52023-02-21 12:44:12 +01006411 if (g_pars.ignore_mgw_mdcx) {
Oliver Smith30eb8822023-03-06 12:31:53 +01006412 if (g_pars.aoip) {
6413 MGCP.receive(tr_MDCX);
6414 MGCP.receive(tr_DLCX);
6415 MGCP.receive(tr_DLCX);
6416 } else {
6417 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_MDCX}));
6418 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_DLCX}));
6419 }
Oliver Smitha1cbec52023-02-21 12:44:12 +01006420 }
Oliver Smith7a8594a2023-02-13 14:30:49 +01006421 return;
6422 }
6423
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006424 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6425
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006426 /* we're sure that the channel activation is done now, verify the parameters in it */
6427 var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
6428 f_verify_encr_info(chan_act);
6429 f_chan_act_verify_tsc(chan_act, expect_target_tsc);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006430
Neels Hofmeyr46e16e52022-02-23 17:04:00 +01006431 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.codecList)) {
6432 if (not g_pars.aoip) {
6433 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6434 "handoverRequestAck: Expected no Speech Codec List (BSS Supported), because this is not AoIP");
6435 }
6436 /* TODO: check actual codecs? */
6437 } else {
6438 if (g_pars.aoip) {
6439 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6440 "handoverRequestAck: Expected Speech Codec List (BSS Supported), but none found");
6441 }
6442 }
6443
6444 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.speechCodec)) {
6445 if (not g_pars.aoip) {
6446 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6447 "handoverRequestAck: Expected no Speech Codec (Chosen), because this is not AoIP");
6448 }
6449 /* TODO: check actual codec? */
6450 } else {
6451 if (g_pars.aoip) {
6452 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6453 "handoverRequestAck: Expected Speech Codec (Chosen), but none found");
6454 }
6455 }
6456
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006457 var octetstring ho_command_str;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006458 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6459 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6460 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6461 log("L3 Info in HO Request Ack is ", ho_command);
6462
6463 var GsmArfcn arfcn;
6464 var RslChannelNr actual_new_chan_nr;
6465 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6466 actual_new_chan_nr, arfcn);
6467
6468 if (actual_new_chan_nr != new_chan_nr) {
6469 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6470 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6471 setverdict(fail);
6472 return;
6473 }
6474 log("Handover Command chan_nr is", actual_new_chan_nr);
6475
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006476 var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
6477 if (not match(got_tsc, expect_target_tsc)) {
6478 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6479 expect_target_tsc, " got ", got_tsc);
6480 mtc.stop;
6481 } else {
6482 log("handoverCommand: verified TSC = ", got_tsc);
6483 }
6484
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006485 /* Check the Cipher Mode Setting IE (shall be present during inter-RAT handover) */
6486 if (ispresent(ho_command.msgs.rrm.handoverCommand.cipherModeSetting)) {
6487 var CipherModeSetting_TV cms := ho_command.msgs.rrm.handoverCommand.cipherModeSetting;
6488 var template (present) CipherModeSetting_TV tr_cms := {
6489 sC := '0'B, /* no ciphering by default */
6490 algorithmIdentifier := '000'B,
6491 elementIdentifier := ?
6492 };
6493 if (ispresent(g_pars.encr) and g_pars.encr.enc_alg_expect != '01'O) { /* A5/N */
6494 tr_cms.algorithmIdentifier := f_cipher_mode_bssmap_to_rr(g_pars.encr.enc_alg_expect);
6495 tr_cms.sC := '1'B;
6496 }
6497 if (not match(cms, tr_cms)) {
6498 setverdict(fail, "RR Handover Command: unexpected Cipher Mode Setting IE: ",
6499 cms, ", expected: ", tr_cms);
6500 }
6501 } else {
6502 setverdict(fail, "RR Handover Command: Cipher Mode Setting IE is not present");
6503 }
6504
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006505 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6506 * tells the MS to handover to the new lchan. Here comes the new MS on
6507 * the new lchan with a Handover RACH: */
6508
6509 /* send handover detect */
6510
6511 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6512
6513 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6514
6515 /* send handover complete over the new channel */
6516
6517 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_HandoverComplete('00'O));
6518 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
6519 enc_PDU_ML3_MS_NW(l3_tx)));
6520
6521 BSSAP.receive(tr_BSSMAP_HandoverComplete);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006522 deactivate(as_media);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006523 setverdict(pass);
6524}
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006525
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006526private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006527 var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006528 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
6529 if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
6530 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006531 }
6532 if (g_pars.exp_fast_return) {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006533 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006534 } else {
6535 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006536 }
6537 f_ho_into_this_bsc(id, oldToNewBSSIEs);
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006538 if (g_pars.expect_ho_fail) {
6539 f_perform_clear_no_lchan();
Oliver Smith7a8594a2023-02-13 14:30:49 +01006540 } else if (g_pars.expect_ho_fail_lchan_est) {
6541 BSSAP.receive(tr_BSSMAP_ClearRequest);
6542 f_perform_clear_no_lchan();
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006543 } else {
6544 f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
6545 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006546 setverdict(pass);
6547}
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006548function 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 +01006549 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006550
6551 f_init(1, true);
6552 f_sleep(1.0);
6553
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006554 f_vty_encryption_a5(vty_a5_cfg);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006555 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006556
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006557 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6558 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006559
6560 vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
6561 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006562
6563 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006564 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006565 if (pars.expect_ho_fail) {
6566 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6567 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:failed");
Oliver Smith7a8594a2023-02-13 14:30:49 +01006568 } else if (pars.expect_ho_fail_lchan_est) {
6569 f_ctrs_bsc_and_bts_add(0, "handover:error");
6570 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006571 } else {
6572 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6573 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
6574 }
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006575 f_ctrs_bsc_and_bts_verify();
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006576
6577 f_vty_encryption_a5_reset();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006578}
6579
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006580testcase TC_ho_into_this_bsc() runs on test_CT {
6581 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6582 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006583 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006584}
6585
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006586function f_tc_ho_into_this_bsc_a5(TestHdlrEncrParams encr, charstring vty_a5_cfg := VTY_A5_DEFAULT,
6587 boolean expect_fail := false) runs on test_CT {
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006588 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006589 pars.encr := encr;
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006590 pars.expect_ho_fail := expect_fail;
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006591 f_tc_ho_into_this_bsc_main(pars, vty_a5_cfg);
Oliver Smith39f53072022-10-27 14:44:04 +02006592 f_shutdown_helper(ho := true);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006593}
6594
6595testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006596 f_tc_ho_into_this_bsc_a5(f_encr_params('01'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006597}
6598
6599testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006600 f_tc_ho_into_this_bsc_a5(f_encr_params('02'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006601}
6602
6603testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006604 f_tc_ho_into_this_bsc_a5(f_encr_params('08'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006605}
6606
6607testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006608 f_tc_ho_into_this_bsc_a5(f_encr_params('10'O, kc128 := true), "3 4");
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006609}
6610
Neels Hofmeyr1951be22022-02-16 16:21:07 +01006611/* Report: in inter-BSC incoming handover, when the MSC omits the Chosen Encryption Algorithm IE in the Handover Request
6612 * message, then osmo-bsc starts an unencrypted lchan even if A5/0 is not permitted.
6613 *
6614 * This test verifies that the Encryption Information is present in the Channel Activation when the Chosen Enc Alg is
6615 * omitted.
6616 *
6617 * Related: SYS#5839
6618 */
6619testcase TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() runs on test_CT {
6620 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O, alg_chosen := omit));
6621}
6622
6623testcase TC_ho_into_this_bsc_a5_1_3() runs on test_CT {
6624 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O));
6625}
6626
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006627/* Send a permitted algo mask that does not intersect with osmo-bsc.cfg */
6628testcase TC_ho_into_this_bsc_a5_mismatch() runs on test_CT {
6629 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '18'O, alg_expect := '10'O), "0 1",
6630 expect_fail := true); // 0x18 = A5/3 and A5/4
6631}
6632
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006633testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
6634 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6635 pars.host_aoip_tla := "::6";
6636 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006637 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006638}
6639
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006640/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006641 to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006642 channel is later released (RR CHannel Release), should trigger inclusion of
6643 IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
6644 neighbors. */
6645testcase TC_srvcc_eutran_to_geran() runs on test_CT {
6646 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6647 pars.last_used_eutran_plmn := '323454'O;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006648 pars.exp_fast_return := true;
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006649 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006650
6651 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6652 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6653 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006654 f_shutdown_helper(ho := true);
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006655}
6656
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006657/* Same as TC_srvcc_eutran_to_geran, but enables ciphering on the target channel. */
6658testcase TC_srvcc_eutran_to_geran_a5_3() runs on test_CT {
6659 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6660 pars.encr := f_encr_params('08'O); /* only A5/3 */
6661 pars.last_used_eutran_plmn := '323454'O;
6662 pars.exp_fast_return := true;
6663 f_tc_ho_into_this_bsc_main(pars);
6664
6665 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6666 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6667 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006668 f_shutdown_helper(ho := true);
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006669}
6670
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006671/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
6672 on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
6673 list when the channel is released. */
6674testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
6675 f_init_vty();
6676 f_vty_allow_srvcc_fast_return(true, 0)
6677
6678 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6679 pars.last_used_eutran_plmn := '323454'O;
6680 pars.exp_fast_return := false;
6681 f_tc_ho_into_this_bsc_main(pars);
6682 f_vty_allow_srvcc_fast_return(false, 0);
6683 f_shutdown_helper();
6684}
6685
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01006686/* Same as TC_srvcc_eutran_to_geran, but using SAI as serving Cell Identifier. SYS#5838 */
6687testcase TC_srvcc_eutran_to_geran_src_sai() runs on test_CT {
6688 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6689 pars.last_used_eutran_plmn := '323454'O;
6690 pars.cell_id_source := valueof(ts_CellID_SAI('123456'O, 300, 444));
6691 f_tc_ho_into_this_bsc_main(pars);
6692
6693 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6694 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6695 f_ctrs_bsc_and_bts_verify();
6696 f_shutdown_helper();
6697}
6698
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006699private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
6700 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
6701 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
6702 f_ho_into_this_bsc(id, oldToNewBSSIEs);
6703 f_ho_out_of_this_bsc(oldToNewBSSIEs);
6704 setverdict(pass);
6705}
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006706
6707private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
6708 runs on test_CT {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006709 var MSC_ConnHdlr vc_conn;
6710 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6711
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006712 f_init_vty();
6713 f_bts_0_cfg(BSCVTY,
6714 {"neighbor-list mode automatic",
6715 "handover 1",
6716 "handover algorithm 2",
6717 "handover2 window rxlev averaging 1",
6718 "no neighbors",
6719 "neighbor lac 99 arfcn 123 bsic any"});
6720 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6721
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006722 f_init(1, true);
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006723 if (disable_fast_return) {
6724 f_vty_allow_srvcc_fast_return(true, 0);
6725 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006726 f_sleep(1.0);
6727
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006728 f_ctrs_bsc_and_bts_handover_init();
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006729
6730 pars.last_used_eutran_plmn := '323454'O;
6731 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6732 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
6733
6734 vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
6735 vc_conn.done;
6736
6737 f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
6738 f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
6739 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
6740 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
6741 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
6742 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006743
6744 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
6745 f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006746 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006747
6748 if (disable_fast_return) {
6749 f_vty_allow_srvcc_fast_return(false, 0);
6750 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006751 f_shutdown_helper();
6752}
6753
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006754/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
6755 BSS Information" IE with "Last Used E-UTRAN PLMN Id".
6756 Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
6757 IE with "Last Used E-UTRAN PLMN Id" from first step. */
6758testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
6759 f_tc_srvcc_eutran_to_geran_ho_out_main(false);
6760}
6761/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
6762 * independently of fast-reture allowed/forbidden in local BTS */
6763testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
6764 f_tc_srvcc_eutran_to_geran_ho_out_main(true);
6765}
6766
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006767private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
6768 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6769 f_rslem_register(0, new_chan_nr);
6770 g_chan_nr := new_chan_nr;
6771 f_sleep(1.0);
6772
6773 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6774 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6775 activate(as_Media());
6776
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006777 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006778 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006779 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006780
6781 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6782
6783 var PDU_BSSAP rx_bssap;
6784 var octetstring ho_command_str;
6785
6786 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6787
6788 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6789 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6790 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6791 log("L3 Info in HO Request Ack is ", ho_command);
6792
6793 var GsmArfcn arfcn;
6794 var RslChannelNr actual_new_chan_nr;
6795 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6796 actual_new_chan_nr, arfcn);
6797
6798 if (actual_new_chan_nr != new_chan_nr) {
6799 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6800 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6801 setverdict(fail);
6802 return;
6803 }
6804 log("Handover Command chan_nr is", actual_new_chan_nr);
6805
Neels Hofmeyr61ca08d2019-05-06 23:52:22 +02006806 /* For deterministic test results, give some time for the MGW endpoint to be configured */
6807 f_sleep(1.0);
6808
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006809 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6810 * tells the MS to handover to the new lchan. In this case, the MS
6811 * reports a Handover Failure to the old BSS, which forwards a BSSMAP
6812 * Handover Failure to the MSC. The procedure according to 3GPP TS
6813 * 48.008 3.1.5.3.2 "Handover Failure" is then that the MSC sends a
6814 * BSSMAP Clear Command: */
6815
6816 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6817 var BssmapCause cause := enum2int(cause_val);
6818 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6819
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006820 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006821 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006822 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006823
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006824 setverdict(pass);
6825 f_sleep(1.0);
6826
6827 setverdict(pass);
6828}
6829testcase TC_ho_in_fail_msc_clears() runs on test_CT {
6830 var MSC_ConnHdlr vc_conn;
6831 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6832
6833 f_init(1, true);
6834 f_sleep(1.0);
6835
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006836 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006837
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006838 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6839 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006840
6841 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
6842 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006843
6844 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6845 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6846 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6847 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6848 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006849 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006850}
6851
6852private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
6853 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6854 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6855 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6856 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6857 * before we get started. */
6858 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6859 f_rslem_register(0, new_chan_nr);
6860 g_chan_nr := new_chan_nr;
6861 f_sleep(1.0);
6862
6863 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6864 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6865 activate(as_Media());
6866
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006867 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006868 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006869 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006870
6871 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6872
6873 var PDU_BSSAP rx_bssap;
6874 var octetstring ho_command_str;
6875
6876 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6877
6878 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6879 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6880 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6881 log("L3 Info in HO Request Ack is ", ho_command);
6882
6883 var GsmArfcn arfcn;
6884 var RslChannelNr actual_new_chan_nr;
6885 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6886 actual_new_chan_nr, arfcn);
6887
6888 if (actual_new_chan_nr != new_chan_nr) {
6889 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6890 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6891 setverdict(fail);
6892 return;
6893 }
6894 log("Handover Command chan_nr is", actual_new_chan_nr);
6895
6896 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6897 * tells the MS to handover to the new lchan. Here comes the new MS on
6898 * the new lchan with a Handover RACH: */
6899
6900 /* send handover detect */
6901
6902 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6903
6904 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6905
6906 /* The MSC chooses to clear the connection now, maybe we got the
6907 * Handover RACH on the new cell but the MS still signaled Handover
6908 * Failure to the old BSS? */
6909
6910 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6911 var BssmapCause cause := enum2int(cause_val);
6912 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6913
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006914 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006915 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006916 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006917
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006918 f_sleep(1.0);
6919}
6920testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
6921 var MSC_ConnHdlr vc_conn;
6922 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6923
6924 f_init(1, true);
6925 f_sleep(1.0);
6926
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006927 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006928
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006929 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6930 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006931
6932 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
6933 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006934
6935 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6936 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6937 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6938 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6939 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006940 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006941}
6942
6943/* The new BSS's lchan times out before the MSC decides that handover failed. */
6944private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
6945 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6946 f_rslem_register(0, new_chan_nr);
6947 g_chan_nr := new_chan_nr;
6948 f_sleep(1.0);
6949
6950 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6951 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01006952 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006953
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006954 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006955 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006956 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006957
6958 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6959
6960 var PDU_BSSAP rx_bssap;
6961 var octetstring ho_command_str;
6962
6963 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6964
6965 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6966 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6967 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6968 log("L3 Info in HO Request Ack is ", ho_command);
6969
6970 var GsmArfcn arfcn;
6971 var RslChannelNr actual_new_chan_nr;
6972 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6973 actual_new_chan_nr, arfcn);
6974
6975 if (actual_new_chan_nr != new_chan_nr) {
6976 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6977 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6978 setverdict(fail);
6979 return;
6980 }
6981 log("Handover Command chan_nr is", actual_new_chan_nr);
6982
6983 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6984 * tells the MS to handover to the new lchan. But the MS never shows up
6985 * on the new lchan. */
6986
6987 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6988
6989 /* Did osmo-bsc also send a Clear Request? */
6990 timer T := 0.5;
6991 T.start;
6992 alt {
6993 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
6994 [] T.timeout { }
6995 }
6996
6997 /* MSC plays along with a Clear Command (no matter whether osmo-bsc
6998 * asked for it, this is a Handover Failure after all). */
6999
7000 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
7001 var BssmapCause cause := enum2int(cause_val);
7002 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7003
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007004 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007005 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007006 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007007
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007008 f_sleep(1.0);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007009}
7010testcase TC_ho_in_fail_no_detect() runs on test_CT {
7011 var MSC_ConnHdlr vc_conn;
7012 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7013
Oliver Smithd49f46d2023-03-08 12:23:13 +01007014 pars.fail_on_dlcx := false;
7015
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007016 f_init(1, true);
7017 f_sleep(1.0);
7018
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007019 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007020
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007021 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7022 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007023
7024 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect), pars);
7025 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007026
7027 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7028 f_ctrs_bsc_and_bts_add(0, "handover:error");
7029 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7030 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7031 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007032 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007033}
7034
7035/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
7036private function f_tc_ho_in_fail_no_detect2(charstring id) runs on MSC_ConnHdlr {
7037 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
7038 f_rslem_register(0, new_chan_nr);
7039 g_chan_nr := new_chan_nr;
7040 f_sleep(1.0);
7041
7042 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
7043 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01007044 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007045
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007046 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007047 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02007048 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007049
7050 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
7051
7052 var PDU_BSSAP rx_bssap;
7053 var octetstring ho_command_str;
7054
7055 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
7056
7057 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
7058 log("Received L3 Info in HO Request Ack: ", ho_command_str);
7059 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
7060 log("L3 Info in HO Request Ack is ", ho_command);
7061
7062 var GsmArfcn arfcn;
7063 var RslChannelNr actual_new_chan_nr;
7064 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
7065 actual_new_chan_nr, arfcn);
7066
7067 if (actual_new_chan_nr != new_chan_nr) {
7068 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
7069 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
7070 setverdict(fail);
7071 return;
7072 }
7073 log("Handover Command chan_nr is", actual_new_chan_nr);
7074
7075 /* Now the MSC forwards the RR Handover Command to the other BSC, which
7076 * tells the MS to handover to the new lchan. But the MS never shows up
7077 * on the new lchan. */
7078
7079 BSSAP.receive(tr_BSSMAP_HandoverFailure);
7080
7081 /* MSC plays dumb and sends no Clear Command */
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007082 var PDU_BSSAP rx_clear_request;
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02007083
7084 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request {
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007085 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
7086 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7087 };
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007088 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007089 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007090 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007091
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007092 f_sleep(1.0);
7093}
7094testcase TC_ho_in_fail_no_detect2() runs on test_CT {
7095 var MSC_ConnHdlr vc_conn;
7096 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7097
Oliver Smith735b47c2023-02-15 16:03:54 +01007098 pars.fail_on_dlcx := false;
7099
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007100 f_init(1, true);
7101 f_sleep(1.0);
7102
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007103 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007104
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007105 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7106 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007107
7108 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
7109 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007110
7111 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7112 f_ctrs_bsc_and_bts_add(0, "handover:error");
7113 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7114 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7115 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007116 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007117}
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01007118
Oliver Smith7a8594a2023-02-13 14:30:49 +01007119testcase TC_ho_in_fail_mgw_mdcx_timeout() runs on test_CT {
7120 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7121
7122 pars.ignore_mgw_mdcx := true;
7123 pars.expect_ho_fail_lchan_est := true;
7124
7125 f_tc_ho_into_this_bsc_main(pars);
7126 f_shutdown_helper(ho := true);
7127}
7128
Oliver Smith4eed06f2023-02-15 15:43:19 +01007129testcase TC_ho_in_fail_ipa_crcx_timeout() runs on test_CT {
7130 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7131
7132 pars.ignore_ipa_media := true;
7133 pars.expect_ho_fail_lchan_est := true;
7134 pars.fail_on_dlcx := false;
7135
7136 f_tc_ho_into_this_bsc_main(pars);
7137 f_shutdown_helper(ho := true);
7138}
7139
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007140/* An incoming inter-BSC HO can either issue the Handover Request message attached to the initial SCCP N-Connect (as in
7141 * the other tests we have so far), or the first CR can be "empty" with the BSSAP request following later. Test the
7142 * empty N-Connect case. */
7143testcase TC_ho_into_this_bsc_sccp_cr_without_bssap() runs on test_CT {
7144 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7145 pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr := false;
7146 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02007147 f_shutdown_helper(ho := true);
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007148}
7149
Neels Hofmeyr91401012019-07-11 00:42:35 +02007150type record of charstring Commands;
7151
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007152private function f_bts_0_cfg(TELNETasp_PT pt, Commands cmds := {})
Neels Hofmeyr91401012019-07-11 00:42:35 +02007153{
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007154 f_vty_enter_cfg_bts(pt, 0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007155 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007156 f_vty_transceive(pt, cmds[i]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007157 }
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007158 f_vty_transceive(pt, "end");
Neels Hofmeyr91401012019-07-11 00:42:35 +02007159}
7160
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01007161private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
7162{
7163 f_vty_enter_cfg_cs7_inst(pt, 0);
7164 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
7165 f_vty_transceive(pt, cmds[i]);
7166 }
7167 f_vty_transceive(pt, "end");
7168}
7169
Neels Hofmeyr91401012019-07-11 00:42:35 +02007170private function f_probe_for_handover(charstring log_label,
7171 charstring log_descr,
7172 charstring handover_vty_cmd,
7173 boolean expect_handover,
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007174 boolean is_inter_bsc_handover := false,
7175 template uint3_t expect_target_tsc := ?)
Neels Hofmeyr91401012019-07-11 00:42:35 +02007176runs on MSC_ConnHdlr
7177{
Neels Hofmeyrb3fc8982020-05-11 00:16:42 +02007178 /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
7179 * lchans to be established on bts 1 or bts 2. */
7180 f_rslem_suspend(RSL1_PROC);
7181 f_rslem_suspend(RSL2_PROC);
7182
Neels Hofmeyr91401012019-07-11 00:42:35 +02007183 var RSL_Message rsl;
7184
7185 var charstring log_msg := " (expecting handover)"
7186 if (not expect_handover) {
7187 log_msg := " (expecting NO handover)";
7188 }
7189 log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg);
7190 f_vty_transceive(BSCVTY, handover_vty_cmd);
7191
Neels Hofmeyr91401012019-07-11 00:42:35 +02007192 timer T := 2.0;
7193 T.start;
7194
7195 alt {
7196 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
7197 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
7198 log("Rx L3 from net: ", l3);
7199 if (ischosen(l3.msgs.rrm.handoverCommand)) {
7200 var RslChannelNr new_chan_nr;
7201 var GsmArfcn arfcn;
7202 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
7203 new_chan_nr, arfcn);
7204 log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
7205 log(l3.msgs.rrm.handoverCommand);
7206
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007207 /* Verify correct TSC in handoverCommand */
7208 var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
7209 if (not match(got_tsc, expect_target_tsc)) {
7210 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
7211 expect_target_tsc, " got ", got_tsc);
7212 mtc.stop;
7213 } else {
7214 log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
7215 expect_target_tsc, ")");
7216 }
7217
Neels Hofmeyr91401012019-07-11 00:42:35 +02007218 /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
7219 * matter on which BTS it really is, we're not going to follow through an entire handover
7220 * anyway. */
7221 f_rslem_register(0, new_chan_nr, RSL1_PROC);
7222 f_rslem_resume(RSL1_PROC);
7223 f_rslem_register(0, new_chan_nr, RSL2_PROC);
7224 f_rslem_resume(RSL2_PROC);
7225
7226 if (expect_handover and not is_inter_bsc_handover) {
7227 setverdict(pass);
7228 log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected.");
7229 } else {
7230 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. "
7231 & log_label & ": " & log_descr);
7232 }
7233
7234 log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
7235 /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with
7236 * Handover Failure. */
7237 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
7238
7239 /* target BTS is told to release lchan again; don't care which BTS nor what messages. */
7240 f_sleep(0.5);
7241 RSL1.clear;
7242 RSL2.clear;
7243 log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)");
7244 break;
7245 } else {
7246 repeat;
7247 }
7248 }
7249 [] BSSAP.receive(tr_BSSMAP_HandoverRequired) {
7250 if (expect_handover and is_inter_bsc_handover) {
7251 setverdict(pass);
7252 log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected.");
7253 } else {
7254 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. "
7255 & log_label & ": " & log_descr);
7256 }
7257
7258 log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)");
7259
7260 /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to
7261 * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required,
7262 * setting a short timeout and waiting is the only way. */
7263 log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out...");
7264 f_sleep(1.5);
7265 log("f_probe_for_handover(" & log_label & "): ...done");
7266
7267 break;
7268 }
7269 [] T.timeout {
7270 if (expect_handover) {
7271 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. "
7272 & log_label & ": " & log_descr);
7273 } else {
7274 setverdict(pass);
7275 log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected.");
7276 }
7277 log("f_probe_for_handover(" & log_label & "): done (got no Handover)");
7278 break;
7279 }
7280 }
7281
7282 f_rslem_resume(RSL1_PROC);
7283 f_rslem_resume(RSL2_PROC);
7284 f_sleep(3.0);
7285 RSL.clear;
7286
7287 log("f_probe_for_handover(" & log_label & "): done clearing");
7288}
7289
7290/* Test the effect of various neighbor configuration scenarios:
7291 *
7292 * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0.
7293 * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO.
7294 */
7295private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
7296 g_pars := f_gen_test_hdlr_pars();
7297 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
7298 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007299
7300 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
7301 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
7302
7303 /* Establish lchan at bts 0 */
7304 f_establish_fully(ass_cmd, exp_compl);
7305
7306 /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */
7307 f_vty_enter_cfg_network(BSCVTY);
7308 f_vty_transceive(BSCVTY, "timer T7 1");
7309 f_vty_transceive(BSCVTY, "end");
7310}
7311
7312private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
7313 f_tc_ho_neighbor_config_start();
7314
7315 /*
7316 * bts 0 ARFCN 871 BSIC 10
7317 * bts 1 ARFCN 871 BSIC 11
7318 * bts 2 ARFCN 871 BSIC 12
7319 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7320 */
7321
7322 log("f_tc_ho_neighbor_config: 1. No 'neighbor' config");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007323 f_bts_0_cfg(BSCVTY, {"no neighbors"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007324 f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
7325 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007326 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007327
7328 f_probe_for_handover("1.b", "HO to unknown cell does not start",
7329 "handover any to arfcn 13 bsic 39",
7330 false);
7331
7332 f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error",
7333 "handover any to arfcn 871 bsic 12",
7334 false);
7335
7336 f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
7337 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007338 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007339
7340 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007341}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007342testcase TC_ho_neighbor_config_1() runs on test_CT {
7343 var MSC_ConnHdlr vc_conn;
7344 f_init(3, true, guard_timeout := 60.0);
7345 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007346 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007347 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
7348 vc_conn.done;
7349
7350 /* f_tc_ho_neighbor_config_start() */
7351 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7352 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7353
7354 /* 1.a */
7355 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7356 * handover quickly by sending a Handover Failure message. */
7357 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7358 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7359 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7360 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007361 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7362 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007363
7364 /* 1.b */
7365 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7366 f_ctrs_bsc_and_bts_add(0, "handover:error");
7367
7368 /* 1.c */
7369 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7370 f_ctrs_bsc_and_bts_add(0, "handover:error");
7371
7372 /* 1.d */
7373 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7374 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7375 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7376 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007377 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7378 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007379
7380 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007381 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007382}
7383
Neels Hofmeyr91401012019-07-11 00:42:35 +02007384private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
7385 f_tc_ho_neighbor_config_start();
7386
7387 /*
7388 * bts 0 ARFCN 871 BSIC 10
7389 * bts 1 ARFCN 871 BSIC 11
7390 * bts 2 ARFCN 871 BSIC 12
7391 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7392 */
7393
7394 log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007395 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007396 f_sleep(0.5);
7397
7398 f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
7399 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007400 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007401
7402 f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
7403 "handover any to arfcn 871 bsic 12",
7404 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007405 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007406}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007407testcase TC_ho_neighbor_config_2() runs on test_CT {
7408 var MSC_ConnHdlr vc_conn;
7409 f_init(3, true, guard_timeout := 50.0);
7410 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007411 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007412 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
7413 vc_conn.done;
7414
7415 /* f_tc_ho_neighbor_config_start() */
7416 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7417 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7418
7419 /* 2.a */
7420 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7421 * handover quickly by sending a Handover Failure message. */
7422 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7423 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7424 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7425 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007426 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7427 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007428
7429 /* 2.b */
7430 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7431 f_ctrs_bsc_and_bts_add(0, "handover:error");
7432
7433 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007434 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007435}
7436
Neels Hofmeyr91401012019-07-11 00:42:35 +02007437private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
7438 f_tc_ho_neighbor_config_start();
7439
7440 /*
7441 * bts 0 ARFCN 871 BSIC 10
7442 * bts 1 ARFCN 871 BSIC 11
7443 * bts 2 ARFCN 871 BSIC 12
7444 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7445 */
7446
7447 log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007448 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007449 f_sleep(0.5);
7450
7451 f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor",
7452 "handover any to arfcn 871 bsic 11",
7453 false);
7454 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",
7455 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007456 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007457 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007458}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007459testcase TC_ho_neighbor_config_3() runs on test_CT {
7460 var MSC_ConnHdlr vc_conn;
7461 f_init(3, true, guard_timeout := 50.0);
7462 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007463 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007464 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
7465 vc_conn.done;
7466
7467 /* f_tc_ho_neighbor_config_start() */
7468 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7469 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7470
7471 /* 3.a */
7472 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7473 f_ctrs_bsc_and_bts_add(0, "handover:error");
7474
7475 /* 3.b */
7476 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7477 * handover quickly by sending a Handover Failure message. */
7478 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7479 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7480 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7481 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007482 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7483 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007484
7485 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007486 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007487}
7488
Neels Hofmeyr91401012019-07-11 00:42:35 +02007489private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
7490 f_tc_ho_neighbor_config_start();
7491
7492 /*
7493 * bts 0 ARFCN 871 BSIC 10
7494 * bts 1 ARFCN 871 BSIC 11
7495 * bts 2 ARFCN 871 BSIC 12
7496 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7497 */
7498
7499 log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007500 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007501 f_sleep(0.5);
7502
7503 f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor",
7504 "handover any to arfcn 871 bsic 11",
7505 false);
7506 f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor",
7507 "handover any to arfcn 871 bsic 12",
7508 false);
7509 f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
7510 "handover any to arfcn 123 bsic 45",
7511 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007512 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007513}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007514testcase TC_ho_neighbor_config_4() runs on test_CT {
7515 var MSC_ConnHdlr vc_conn;
7516 f_init(3, true, guard_timeout := 50.0);
7517 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007518 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007519 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
7520 vc_conn.done;
7521
7522 /* f_tc_ho_neighbor_config_start() */
7523 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7524 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7525
7526 /* 4.a */
7527 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7528 f_ctrs_bsc_and_bts_add(0, "handover:error");
7529
7530 /* 4.b */
7531 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7532 f_ctrs_bsc_and_bts_add(0, "handover:error");
7533
7534 /* 4.c */
7535 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7536 * handover quickly by timing out after the Handover Required message */
7537 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7538 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7539 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7540 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7541
7542 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007543 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007544}
7545
Neels Hofmeyr91401012019-07-11 00:42:35 +02007546private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
7547 f_tc_ho_neighbor_config_start();
7548
7549 /*
7550 * bts 0 ARFCN 871 BSIC 10
7551 * bts 1 ARFCN 871 BSIC 11
7552 * bts 2 ARFCN 871 BSIC 12
7553 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7554 */
7555
7556 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 +02007557 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007558 f_sleep(0.5);
7559
7560 f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
7561 "handover any to arfcn 871 bsic 12",
7562 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007563 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007564}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007565testcase TC_ho_neighbor_config_5() runs on test_CT {
7566 var MSC_ConnHdlr vc_conn;
7567 f_init(3, true);
7568 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007569 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007570 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
7571 vc_conn.done;
7572
7573 /* f_tc_ho_neighbor_config_start() */
7574 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7575 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7576
7577 /* 5 */
7578 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7579 * handover quickly by timing out after the Handover Required message */
7580 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7581 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7582 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7583 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7584
7585 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007586 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007587}
7588
Neels Hofmeyr91401012019-07-11 00:42:35 +02007589private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
7590 f_tc_ho_neighbor_config_start();
7591
7592 /*
7593 * bts 0 ARFCN 871 BSIC 10
7594 * bts 1 ARFCN 871 BSIC 11
7595 * bts 2 ARFCN 871 BSIC 12
7596 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7597 */
7598
7599 log("f_tc_ho_neighbor_config: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:"
7600 & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007601 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007602 f_sleep(0.5);
7603
7604 f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
7605 "handover any to arfcn 871 bsic 12",
7606 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007607 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007608}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007609testcase TC_ho_neighbor_config_6() runs on test_CT {
7610 var MSC_ConnHdlr vc_conn;
7611 f_init(3, true);
7612 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007613 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007614 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
7615 vc_conn.done;
7616
7617 /* f_tc_ho_neighbor_config_start() */
7618 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7619 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7620
7621 /* 6.a */
7622 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7623 * handover quickly by timing out after the Handover Required message */
7624 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7625 f_ctrs_bsc_and_bts_add(0, "handover:error");
7626
7627 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007628 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007629}
7630
Neels Hofmeyr91401012019-07-11 00:42:35 +02007631private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
7632 f_tc_ho_neighbor_config_start();
7633
7634 /*
7635 * bts 0 ARFCN 871 BSIC 10
7636 * bts 1 ARFCN 871 BSIC 11
7637 * bts 2 ARFCN 871 BSIC 12
7638 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7639 */
7640
7641 log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:"
7642 & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007643 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007644 f_sleep(0.5);
7645
7646 f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
7647 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007648 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007649 f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
7650 "handover any to arfcn 123 bsic 45",
7651 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007652 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007653}
Neels Hofmeyr91401012019-07-11 00:42:35 +02007654testcase TC_ho_neighbor_config_7() runs on test_CT {
7655 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf2b88032020-06-16 00:35:04 +02007656 f_init(3, true, guard_timeout := 50.0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007657 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007658 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007659 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
7660 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007661
7662 /* f_tc_ho_neighbor_config_start() */
7663 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7664 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7665
7666 /* 7.a */
7667 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7668 * handover quickly by sending a Handover Failure message. */
7669 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7670 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7671 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7672 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007673 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7674 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007675
7676 /* 7.b */
7677 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7678 * handover quickly by timing out after the Handover Required message */
7679 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7680 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7681 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7682 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7683
7684 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007685 f_shutdown_helper(ho := true);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007686}
7687
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007688/* OS#3041: Open and close N connections in a normal fashion, and expect no
7689 * BSSMAP Reset just because of that. */
7690testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
7691 var default d;
7692 var integer i;
7693 var DchanTuple dt;
7694
7695 f_init();
7696
7697 /* Wait for initial BSSMAP Reset to pass */
7698 f_sleep(4.0);
7699
7700 d := activate(no_bssmap_reset());
7701
7702 /* Setup up a number of connections and RLSD them again from the MSC
7703 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7704 * Let's do it some more times for good measure. */
Harald Weltec3260d92018-06-11 17:48:16 +02007705 for (i := 0; i < 4; i := i+1) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007706 /* Since we're doing a lot of runs, give each one a fresh
7707 * T_guard from the top. */
7708 T_guard.start;
7709
7710 /* Setup a BSSAP connection and clear it right away. This is
7711 * the MSC telling the BSC about a planned release, it's not an
7712 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007713 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007714
7715 /* MSC disconnects (RLSD). */
7716 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
7717 }
7718
7719 /* In the buggy behavior, a timeout of 2 seconds happens between above
7720 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7721 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7722 f_sleep(4.0);
7723
7724 deactivate(d);
7725 f_shutdown_helper();
7726}
Harald Welte552620d2017-12-16 23:21:36 +01007727
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007728/* OS#3041: Open and close N connections in a normal fashion, and expect no
7729 * BSSMAP Reset just because of that. Invoke the release by a BSSMAP Clear from
7730 * the MSC. */
7731testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
7732 var default d;
7733 var integer i;
7734 var DchanTuple dt;
7735 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007736 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
7737 var BssmapCause cause := enum2int(cause_val);
7738
7739 f_init();
7740
7741 /* Wait for initial BSSMAP Reset to pass */
7742 f_sleep(4.0);
7743
7744 d := activate(no_bssmap_reset());
7745
7746 /* Setup up a number of connections and RLSD them again from the MSC
7747 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7748 * Let's do it some more times for good measure. */
7749 for (i := 0; i < 8; i := i+1) {
7750 /* Since we're doing a lot of runs, give each one a fresh
7751 * T_guard from the top. */
7752 T_guard.start;
7753
7754 /* Setup a BSSAP connection and clear it right away. This is
7755 * the MSC telling the BSC about a planned release, it's not an
7756 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007757 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007758
7759 /* Instruct BSC to clear channel */
7760 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7761
7762 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007763 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007764 }
7765
7766 /* In the buggy behavior, a timeout of 2 seconds happens between above
7767 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7768 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7769 f_sleep(4.0);
7770
7771 deactivate(d);
7772 f_shutdown_helper();
7773}
7774
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007775/* OS#3041: Open and close N connections in a normal fashion, and expect no
7776 * BSSMAP Reset just because of that. Close connections from the MS side with a
7777 * Release Ind on RSL. */
7778testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
7779 var default d;
7780 var integer i;
7781 var DchanTuple dt;
7782 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007783 var integer j;
7784
7785 f_init();
7786
7787 /* Wait for initial BSSMAP Reset to pass */
7788 f_sleep(4.0);
7789
7790 d := activate(no_bssmap_reset());
7791
7792 /* Setup up a number of connections and RLSD them again from the MSC
7793 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7794 * Let's do it some more times for good measure. */
7795 for (i := 0; i < 8; i := i+1) {
7796 /* Since we're doing a lot of runs, give each one a fresh
7797 * T_guard from the top. */
7798 T_guard.start;
7799
7800 /* Setup a BSSAP connection and clear it right away. This is
7801 * the MSC telling the BSC about a planned release, it's not an
7802 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007803 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007804
7805 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007806 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007807
7808 /* expect Clear Request on MSC side */
7809 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
7810
7811 /* Instruct BSC to clear channel */
7812 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
7813 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7814
7815 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007816 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007817 }
7818
7819 /* In the buggy behavior, a timeout of 2 seconds happens between above
7820 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7821 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7822 f_sleep(4.0);
7823
7824 deactivate(d);
7825 f_shutdown_helper();
7826}
7827
Harald Welte94e0c342018-04-07 11:33:23 +02007828/***********************************************************************
7829 * IPA style dynamic PDCH
7830 ***********************************************************************/
7831
7832private function f_dyn_ipa_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7833 template (omit) RSL_Cause nack := omit)
7834runs on test_CT {
7835 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7836 var RSL_Message rsl_unused;
7837 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7838 f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
7839 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007840 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007841 if (istemplatekind(nack, "omit")) {
7842 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007843 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007844 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007845 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007846 }
7847}
7848
7849private function f_dyn_ipa_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7850 template (omit) RSL_Cause nack := omit)
7851runs on test_CT {
7852 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7853 var RSL_Message rsl_unused;
7854 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7855 f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
7856 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007857 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_DEACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007858 if (istemplatekind(nack, "omit")) {
7859 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007860 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007861 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007862 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007863 }
7864}
7865
7866private function f_ts_dyn_mode_get(integer bts_nr, integer trx_nr, integer ts_nr)
7867runs on test_CT return charstring {
7868 var charstring cmd, resp;
7869 cmd := "show timeslot "&int2str(bts_nr)&" "&int2str(trx_nr)&" "&int2str(ts_nr);
Stefan Sperlingcff13562018-11-13 15:24:06 +01007870 return f_vty_transceive_match_regexp_retry(BSCVTY, cmd, "*\((*)\)*", 0, 4, 1.0);
Harald Welte94e0c342018-04-07 11:33:23 +02007871}
7872
7873private function f_ts_dyn_mode_assert(integer bts_nr, integer trx_nr, integer ts_nr,
7874 template charstring exp)
7875runs on test_CT {
7876 var charstring mode := f_ts_dyn_mode_get(bts_nr, trx_nr, ts_nr);
7877 if (not match(mode, exp)) {
7878 setverdict(fail, "Unexpected TS Mode: ", mode);
Daniel Willmannafce8662018-07-06 23:11:32 +02007879 mtc.stop;
Harald Welte94e0c342018-04-07 11:33:23 +02007880 }
7881}
7882
7883private function f_ts_set_chcomb(integer bts_nr, integer trx_nr, integer ts_nr, charstring chcomb)
7884runs on test_CT {
7885 f_vty_enter_cfg_ts(BSCVTY, bts_nr, trx_nr, ts_nr);
7886 f_vty_transceive(BSCVTY, "phys_chan_config " & chcomb);
7887 f_vty_transceive(BSCVTY, "end");
7888}
7889
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007890
7891private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
7892 var integer i;
7893 for (i := 0; i < 8; i := i + 1) {
7894 f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
7895 }
7896}
7897
Harald Welte94e0c342018-04-07 11:33:23 +02007898private const charstring TCHF_MODE := "TCH/F mode";
7899private const charstring TCHH_MODE := "TCH/H mode";
7900private const charstring PDCH_MODE := "PDCH mode";
7901private const charstring NONE_MODE := "NONE mode";
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007902private const charstring SDCCH8_MODE := "SDCCH8 mode";
Harald Welte94e0c342018-04-07 11:33:23 +02007903
7904/* Test IPA PDCH activation / deactivation triggered by VTY */
7905testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
7906 var RSL_Message rsl_unused;
7907
7908 /* change Timeslot 6 before f_init() starts RSL */
7909 f_init_vty();
7910 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7911 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7912
7913 f_init(1, false);
7914 f_sleep(1.0);
7915
7916 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7917
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007918 log("TCH/F_PDCH pchan starts out in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007919 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7920 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007921 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7922 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007923 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007924 log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007925 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7926
7927 /* De-activate it via VTY */
7928 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7929 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007930 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007931 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7932
7933 /* re-activate it via VTY */
7934 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn);
7935 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007936 log("TCH/F_PDCH pchan, PDCH ACT via VTY, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007937 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7938
7939 /* and finally de-activate it again */
7940 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7941 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007942 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007943 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7944
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007945 /* clean up config */
7946 f_ts_set_chcomb(0, 0, 6, "PDCH");
7947
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007948 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007949}
7950
7951/* Test IPA PDCH activation NACK */
7952testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
7953 var RSL_Message rsl_unused;
7954
7955 /* change Timeslot 6 before f_init() starts RSL */
7956 f_init_vty();
7957 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7958 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7959
7960 f_init(1, false);
7961 f_sleep(1.0);
7962
7963 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7964
7965 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7966 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007967 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7968 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007969 f_sleep(1.0);
7970 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7971
7972 /* De-activate it via VTY */
7973 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7974 f_sleep(1.0);
7975 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7976
7977 /* re-activate it via VTY, but fail that; check BSC still assumes TCH/F mode */
7978 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn, RSL_ERR_EQUIPMENT_FAIL);
7979 f_sleep(1.0);
7980 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7981
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007982 /* clean up config */
7983 f_ts_set_chcomb(0, 0, 6, "PDCH");
7984
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007985 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007986}
7987
7988
7989/***********************************************************************
7990 * Osmocom style dynamic PDCH
7991 ***********************************************************************/
7992
7993private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7994 template (omit) RSL_Cause nack := omit)
7995runs on test_CT {
7996 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7997 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007998 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007999 /* FIXME: no VTY command to activate Osmocom PDCH !! */
8000 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008001 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT(chan_nr, ?));
Harald Welte94e0c342018-04-07 11:33:23 +02008002 if (istemplatekind(nack, "omit")) {
8003 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008004 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02008005 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008006 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02008007 }
8008}
8009
8010private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
8011 template (omit) RSL_Cause nack := omit)
8012runs on test_CT {
8013 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
8014 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02008015 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02008016 /* FIXME: no VTY command to activate Osmocom PDCH !! */
8017 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008018 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008019 if (istemplatekind(nack, "omit")) {
8020 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008021 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008022 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008023 //f_ipa_tx(ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02008024 }
8025}
8026
8027/* Test Osmocom dyn PDCH activation / deactivation triggered by VTY */
8028testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
8029 var RSL_Message rsl_unused;
8030
8031 /* change Timeslot 6 before f_init() starts RSL */
8032 f_init_vty();
8033 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8034 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8035
8036 f_init(1, false);
8037 f_sleep(1.0);
8038
8039 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8040
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008041 log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02008042 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8043 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008044 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008045
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008046 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02008047 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008048 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 +02008049 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
8050
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008051 /* clean up config */
8052 f_ts_set_chcomb(0, 0, 6, "PDCH");
8053
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008054 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008055}
8056
8057/* Test Osmocom dyn PDCH activation NACK behavior */
8058testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
8059 var RSL_Message rsl_unused;
8060
8061 /* change Timeslot 6 before f_init() starts RSL */
8062 f_init_vty();
8063 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8064 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8065
8066 f_init(1, false);
8067 f_sleep(1.0);
8068
8069 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8070
8071 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8072 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008073 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008074
8075 /* NACK this activation and expect the "show timeslot" mode still to be NONE */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008076 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte94e0c342018-04-07 11:33:23 +02008077 f_sleep(1.0);
8078 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8079
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008080 /* clean up config */
8081 f_ts_set_chcomb(0, 0, 6, "PDCH");
8082
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008083 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008084}
8085
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008086/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
8087testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
8088 var RSL_Message rsl_unused, rsl_msg;
8089 var DchanTuple dt;
8090 var BSSAP_N_CONNECT_ind rx_c_ind;
8091
8092 /* change Timeslot 6 before f_init() starts RSL */
8093 f_init_vty();
8094 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8095 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8096
8097 f_init(1, false);
8098 f_sleep(1.0);
8099
8100 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8101
8102 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8103 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8104 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008105 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008106
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008107 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008108 f_sleep(1.0);
8109 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8110 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8111
8112 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8113 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008114 var DchanTuples sdcch_cleanup := {};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008115 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008116 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008117 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008118 sdcch_cleanup := sdcch_cleanup & { dt };
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008119 }
8120
8121 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008122 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8123 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8124 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008125
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008126 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008127 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008128 dt.idx := {0, 0};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008129
8130 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008131 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8132 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008133 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
8134
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008135 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 +02008136 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8137 dt.sccp_conn_id := rx_c_ind.connectionId;
8138 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8139
8140 /* Instruct BSC to clear channel */
8141 var BssmapCause cause := 0;
8142 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008143 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008144
8145 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008146 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8147 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008148 f_sleep(1.0);
8149 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8150
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008151 /* Clean up SDCCH lchans */
8152 for (i := 0; i < lengthof(sdcch_cleanup); i := i + 1) {
8153 f_perform_clear_test_ct(sdcch_cleanup[i]);
8154 }
8155
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008156 /* clean up config */
8157 f_ts_set_chcomb(0, 0, 6, "PDCH");
8158
8159 f_shutdown_helper();
8160}
8161
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008162/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
8163testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
8164 var ASP_RSL_Unitdata rsl_ud;
8165 var integer i;
8166 var integer chreq_total, chreq_nochan;
8167
8168 f_init_vty();
8169 for (i := 1; i < 8; i := i + 1) {
8170 if (i == 2) {
8171 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8172 } else {
8173 f_ts_set_chcomb(0, 0, i, "PDCH");
8174 }
8175 }
8176 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8177
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008178 f_init(1, guard_timeout := 60.0);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008179
8180 /* The dyn TS want to activate PDCH mode, ACK that. */
8181 var RslChannelNr chan_nr;
8182 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008183 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
8184 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008185
8186 f_sleep(1.0);
8187
8188 /* Exhaust all dedicated SDCCH lchans.
8189 /* GSM 44.018 Table 9.1.8.2:
8190 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
8191 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008192 var DchanTuples chan_cleanup := {};
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008193 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008194 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 +02008195 }
8196
8197 /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008198 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 +02008199 /* Also occupy the seven other SDCCH of the dyn TS */
8200 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008201 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 +01008202 }
8203
8204 /* Clean up SDCCH lchans */
8205 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8206 f_perform_clear_test_ct(chan_cleanup[i]);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008207 }
8208
8209 /* clean up config */
8210 f_ts_reset_chcomb(0);
8211
8212 f_shutdown_helper();
8213}
8214
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008215/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
8216 SDCCH8 would end up in having no free TCH, then BSC should decide to activate
8217 it as TCH directly instead. SYS#5309. */
8218testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
8219 var RSL_Message rsl_unused, rsl_msg;
8220 var DchanTuple dt;
8221 var BSSAP_N_CONNECT_ind rx_c_ind;
8222 var integer i;
8223
8224 /* change Timeslot 6 before f_init() starts RSL */
8225 f_init_vty();
8226 for (i := 1; i < 8; i := i + 1) {
8227 if (i == 6) {
8228 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8229 } else {
8230 f_ts_set_chcomb(0, 0, i, "PDCH");
8231 }
8232 }
8233 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8234
8235 f_init(1, false);
8236 f_sleep(1.0);
8237
8238 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8239
8240 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8241 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8242 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008243 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008244
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008245 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008246 f_sleep(1.0);
8247 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8248 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8249
8250 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8251 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008252 var DchanTuples chan_cleanup := {};
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02008253 var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008254 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008255 dt := f_est_dchan(ra, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008256 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008257 }
8258
8259 /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008260 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
8261 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8262 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008263
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008264 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008265 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008266 dt.idx := {0, 0};
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008267
8268 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008269 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8270 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008271 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
8272
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008273 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 +02008274 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8275 dt.sccp_conn_id := rx_c_ind.connectionId;
8276 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8277
8278 /* Instruct BSC to clear channel */
8279 var BssmapCause cause := 0;
8280 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008281 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008282
8283 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008284 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8285 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008286 f_sleep(1.0);
8287 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8288
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008289 /* Clean up SDCCH lchans */
8290 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8291 f_perform_clear_test_ct(chan_cleanup[i]);
8292 }
8293
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008294 /* clean up config */
8295 f_ts_reset_chcomb(0);
8296 /* TODO: clean up other channels? */
8297
8298 f_shutdown_helper();
8299}
8300
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008301/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
8302testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
8303 var RSL_Message rsl_unused, rsl_msg;
8304 var DchanTuple dt;
8305 var BSSAP_N_CONNECT_ind rx_c_ind;
8306 var GsmRrMessage rr;
8307
8308 /* change Timeslot 6 before f_init() starts RSL */
8309 f_init_vty();
8310 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8311 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8312
8313 f_init(1, false);
8314 f_sleep(1.0);
8315
8316 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8317
8318 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8319 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8320 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008321 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008322
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008323 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008324 f_sleep(1.0);
8325 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8326 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8327
8328 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8329 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008330 var DchanTuples chan_cleanup := {};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008331 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008332 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008333 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008334 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008335 }
8336
8337 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008338 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8339 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8340 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008341
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008342 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008343 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008344 dt.idx := {0, 0};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008345
8346 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008347 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
8348 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008349 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
8350 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
8351 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
8352 }
8353
8354 /* FIXME? Currently the TS stays in state BORKEN: */
8355
8356 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008357 /* rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8358 * f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008359 * f_sleep(1.0);
8360 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
8361 */
8362
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008363 /* Clean up SDCCH lchans */
8364 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8365 f_perform_clear_test_ct(chan_cleanup[i]);
8366 }
8367
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008368 /* clean up config */
8369 f_ts_set_chcomb(0, 0, 6, "PDCH");
8370
8371 f_shutdown_helper();
8372}
8373
Stefan Sperling0796a822018-10-05 13:01:39 +02008374testcase TC_chopped_ipa_ping() runs on test_CT {
Stefan Sperling554123f2018-10-09 14:12:30 +02008375 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port, mp_bsc_ctrl_port};
Stefan Sperling0796a822018-10-05 13:01:39 +02008376 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8377 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8378 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008379 f_shutdown_helper();
Stefan Sperling0796a822018-10-05 13:01:39 +02008380}
8381
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008382testcase TC_chopped_ipa_payload() runs on test_CT {
8383 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port
8384 /* TODO: mp_bsc_ctrl_port does not work yet */};
8385 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8386 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8387 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008388 f_shutdown_helper();
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008389}
8390
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008391/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
8392 the BTS does autonomous MS power control loop */
8393testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
8394 var MSC_ConnHdlr vc_conn;
8395 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8396 //pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
8397 pars.exp_ms_power_params := true;
8398
8399 f_init(1, true);
8400 f_sleep(1.0);
8401 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
8402 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008403 f_shutdown_helper();
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008404}
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008405
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008406/* Verify activation and deactivation of the BCCH carrier power reduction mode */
8407testcase TC_c0_power_red_mode() runs on test_CT {
8408 f_init(1);
8409
8410 for (var integer red := 6; red >= 0; red := red - 2) {
8411 /* Configure BCCH carrier power reduction mode via the VTY */
8412 f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
8413
8414 /* Expect Osmocom specific BS Power Control message on the RSL */
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03008415 var template (present) RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008416 chan_nr := t_RslChanNr_BCCH(0),
8417 bs_power := tr_RSL_IE_BS_Power(red / 2));
8418 tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008419 var RSL_Message unused := f_exp_ipa_rx(tr_rsl_pdu);
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008420
8421 /* Additionally verify the applied value over the CTRL interface */
8422 var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
8423 if (cred != int2str(red)) {
8424 setverdict(fail, "Unexpected BCCH carrier power reduction value ",
8425 cred, " (expected ", red, ")");
8426 }
8427 }
8428
8429 f_shutdown_helper();
8430}
8431
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008432/***********************************************************************
8433 * MSC Pooling
8434 ***********************************************************************/
8435
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008436template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
Harald Weltebf397612021-01-14 20:39:46 +01008437 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 +02008438
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008439private 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 +02008440runs on MSC_ConnHdlr {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008441 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008442 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008443 f_logp(BSCVTY, "Got RSL RR Release");
8444 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008445 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008446 f_logp(BSCVTY, "Got RSL Deact SACCH");
8447 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008448 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008449 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008450 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8451 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008452 break;
8453 }
8454 }
8455}
8456
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008457private altstep as_mgcp_ack_all_dlcx() runs on MSC_ConnHdlr {
8458 var MgcpCommand mgcp_cmd;
8459 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
8460 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
8461 repeat;
8462 }
8463}
8464
8465private altstep as_rsl_ack_all_rel_req() runs on MSC_ConnHdlr {
8466 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
8467 [] RSL.receive(tr_RSL_REL_REQ(g_chan_nr, ?)) {
8468 RSL.send(ts_RSL_REL_CONF(g_chan_nr, main_dcch));
8469 repeat;
8470 }
8471}
8472
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008473friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
8474 template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02008475runs on MSC_ConnHdlr {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008476 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8477 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008478 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008479 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8480 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008481 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008482 f_logp(BSCVTY, "Got RSL RR Release");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008483 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008484 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008485 f_logp(BSCVTY, "Got RSL Deact SACCH");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008486 }
8487 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008488 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008489 /* Also drop the SCCP connection */
8490 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8491 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008492 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008493 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008494 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8495 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008496 }
8497 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008498 deactivate(ack_dlcx);
8499 deactivate(ack_rel_req);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008500}
8501
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01008502friend function f_perform_clear_no_rr_rel(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC)
8503runs on MSC_ConnHdlr {
8504 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8505 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
8506 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8507 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8508 interleave {
8509 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
8510 f_logp(BSCVTY, "Got RSL Deact SACCH");
8511 }
8512 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
8513 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8514 /* Also drop the SCCP connection */
8515 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8516 }
8517 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
8518 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
8519 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8520 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
8521 }
8522 }
8523 deactivate(ack_dlcx);
8524 deactivate(ack_rel_req);
8525}
8526
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01008527friend function f_perform_clear_no_lchan()
8528runs on MSC_ConnHdlr {
8529 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8530 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8531 BSSAP.receive(tr_BSSMAP_ClearComplete);
8532 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8533 /* Also drop the SCCP connection */
8534 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8535}
8536
Vadim Yanitskiy65d879d2022-06-23 18:15:39 +07008537friend function f_perform_clear_test_ct(DchanTuple dt)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008538 runs on test_CT
8539{
8540 /* Instruct BSC to clear channel */
8541 var BssmapCause cause := 0;
8542 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008543 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008544}
8545
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008546private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
8547 template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008548runs on MSC_ConnHdlr {
8549 timer T := 10.0;
8550 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
8551
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008552 f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008553 f_create_bssmap_exp(l3_enc);
8554
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008555 /* RSL_Emulation.f_chan_est() on rsl_pt:
8556 * This is basically code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008557 * RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
8558 */
8559 var RSL_Message rx_rsl;
8560 var GsmRrMessage rr;
8561
8562 /* request a channel to be established */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008563 rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008564 /* expect immediate assignment.
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008565 * Code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008566 * rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
8567 */
8568 timer Tt := 10.0;
8569
8570 /* request a channel to be established */
8571 Tt.start;
8572 alt {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008573 [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008574 Tt.stop;
8575 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008576 [] rsl_pt.receive {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008577 setverdict(fail, "Unexpected RSL message on DCHAN");
8578 mtc.stop;
8579 }
8580 [] Tt.timeout {
8581 setverdict(fail, "Timeout waiting for RSL on DCHAN");
8582 mtc.stop;
8583 }
8584 }
8585 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
8586 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008587 rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008588
8589
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008590 if (expect_bssmap_l3) {
8591 f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
8592 var template PDU_BSSAP exp_l3_compl;
8593 exp_l3_compl := tr_BSSMAP_ComplL3()
8594 if (g_pars.aoip == false) {
8595 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
8596 } else {
8597 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
8598 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008599
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008600 var PDU_BSSAP bssap;
8601 T.start;
8602 alt {
8603 [] BSSAP.receive(exp_l3_compl) -> value bssap {
8604 f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
8605 log("rx exp_l3_compl = ", bssap);
8606 }
8607 [] BSSAP.receive(tr_BSSMAP_ComplL3) {
8608 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
8609 }
8610 [] T.timeout {
8611 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
8612 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008613 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008614
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008615 /* start ciphering, if requested */
8616 if (ispresent(g_pars.encr)) {
8617 f_logp(BSCVTY, "start ciphering");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008618 f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008619 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008620 }
8621
8622 if (do_clear) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008623 f_perform_clear(rsl_pt, rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008624 }
8625 setverdict(pass);
8626 f_sleep(1.0);
8627}
8628
8629private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
8630 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8631 if (g_pars.mscpool.rsl_idx == 0) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008632 f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008633 } else if (g_pars.mscpool.rsl_idx == 1) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008634 f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008635 } else if (g_pars.mscpool.rsl_idx == 2) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008636 f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008637 }
8638}
8639
8640/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
8641private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
8642 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008643 f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
8644 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 +02008645 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)) );
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008646 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 +02008647}
8648testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
8649
8650 f_init(1, true);
8651 f_sleep(1.0);
8652 var MSC_ConnHdlr vc_conn;
8653 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008654
8655 f_ctrs_msc_init();
8656
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008657 vc_conn := f_start_handler(refers(f_tc_mscpool_L3Compl_on_1_msc), pars);
8658 vc_conn.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008659
8660 f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008661 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008662}
8663
8664/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
8665/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8666 * just as well using only RSL. */
8667testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
8668
8669 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8670 f_sleep(1.0);
8671
8672 /* Control which MSC gets chosen next by the round-robin, otherwise
8673 * would be randomly affected by which other tests ran before this. */
8674 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8675
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008676 f_ctrs_msc_init();
8677
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008678 var MSC_ConnHdlr vc_conn1;
8679 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8680 pars1.mscpool.rsl_idx := 0;
8681 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8682 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8683 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008684 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008685
8686 var MSC_ConnHdlr vc_conn2;
8687 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8688 pars2.mscpool.rsl_idx := 1;
8689 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8690 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8691 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008692 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008693
8694 /* Test round-robin wrap to the first MSC */
8695 var MSC_ConnHdlr vc_conn3;
8696 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8697 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008698 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008699 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8700 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008701 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008702 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008703}
8704
8705/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 0
8706 * (configured in osmo-bsc.cfg). */
8707/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8708 * just as well using only RSL. */
8709testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
8710
8711 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8712 f_sleep(1.0);
8713
8714 /* Control which MSC gets chosen next by the round-robin, otherwise
8715 * would be randomly affected by which other tests ran before this. */
8716 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8717
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008718 f_ctrs_msc_init();
8719
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008720 var MSC_ConnHdlr vc_conn1;
8721 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8722 pars1.mscpool.rsl_idx := 0;
8723 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8724 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8725 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008726 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008727
8728 var MSC_ConnHdlr vc_conn2;
8729 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8730 pars2.mscpool.rsl_idx := 1;
8731 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8732 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8733 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008734 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008735
8736 /* Test round-robin wrap to the first MSC */
8737 var MSC_ConnHdlr vc_conn3;
8738 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8739 pars3.mscpool.rsl_idx := 2;
8740 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8741 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8742 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008743 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008744 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008745}
8746
8747/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
8748 * (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
8749 * NULL-NRI setting is stronger than that. */
8750/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8751 * just as well using only RSL. */
8752testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
8753
8754 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8755 f_sleep(1.0);
8756
8757 /* Control which MSC gets chosen next by the round-robin, otherwise
8758 * would be randomly affected by which other tests ran before this. */
8759 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8760
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008761 f_ctrs_msc_init();
8762
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008763 var MSC_ConnHdlr vc_conn1;
8764 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8765 pars1.mscpool.rsl_idx := 0;
8766 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8767 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8768 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008769 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008770
8771 var MSC_ConnHdlr vc_conn2;
8772 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8773 pars2.mscpool.rsl_idx := 1;
8774 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8775 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8776 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008777 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008778
8779 /* Test round-robin wrap to the first MSC */
8780 var MSC_ConnHdlr vc_conn3;
8781 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8782 pars3.mscpool.rsl_idx := 2;
8783 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8784 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8785 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008786 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008787 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008788}
8789
8790/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
8791 * assigned to any MSC (configured in osmo-bsc.cfg). */
8792/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8793 * just as well using only RSL. */
8794testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test_CT {
8795
8796 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8797 f_sleep(1.0);
8798
8799 /* Control which MSC gets chosen next by the round-robin, otherwise
8800 * would be randomly affected by which other tests ran before this. */
8801 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8802
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008803 f_ctrs_msc_init();
8804
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008805 var MSC_ConnHdlr vc_conn1;
8806 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8807 pars1.mscpool.rsl_idx := 0;
8808 /* An NRI that is not assigned to any MSC */
8809 pars1.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(1023))));
8810 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8811 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008812 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008813
8814 var MSC_ConnHdlr vc_conn2;
8815 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8816 pars2.mscpool.rsl_idx := 1;
8817 /* An NRI that is not assigned to any MSC */
8818 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(768)), '00F110'O));
8819 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8820 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008821 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008822
8823 /* Test round-robin wrap to the first MSC */
8824 var MSC_ConnHdlr vc_conn3;
8825 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8826 pars3.mscpool.rsl_idx := 2;
8827 /* An NRI that is not assigned to any MSC */
8828 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, valueof(ts_MI_TMSI_NRI_LV(819))));
8829 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8830 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008831 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008832 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008833}
8834
8835/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
8836 * assigned to an MSC that is currently not connected (configured in osmo-bsc.cfg). */
8837/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8838 * just as well using only RSL. */
8839testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
8840
8841 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8842 f_sleep(1.0);
8843
8844 /* Control which MSC gets chosen next by the round-robin, otherwise
8845 * would be randomly affected by which other tests ran before this. */
8846 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8847
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008848 f_ctrs_msc_init();
8849
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008850 var MSC_ConnHdlr vc_conn1;
8851 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8852 pars1.mscpool.rsl_idx := 0;
8853 /* An NRI that is assigned to an unconnected MSC */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008854 pars1.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(512)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008855 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8856 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008857 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8858 f_ctrs_msc_add(0, "mscpool:subscr:new");
8859 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008860
8861 var MSC_ConnHdlr vc_conn2;
8862 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8863 pars2.mscpool.rsl_idx := 1;
8864 /* An NRI that is assigned to an unconnected MSC */
8865 pars2.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(767))));
8866 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8867 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008868 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8869 f_ctrs_msc_add(1, "mscpool:subscr:new");
8870 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008871
8872 /* Test round-robin wrap to the first MSC */
8873 var MSC_ConnHdlr vc_conn3;
8874 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8875 pars3.mscpool.rsl_idx := 2;
8876 /* An NRI that is assigned to an unconnected MSC */
8877 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(750)), '00F110'O));
8878 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8879 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008880 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8881 f_ctrs_msc_add(0, "mscpool:subscr:new");
8882 f_ctrs_msc_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008883 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008884}
8885
8886/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
8887 * osmo-bsc.cfg). */
8888/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8889 * just as well using only RSL. */
8890testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
8891
8892 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8893 f_sleep(1.0);
8894
8895 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
8896 * this is not using round-robin. */
8897 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8898
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008899 f_ctrs_msc_init();
8900
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008901 var MSC_ConnHdlr vc_conn1;
8902 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8903 pars1.mscpool.rsl_idx := 0;
8904 /* An NRI of the second MSC's range (256-511) */
8905 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(256))));
8906 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8907 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008908 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008909
8910 var MSC_ConnHdlr vc_conn2;
8911 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8912 pars2.mscpool.rsl_idx := 1;
8913 /* An NRI of the second MSC's range (256-511) */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008914 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(260)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008915 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8916 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008917 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008918
8919 var MSC_ConnHdlr vc_conn3;
8920 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8921 pars3.mscpool.rsl_idx := 2;
8922 /* An NRI of the second MSC's range (256-511) */
8923 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(511)), '00F110'O));
8924 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8925 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008926 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008927 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008928}
8929
8930/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
8931 * while a round-robin remains unaffected by that. */
8932/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8933 * just as well using only RSL. */
8934testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
8935
8936 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8937 f_sleep(1.0);
8938
8939 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
8940 * this is not using round-robin. */
8941 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8942
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008943 f_ctrs_msc_init();
8944
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008945 var MSC_ConnHdlr vc_conn1;
8946 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 2);
8947 pars1.mscpool.rsl_idx := 0;
8948 /* An NRI of the third MSC's range (512-767) */
8949 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(512))));
8950 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8951 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008952 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008953
8954 var MSC_ConnHdlr vc_conn2;
8955 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8956 pars2.mscpool.rsl_idx := 1;
8957 /* An NRI of the third MSC's range (512-767) */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008958 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(678)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008959 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8960 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008961 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008962
8963 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
8964 var MSC_ConnHdlr vc_conn3;
8965 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8966 pars3.mscpool.rsl_idx := 2;
8967 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000013'H)), '00F110'O));
8968 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8969 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008970 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008971 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008972}
8973
8974/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
8975/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8976 * just as well using only RSL. */
8977testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
8978
8979 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8980 f_sleep(1.0);
8981
8982 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
8983 * instead, and hits msc 0. */
8984 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8985
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008986 f_ctrs_msc_init();
8987
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008988 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-bsc.cfg */
8989 var MSC_ConnHdlr vc_conn1;
8990 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8991 pars1.mscpool.rsl_idx := 0;
8992 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(260)), '99F999'O));
8993 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8994 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008995 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008996
8997 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
8998 var MSC_ConnHdlr vc_conn2;
8999 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9000 pars2.mscpool.rsl_idx := 1;
9001 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(555)), '00F110'O));
9002 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9003 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009004 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009005 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009006}
9007
9008/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
9009 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9010private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
9011 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9012 //cid_list := { cIl_allInBSS := ''O };
9013 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9014 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9015 var BSSAP_N_UNITDATA_req paging;
9016 var hexstring imsi := '001010000000123'H;
9017
9018 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9019
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009020 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009021 valueof(ts_BSSMAP_Paging(imsi, cid_list, omit, bssmap_chneed))));
9022 BSSAP.send(paging);
9023
9024 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9025 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9026 * channel number is picked here. */
9027 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9028 f_rslem_register(0, new_chan_nr);
9029 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(imsi)));
9030 f_rslem_unregister(0, new_chan_nr);
9031
9032 /* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
9033 * causes this Paging Response to go to the first MSC (bssap_idx := 0). */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009034 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV(imsi)) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009035 f_sleep(1.0);
9036}
9037testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
9038 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9039 f_sleep(1.0);
9040
9041 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9042 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9043 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
9044
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009045 f_ctrs_msc_init();
9046
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009047 var MSC_ConnHdlr vc_conn1;
9048 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9049 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009050 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9051 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009052 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
9053 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009054 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009055 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009056}
9057
9058/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
9059 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9060private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
9061 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9062 //cid_list := { cIl_allInBSS := ''O };
9063 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9064 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9065 var integer nri_v := 300; /* <-- second MSC's NRI */
Harald Weltebf397612021-01-14 20:39:46 +01009066 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009067 var BSSAP_N_UNITDATA_req paging;
9068
9069 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9070
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009071 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009072 valueof(ts_BSSMAP_Paging('001010000000011'H, cid_list, tmsi, bssmap_chneed))));
9073 BSSAP.send(paging);
9074
9075 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9076 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9077 * channel number is picked here. */
9078 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9079 f_rslem_register(0, new_chan_nr);
9080 RSL.receive(tr_RSL_PAGING_CMD(t_MI_TMSI(tmsi)));
9081 f_rslem_unregister(0, new_chan_nr);
9082
9083 /* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
9084 * third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
9085 * the first MSC (bssap_idx := 0). */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009086 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_TMSI_NRI_LV(nri_v)) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009087 f_sleep(1.0);
9088}
9089testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
9090 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9091 f_sleep(1.0);
9092
9093 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9094 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9095 f_vty_transceive(BSCVTY, "mscpool roundrobin next 2");
9096
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009097 f_ctrs_msc_init();
9098
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009099 var MSC_ConnHdlr vc_conn1;
9100 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9101 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009102 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9103 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009104 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
9105 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009106 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009107 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009108}
9109
9110/* For round-robin, skip an MSC that has 'no allow-attach' set. */
9111/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
9112 * just as well using only RSL. */
9113testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
9114
9115 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9116 f_sleep(1.0);
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009117 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9118 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009119
9120 /* Control which MSC gets chosen next by the round-robin, otherwise
9121 * would be randomly affected by which other tests ran before this. */
9122 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9123
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009124 f_ctrs_msc_init();
9125
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009126 var MSC_ConnHdlr vc_conn1;
9127 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9128 pars1.mscpool.rsl_idx := 0;
9129 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9130 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9131 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009132 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009133
9134 var MSC_ConnHdlr vc_conn2;
9135 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9136 pars2.mscpool.rsl_idx := 1;
9137 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9138 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9139 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009140 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009141
9142 var MSC_ConnHdlr vc_conn3;
9143 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
9144 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009145 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009146 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9147 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009148 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009149 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009150}
9151
9152/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
9153 * TMSI NRI. */
9154testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
9155
9156 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9157 f_sleep(1.0);
9158
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009159 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9160 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
9161
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009162 /* Control which MSC gets chosen next by the round-robin, otherwise
9163 * would be randomly affected by which other tests ran before this. */
9164 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9165
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009166 f_ctrs_msc_init();
9167
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009168 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
9169 var MSC_ConnHdlr vc_conn1;
9170 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
9171 pars1.mscpool.rsl_idx := 0;
9172 /* An NRI of the second MSC's range (256-511) */
9173 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_TMSI_NRI_LV(260))));
9174 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9175 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009176 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009177
9178 var MSC_ConnHdlr vc_conn2;
9179 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9180 pars2.mscpool.rsl_idx := 1;
9181 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9182 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9183 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009184 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009185
9186 var MSC_ConnHdlr vc_conn3;
9187 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 2);
9188 pars3.mscpool.rsl_idx := 2;
9189 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000003'H))));
9190 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9191 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009192 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009193 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009194}
9195
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009196/* When an MSC point-code gets an SCCP N-PCSTATE saying it is unreachable, immediately mark the MSC as unusable. */
9197testcase TC_mscpool_sccp_n_pcstate_detaches_msc() runs on test_CT {
9198
9199 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
9200 f_sleep(1.0);
9201
9202 /* Control which MSC gets chosen next by the round-robin, otherwise
9203 * would be randomly affected by which other tests ran before this. */
9204 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9205
9206 f_ctrs_msc_init();
9207
9208 var MSC_ConnHdlr vc_conn1;
9209 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9210 pars1.mscpool.rsl_idx := 0;
9211 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9212 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9213 vc_conn1.done;
9214 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9215
9216 var MSC_ConnHdlr vc_conn2;
9217 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
9218 pars2.mscpool.rsl_idx := 1;
9219 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9220 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9221 vc_conn2.done;
9222 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9223
9224 f_logp(BSCVTY, "disconnecting msc0");
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009225 f_bssap_idx_disconnect(0);
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009226
9227 /* Now round-robin would wrap to the first MSC, but since the first MSC is disconnected, it wraps around to msc
9228 * 2 again. */
9229 var MSC_ConnHdlr vc_conn3;
9230 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
9231 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009232 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009233 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9234 vc_conn3.done;
9235 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9236 f_shutdown_helper();
9237}
9238
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009239/* When an MSC point-code gets an SCCP N-PCSTATE saying it is now reachable, immediately trigger RESET and bring up the
9240 * MSC. */
9241testcase TC_mscpool_sccp_n_pcstate_attaches_msc() runs on test_CT {
9242
9243 f_init(nr_bts := 3, handler_mode := true, nr_msc := 1);
9244 f_sleep(1.0);
9245
9246 /* Control which MSC gets chosen next by the round-robin, otherwise
9247 * would be randomly affected by which other tests ran before this. */
9248 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9249
9250 f_ctrs_msc_init();
9251
9252 /* There is only one MSC, round robin stays on msc0 */
9253 var MSC_ConnHdlr vc_conn1;
9254 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9255 pars1.mscpool.rsl_idx := 0;
9256 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('0010100230000001'H)), '00F110'O));
9257 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9258 vc_conn1.done;
9259 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9260
9261 var MSC_ConnHdlr vc_conn2;
9262 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9263 pars2.mscpool.rsl_idx := 1;
9264 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010023000002'H))));
9265 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9266 vc_conn2.done;
9267 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9268
9269 f_logp(BSCVTY, "connecting msc1");
9270 f_vty_msc_allow_attach(BSCVTY, { true, true });
9271 f_bssap_idx_init(1);
9272 f_sleep(1.0);
9273
9274 /* This time round-robin wraps to the second MSC, because it is now online. */
9275 var MSC_ConnHdlr vc_conn4;
9276 var TestHdlrParams pars4 := f_gen_test_hdlr_pars(bssap_idx := 1);
9277 pars4.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009278 pars4.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010023000003'H)));
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009279 vc_conn4 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars4);
9280 vc_conn4.done;
9281 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9282
9283 f_shutdown_helper();
9284}
9285
Philipp Maier783681c2020-07-16 16:47:06 +02009286/* Allow/Deny emergency calls globally via VTY */
9287private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
9288 f_vty_enter_cfg_msc(BSCVTY, 0);
9289 if (allow) {
9290 f_vty_transceive(BSCVTY, "allow-emergency allow");
9291 } else {
9292 f_vty_transceive(BSCVTY, "allow-emergency deny");
9293 }
9294 f_vty_transceive(BSCVTY, "exit");
9295 f_vty_transceive(BSCVTY, "exit");
9296}
9297
9298/* Allow/Deny emergency calls per BTS via VTY */
9299private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
9300 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9301 if (allow) {
9302 f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
9303 } else {
9304 f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
9305 }
9306 f_vty_transceive(BSCVTY, "exit");
9307 f_vty_transceive(BSCVTY, "exit");
Neels Hofmeyrb6ed80c2020-10-12 22:52:39 +00009308 f_vty_transceive(BSCVTY, "exit");
Philipp Maier783681c2020-07-16 16:47:06 +02009309}
9310
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02009311/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
9312private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
9313 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9314 if (allow) {
9315 f_vty_transceive(BSCVTY, "srvcc fast-return allow");
9316 } else {
9317 f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
9318 }
9319 f_vty_transceive(BSCVTY, "exit");
9320 f_vty_transceive(BSCVTY, "exit");
9321 f_vty_transceive(BSCVTY, "exit");
9322}
9323
Pau Espin Pedrol14475352021-07-22 15:48:16 +02009324/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
9325private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
9326 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9327 if (allow) {
9328 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
9329 } else {
9330 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
9331 }
9332 f_vty_transceive(BSCVTY, "exit");
9333 f_vty_transceive(BSCVTY, "exit");
9334 f_vty_transceive(BSCVTY, "exit");
9335}
9336
Pau Espin Pedrol35609792023-01-03 16:56:59 +01009337/* Begin assignment procedure and send an EMERGENCY SETUP (RR) */
Philipp Maier783681c2020-07-16 16:47:06 +02009338private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
9339 var PDU_ML3_MS_NW emerg_setup;
9340 var octetstring emerg_setup_enc;
9341 var RSL_Message emerg_setup_data_ind;
9342
9343 f_establish_fully(omit, omit);
9344
9345 emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
9346 emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
9347 emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
9348
9349 RSL.send(emerg_setup_data_ind);
9350}
9351
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009352/* expect EmergencySetup on BSSAP after calling f_assignment_emerg_setup() */
9353private function f_assignment_emerg_setup_exp_bssap()
9354runs on MSC_ConnHdlr {
Philipp Maier783681c2020-07-16 16:47:06 +02009355 var PDU_BSSAP emerg_setup_data_ind_bssap;
9356 var PDU_ML3_MS_NW emerg_setup;
9357 timer T := 3.0;
9358
Philipp Maier783681c2020-07-16 16:47:06 +02009359 T.start;
9360 alt {
9361 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
9362 emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
9363 if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
9364 setverdict(fail, "no emergency setup");
9365 }
9366 }
9367 [] BSSAP.receive {
9368 setverdict(fail, "unexpected BSSAP message!");
9369 }
9370 [] T.timeout {
9371 setverdict(fail, "timout waiting for EMERGENCY SETUP!");
9372 }
9373 }
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009374}
9375
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009376private function f_assignment_emerg_setup_voice()
9377runs on MSC_ConnHdlr {
9378 /* Go on with voice call assignment */
9379 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
9380 var PDU_BSSAP ass_cmd := f_gen_ass_req();
9381
9382 /* Below speechOrDataIndicator and codecList are copied from an emergency call captured during tests.
9383 * They seem a bit weird (AMR-WB, and the order differ between speechId_DataIndicator and the codecList), but
9384 * seems a good idea to see how osmo-bsc reacts to this. */
9385 ass_cmd.pdu.bssmap.assignmentRequest.channelType := {
9386 elementIdentifier := '0B'O, /* overwritten */
9387 lengthIndicator := 0, /* overwritten */
9388 speechOrDataIndicator := '0001'B, /* speech */
9389 spare1_4 := '0000'B,
9390 channelRateAndType := ChRate_TCHForH_Fpref,
9391 speechId_DataIndicator := 'c2918105'O
9392 };
9393 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({
9394 ts_CodecHR, ts_CodecAMR_WB, ts_CodecEFR, ts_CodecFR}));
9395
9396 f_rslem_dchan_queue_enable();
9397
9398 var ExpectCriteria mgcpcrit := {
9399 connid := omit,
9400 endpoint := omit,
9401 transid := omit
9402 };
9403 f_create_mgcp_expect(mgcpcrit);
9404
9405 BSSAP.send(ass_cmd);
9406
9407 var AssignmentState st := valueof(ts_AssignmentStateInit);
Oliver Smithce2dd692023-04-17 10:25:50 +02009408 st.rtp_stream := true;
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009409 st.is_assignment := false;
9410 alt {
9411 [] as_modify(st);
9412 [] as_Media();
9413 [st.modify_done] BSSAP.receive(exp_compl) {
9414 setverdict(pass);
9415 }
9416 }
9417
9418 /* Voice call carries on ... */
9419 f_sleep(2.0);
9420}
9421
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009422/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
9423 * CALLS are permitted by the BSC config. */
9424private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
9425
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009426 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
9427 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
9428 * another lchan. */
9429 g_pars.ra := f_rnd_ra_emerg();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009430 f_assignment_emerg_setup();
9431 f_assignment_emerg_setup_exp_bssap();
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009432 f_assignment_emerg_setup_voice();
Philipp Maier783681c2020-07-16 16:47:06 +02009433
9434 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009435 f_perform_clear();
Philipp Maier783681c2020-07-16 16:47:06 +02009436}
9437
9438/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
9439 * forbidden by the BSC config. */
9440private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
9441 var PDU_BSSAP emerg_setup_data_ind_bssap;
9442 timer T := 3.0;
9443
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009444 f_assignment_emerg_setup();
Philipp Maier783681c2020-07-16 16:47:06 +02009445
9446 T.start;
9447 alt {
9448 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
9449 setverdict(pass);
9450 }
9451 [] RSL.receive {
9452 setverdict(fail, "unexpected RSL message!");
9453 }
9454 [] T.timeout {
9455 setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
9456 }
9457 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009458 BSSAP.receive(tr_BSSMAP_ClearRequest);
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01009459 f_perform_clear_no_rr_rel();
Philipp Maier783681c2020-07-16 16:47:06 +02009460}
9461
9462/* EMERGENCY CALL situation #1, allowed globally and by BTS */
9463testcase TC_assignment_emerg_setup_allow() runs on test_CT {
9464 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9465 var MSC_ConnHdlr vc_conn;
9466
9467 f_init(1, true);
9468 f_sleep(1.0);
9469
9470 f_vty_allow_emerg_msc(true);
9471 f_vty_allow_emerg_bts(true, 0);
9472 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9473 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009474 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009475}
9476
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +01009477/* Test MO emergency call using MobileIdentity=IMEI (possible for emergency
9478 * calls from phones without SIM card).
9479 * 3GPP TS 24.008 section 10.5.1.4, OS#5849 */
9480testcase TC_assignment_emerg_setup_allow_imei() runs on test_CT {
9481 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9482 var MSC_ConnHdlr vc_conn;
9483
9484 /* Remove IMSI set by f_gen_test_hdlr_pars(), then IMEI will be used to place the call */
9485 pars.imsi := omit;
9486
9487 f_init(1, true);
9488 f_sleep(1.0);
9489
9490 f_vty_allow_emerg_msc(true);
9491 f_vty_allow_emerg_bts(true, 0);
9492 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9493 vc_conn.done;
9494 f_shutdown_helper();
9495}
9496
Philipp Maier783681c2020-07-16 16:47:06 +02009497/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
9498testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
9499 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9500 var MSC_ConnHdlr vc_conn;
9501
9502 f_init(1, true);
9503 f_sleep(1.0);
9504
9505 f_vty_allow_emerg_msc(false);
9506 f_vty_allow_emerg_bts(true, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009507 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx): */
9508 pars.ra := f_rnd_ra_emerg();
Philipp Maier783681c2020-07-16 16:47:06 +02009509 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9510 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009511 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009512}
9513
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009514/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS.
9515 * The RACH req (and hence CHAN RQD) indicate other than emergency call.
9516 * Hence BSC only learns about it being an emergency call later during call setup.
9517 * If interested in the ra="emergency call" + deny bts policy case,
9518 * see TC_chan_rqd_emerg_deny.
9519 */
Philipp Maier783681c2020-07-16 16:47:06 +02009520testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
9521 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9522 var MSC_ConnHdlr vc_conn;
9523
9524 /* Note: This simulates a spec violation by the MS, correct MS
9525 * implementations would not try to establish an emergency call because
9526 * the system information tells in advance that emergency calls are
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009527 * not allowed */
Philipp Maier783681c2020-07-16 16:47:06 +02009528
9529 f_init(1, true);
9530 f_sleep(1.0);
9531
9532 f_vty_allow_emerg_msc(true);
9533 f_vty_allow_emerg_bts(false, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009534 /* Note: Here we implicitly leave default g_pars.ra which is different than "emergency call" */
Philipp Maier783681c2020-07-16 16:47:06 +02009535 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), 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
Philipp Maier82812002020-08-13 18:48:27 +02009540/* Test what happens when an emergency call arrives while all TCH channels are
9541 * busy, the BSC is expected to terminate one call in favor of the incoming
9542 * emergency call */
9543testcase TC_emerg_premption() runs on test_CT {
9544 var ASP_RSL_Unitdata rsl_ud;
9545 var integer i;
9546 var integer chreq_total, chreq_nochan;
9547 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009548 var octetstring l3_payload := gen_l3_valid_payload();
Philipp Maier82812002020-08-13 18:48:27 +02009549
9550 f_init(1);
9551 f_sleep(1.0);
9552
9553 f_vty_allow_emerg_msc(true);
9554 f_vty_allow_emerg_bts(true, 0);
9555
9556 /* Fill up all channels on the BTS */
9557 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
9558 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
9559 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 +02009560 f_chreq_act_ack('33'O, i);
Philipp Maier82812002020-08-13 18:48:27 +02009561 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009562 IPA_RSL[0][0].clear;
Philipp Maier82812002020-08-13 18:48:27 +02009563 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
9564 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
9565
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009566 /* Send EST IND for the first TCH, so we get to test the RR release cause */
9567 var RslChannelNr first_tch := valueof(t_RslChanNr_Bm(1));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009568 f_ipa_tx(ts_RSL_EST_IND(first_tch, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009569
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009570 /* Accept BSSAP conn, so we get to test the Clear Request cause */
9571 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009572 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009573 var integer sccp_conn_id := rx_c_ind.connectionId;
9574 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
9575
Philipp Maier82812002020-08-13 18:48:27 +02009576 /* Send Channel request for emegergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009577 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier82812002020-08-13 18:48:27 +02009578
9579 /* Expect the BSC to release one (the first) TCH/F on the BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009580 f_expect_chan_rel(first_tch, expect_rr_chan_rel := true, expect_rll_rel_req := false,
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009581 expect_rr_cause := GSM48_RR_CAUSE_PREMPTIVE_REL);
Philipp Maier82812002020-08-13 18:48:27 +02009582
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009583 /* Also expect a BSSMAP Clear Request with PREEMPTION */
9584 var BSSAP_N_DATA_ind rx_clear_req;
9585 const myBSSMAP_Cause preemption := GSM0808_CAUSE_PREEMPTION;
9586 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_clear_req;
9587 log("XXX ", rx_clear_req);
9588 if (rx_clear_req.userData.pdu.bssmap.clearRequest.cause.causeValue != int2bit(enum2int(preemption), 7)) {
9589 setverdict(fail, "BSSMAP Clear Request: expected cause PREEMPTION");
9590 }
9591
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009592 /* Expect the BSC to send activate/assign the channel for the emergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009593 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009594 if (first_tch != rx_rsl.ies[0].body.chan_nr) {
9595 setverdict(fail, "different TCH lchan activated than expected");
9596 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009597 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(first_tch, 33));
9598 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Philipp Maier104f4c02020-09-11 18:12:18 +02009599
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009600 /* complete the BSSMAP Clear to satisfy the conn leak check */
9601 BSSAP.send(ts_BSSAP_DATA_req(sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(preemption))));
9602 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearComplete)) {
9603 BSSAP.send(ts_BSSAP_DISC_req(sccp_conn_id, 0));
9604 }
9605
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009606 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009607}
9608
9609/* Hopping parameters per a timeslot */
Vadim Yanitskiybc6654a2020-09-13 01:27:40 +07009610private type record length(0..64) of GsmArfcn ArfcnList;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009611private type record FHParamsTs {
9612 boolean enabled,
9613 uint6_t hsn,
9614 uint6_t maio,
9615 ArfcnList ma
9616};
9617
9618/* Hopping parameters per a transceiver */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009619private type record FHParamsTrx {
Philipp Maier798d8952021-10-19 14:43:19 +02009620 GsmBandArfcn arfcn,
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009621 FHParamsTs ts[8]
9622};
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009623
9624/* Randomly generate the hopping parameters for the given timeslot numbers */
9625private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
9626runs on test_CT return FHParamsTrx {
9627 var FHParamsTrx fhp;
9628
Philipp Maier798d8952021-10-19 14:43:19 +02009629 /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
9630 * fall in the GSM900 band. */
9631 fhp.arfcn.arfcn := f_rnd_int(3);
9632 fhp.arfcn.pcs := false;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009633
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009634 for (var integer tn := 0; tn < 8; tn := tn + 1) {
9635 if (not match(tn, tr_tn)) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009636 fhp.ts[tn].enabled := false;
9637 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009638 continue;
9639 }
9640
9641 /* Random HSN / MAIO values: 0..63 */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009642 fhp.ts[tn].hsn := f_rnd_int(64);
9643 fhp.ts[tn].maio := f_rnd_int(64);
9644 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009645
9646 /* Random Mobile Allocation (hopping channels) */
9647 var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
9648 var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
9649 for (var integer i := 1; i <= ma_len; i := i + 1) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009650 fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009651 }
9652
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009653 fhp.ts[tn].enabled := true;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009654 }
9655
9656 log("f_TC_fh_params_gen(): ", fhp);
9657 return fhp;
9658}
9659
9660/* Make sure that the given Channel Description IE matches the hopping configuration */
9661private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
9662{
9663 var template (present) ChannelDescription tr_cd;
9664 var template (present) MaioHsn tr_maio_hsn;
9665 var uint3_t tn := cd.chan_nr.tn;
9666
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009667 if (fhp.ts[tn].enabled) {
9668 tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009669 tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
9670 } else {
Philipp Maier798d8952021-10-19 14:43:19 +02009671 tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009672 }
9673
9674 if (not match(cd, tr_cd)) {
9675 setverdict(fail, "Channel Description IE does not match: ",
9676 cd, " vs expected ", tr_cd);
9677 }
9678}
9679
9680/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
9681private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
9682 in MobileAllocationLV ma)
9683{
9684 var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
9685
9686 if (not match(ma, tr_ma)) {
9687 setverdict(fail, "Mobile Allocation IE does not match (tn := ",
9688 tn, "): ", ma, " vs expected: ", tr_ma);
9689 } else {
9690 setverdict(pass);
9691 }
9692}
9693
9694private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
9695 in MobileAllocationLV ma)
9696return template MobileAllocationLV {
9697 /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009698 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009699 return { len := 0, ma := ''B };
9700 }
9701
9702 var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
9703 var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
9704 var bitstring ma_mask := ''B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009705
9706 /* Compose the full bit-mask (all channels, up to 1024 entries) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009707 for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
9708 for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
9709 if (full_mask[fhp.ts[i].ma[j]] == '1'B)
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009710 { continue; }
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009711 full_mask[fhp.ts[i].ma[j]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009712 }
9713 }
9714
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009715 /* Take ARFCN of the TRX itself into account */
Philipp Maier798d8952021-10-19 14:43:19 +02009716 full_mask[fhp.arfcn.arfcn] := '1'B;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009717
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009718 /* Compose a bit-mask for the given timeslot number */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009719 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9720 slot_mask[fhp.ts[tn].ma[i]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009721 }
9722
9723 /* Finally, compose the Mobile Allocation bit-mask */
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009724 for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009725 if (full_mask[i] != '1'B)
9726 { continue; }
9727
9728 /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
9729 if (slot_mask[i] == '1'B) {
9730 ma_mask := ma_mask & '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009731 } else {
9732 ma_mask := ma_mask & '0'B;
9733 }
9734 }
9735
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009736 /* ARFCN 0 (if present) goes to the last position of the bit-mask */
9737 if (full_mask[0] == '1'B) {
9738 /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
9739 if (slot_mask[0] == '1'B) {
9740 ma_mask := ma_mask & '1'B;
9741 } else {
9742 ma_mask := ma_mask & '0'B;
9743 }
9744 }
9745
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009746 /* Ensure that ma_mask is octet-aligned */
Vadim Yanitskiy2aa02522020-09-06 14:05:23 +07009747 var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009748 ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
9749
9750 return { len := ma_mask_len, ma := ma_mask };
9751}
9752
Philipp Maier798d8952021-10-19 14:43:19 +02009753/* Configure the appropriate band for a given arfcn, exc */
9754private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
9755{
9756 var charstring band;
9757 var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
9758
9759 select (arfcn_) {
9760 case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
9761 case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
9762 case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
9763 case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
9764 case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
9765 case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
9766 case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
9767 case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
9768 case else { return; }
9769 }
9770
9771 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9772 f_vty_transceive(BSCVTY, "band " & band);
9773 f_vty_transceive(BSCVTY, "end");
9774}
9775
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009776/* Configure the hopping parameters in accordance with the given record */
9777private function f_TC_fh_params_set(in FHParamsTrx fhp,
9778 uint8_t bts_nr := 0,
9779 uint8_t trx_nr := 0)
9780runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009781
9782 f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
9783
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009784 /* Enter the configuration node for the given BTS/TRX numbers */
9785 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9786
Philipp Maier798d8952021-10-19 14:43:19 +02009787 f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009788
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009789 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009790 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9791
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009792 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009793 f_vty_transceive(BSCVTY, "hopping enabled 0");
9794 f_vty_transceive(BSCVTY, "exit"); /* go back */
9795 continue;
9796 }
9797
9798 /* Configure HSN / MAIO values */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009799 f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
9800 f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009801
9802 /* Configure the Mobile Allocation (hopping channels) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009803 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9804 f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009805 }
9806
9807 f_vty_transceive(BSCVTY, "hopping enabled 1");
9808 f_vty_transceive(BSCVTY, "exit"); /* go back */
9809 }
9810
9811 f_vty_transceive(BSCVTY, "end");
9812}
9813
9814/* Disable frequency hopping on all timeslots */
9815private function f_TC_fh_params_unset(in FHParamsTrx fhp,
9816 uint8_t bts_nr := 0,
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009817 uint8_t trx_nr := 0,
Philipp Maier798d8952021-10-19 14:43:19 +02009818 GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009819runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009820
9821 f_TC_set_band_by_arfcn(bts_nr, arfcn);
9822
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009823 /* Enter the configuration node for the given BTS/TRX numbers */
9824 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9825
Philipp Maier798d8952021-10-19 14:43:19 +02009826 f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009827
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009828 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009829 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9830
9831 /* Delete all ARFCNs from the Mobile Allocation (if any) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009832 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9833 f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009834 }
9835
9836 f_vty_transceive(BSCVTY, "hopping enabled 0");
9837 f_vty_transceive(BSCVTY, "exit"); /* go back */
9838 }
9839
9840 f_vty_transceive(BSCVTY, "end");
9841 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9842}
9843
9844/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
9845 * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
9846testcase TC_fh_params_chan_activ() runs on test_CT {
9847 var FHParamsTrx fhp := f_TC_fh_params_gen();
9848 var RSL_Message rsl_msg;
9849 var RSL_IE_Body ie;
9850
9851 f_init_vty();
9852
9853 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9854 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9855
9856 f_init(1);
9857
9858 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9859 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009860 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9861 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009862
9863 /* Make sure that Channel Identification IE is present */
9864 if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
9865 setverdict(fail, "RSL Channel Identification IE is absent");
9866 continue;
9867 }
9868
9869 /* Make sure that hopping parameters (HSN/MAIO) match */
9870 f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
9871
9872 /* "Mobile Allocation shall be included but empty" - let's check this */
9873 if (ie.chan_ident.ma.v.len != 0) {
9874 setverdict(fail, "Mobile Allocation IE is not empty: ",
9875 ie.chan_ident.ma, ", despite it shall be");
9876 continue;
9877 }
9878 }
9879
9880 /* Disable frequency hopping */
9881 f_TC_fh_params_unset(fhp);
9882
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009883 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009884}
9885
9886/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
9887testcase TC_fh_params_imm_ass() runs on test_CT {
9888 var FHParamsTrx fhp := f_TC_fh_params_gen();
9889 var RSL_Message rsl_msg;
9890 var RSL_IE_Body ie;
9891
9892 f_init_vty();
9893
9894 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9895 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9896
9897 f_init(1);
9898
9899 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9900 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009901 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9902 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009903
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009904 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9905 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009906
9907 /* Make sure that Full Immediate Assign Info IE is present */
9908 if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
9909 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
9910 continue;
9911 }
9912
9913 /* Decode the actual Immediate Assignment message */
9914 var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
9915 if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
9916 setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
9917 continue;
9918 }
9919
9920 /* Make sure that hopping parameters (HSN/MAIO) match */
9921 f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
9922
9923 /* Make sure that the Mobile Allocation IE matches */
9924 f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
9925 rr_msg.payload.imm_ass.mobile_allocation);
9926 }
9927
9928 /* Disable frequency hopping */
9929 f_TC_fh_params_unset(fhp);
Philipp Maier82812002020-08-13 18:48:27 +02009930
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009931 f_shutdown_helper();
Philipp Maier82812002020-08-13 18:48:27 +02009932}
9933
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009934/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
9935testcase TC_fh_params_assignment_cmd() runs on test_CT {
9936 var FHParamsTrx fhp := f_TC_fh_params_gen();
9937 var RSL_Message rsl_msg;
9938 var RSL_IE_Body ie;
9939
9940 f_init_vty();
9941
9942 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9943 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9944
9945 f_init(1);
9946
9947 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02009948 vc_MGCP[0].stop;
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009949
9950 var template PDU_BSSAP ass_cmd := f_gen_ass_req();
9951 ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
9952
9953 /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
9954 * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
9955 for (var integer i := 0; i < 3; i := i + 1) {
9956 /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009957 var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009958
9959 /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
9960 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009961 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009962
9963 /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009964 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9965 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009966
9967 /* Make sure that L3 Information IE is present */
9968 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9969 setverdict(fail, "RSL L3 Information IE is absent");
9970 continue;
9971 }
9972
9973 /* Decode the L3 message and make sure it is (RR) Assignment Command */
9974 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9975 if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
9976 setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
9977 continue;
9978 }
9979
9980 /* Make sure that hopping parameters (HSN/MAIO) match */
9981 var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
9982 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9983
9984 /* Make sure that Cell Channel Description IE is present if FH is enabled */
9985 if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
Vadim Yanitskiy38d069d2020-09-02 17:18:57 +07009986 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009987 continue;
9988 }
9989
9990 /* Make sure that the Mobile Allocation IE matches (if present) */
9991 var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
9992 if (chan_desc.h and ma_present) {
9993 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9994 l3_msg.payload.ass_cmd.mobile_allocation.v);
9995 } else if (chan_desc.h and not ma_present) {
9996 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9997 continue;
9998 } else if (not chan_desc.h and ma_present) {
9999 setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
10000 continue;
10001 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010002
10003 f_perform_clear_test_ct(dt);
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010004 }
10005
10006 /* Give the IUT some time to release all channels */
10007 f_sleep(3.0);
10008
10009 /* Disable frequency hopping */
10010 f_TC_fh_params_unset(fhp);
10011
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010012 f_shutdown_helper();
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010013}
10014
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010015/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
10016private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
10017runs on test_CT {
10018 var RSL_Message rsl_msg;
10019 var RSL_IE_Body ie;
10020 var DchanTuple dt;
10021
10022 /* Establish a dedicated channel, so we can trigger handover */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010010023 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyc18ff472021-11-18 20:15:37 +030010024 f_sleep(0.5);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010025
10026 /* Trigger handover from BTS0 to BTS1 */
10027 f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
10028 f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
10029
10030 /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010031 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx := {1, 0});
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010032
10033 /* ACKnowledge channel activation and expect (RR) Handover Command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010034 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33), idx := {1, 0});
10035 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010036
10037 /* Make sure that L3 Information IE is present */
10038 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
10039 setverdict(fail, "RSL L3 Information IE is absent");
10040 return;
10041 }
10042
10043 /* Decode the L3 message and make sure it is (RR) Handover Command */
10044 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
10045 if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
10046 setverdict(fail, "Failed to match Handover Command: ", l3_msg);
10047 return;
10048 }
10049
10050 /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
10051 var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
10052 if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
10053 setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
10054 return;
10055 }
10056
10057 /* Make sure that hopping parameters (HSN/MAIO) match */
10058 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10059
10060 /* Make sure that Cell Channel Description IE is present */
10061 if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
10062 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
10063 return;
10064 }
10065
10066 /* Make sure that the Mobile Allocation (after time) IE is present and matches */
10067 var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
10068 if (ma_present) {
10069 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10070 l3_msg.payload.ho_cmd.mobile_allocation.v);
10071 } else {
10072 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10073 return;
10074 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010075
10076 f_perform_clear_test_ct(dt);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010077}
10078testcase TC_fh_params_handover_cmd() runs on test_CT {
10079 var FHParamsTrx fhp := f_TC_fh_params_gen();
10080
10081 f_init_vty();
10082
10083 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
10084 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
10085
10086 f_vty_transceive(BSCVTY, "timeslot 0");
10087 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10088 f_vty_transceive(BSCVTY, "exit"); /* go back */
10089
10090 f_vty_transceive(BSCVTY, "timeslot 1");
10091 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
10092 f_vty_transceive(BSCVTY, "end"); /* we're done */
10093
10094 f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
10095 f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
10096
10097 f_init(2);
10098
10099 f_TC_fh_params_handover_cmd(fhp);
10100
10101 /* Disable frequency hopping on BTS1 */
10102 f_TC_fh_params_unset(fhp, 1);
10103
10104 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
10105 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
10106
10107 f_vty_transceive(BSCVTY, "timeslot 0");
10108 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
10109 f_vty_transceive(BSCVTY, "exit"); /* go back */
10110
10111 f_vty_transceive(BSCVTY, "timeslot 1");
10112 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10113 f_vty_transceive(BSCVTY, "end"); /* we're done */
10114
10115 f_shutdown_helper();
10116}
10117
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010118/* Verify the hopping parameters in System Information Type 4 */
10119testcase TC_fh_params_si4_cbch() runs on test_CT {
10120 var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
10121 var ASP_RSL_Unitdata rx_rsl_ud;
10122 timer T := 5.0;
10123
10124 f_init_vty();
10125
10126 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
10127 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10128
10129 f_vty_transceive(BSCVTY, "timeslot 0");
10130 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10131 f_vty_transceive(BSCVTY, "exit"); /* go back */
10132
10133 f_vty_transceive(BSCVTY, "timeslot 1");
10134 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
10135 f_vty_transceive(BSCVTY, "end"); /* we're done */
10136
10137 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
10138 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10139
10140 f_init(1);
10141
10142 T.start;
10143 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010144 [] 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 +070010145 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
10146 var SystemInformation si := dec_SystemInformation(ie.other.payload);
10147
10148 /* Make sure that what we decoded is System Information Type 4 */
10149 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
10150 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
10151 repeat;
10152 }
10153
10154 /* Make sure that CBCH Channel Description IE is present */
10155 if (not ispresent(si.payload.si4.cbch_chan_desc)) {
10156 setverdict(fail, "CBCH Channel Description IE is absent");
10157 break;
10158 }
10159
10160 /* Finally, check the hopping parameters (HSN, MAIO) */
10161 var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
10162 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10163
10164 /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
10165 * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
10166 if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
10167 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10168 break;
10169 } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
10170 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10171 si.payload.si4.cbch_mobile_alloc.v);
10172 }
10173 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010174 [] IPA_RSL[0][0].receive { repeat; }
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010175 [] T.timeout {
10176 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
10177 }
10178 }
10179
10180 /* Disable frequency hopping */
10181 f_TC_fh_params_unset(fhp);
10182
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010183 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010184 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10185
10186 f_vty_transceive(BSCVTY, "timeslot 0");
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010187 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010188 f_vty_transceive(BSCVTY, "exit"); /* go back */
10189
10190 f_vty_transceive(BSCVTY, "timeslot 1");
10191 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10192 f_vty_transceive(BSCVTY, "end"); /* we're done */
10193
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010194 f_shutdown_helper();
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010195}
10196
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010197template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
10198 := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
10199
10200private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
10201 template (present) BSSLAP_PDU expect_bsslap)
10202{
10203 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
10204 if (not match(bsslap, expect_bsslap)) {
10205 log("EXPECTING BSSLAP: ", expect_bsslap);
10206 log("GOT BSSLAP: ", bsslap);
10207 setverdict(fail, "BSSLAP is not as expected");
10208 mtc.stop;
10209 }
10210 setverdict(pass);
10211}
10212
10213/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
10214const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
10215
10216private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
10217 var PDU_BSSAP_LE rx_bsslap;
10218 BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
10219 f_match_bsslap(rx_bsslap, expect_rx_bsslap);
10220}
10221
10222/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10223 * Request on Lb interface. Either with or without the SMLC doing a BSSLAP TA Request. */
10224private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
10225 f_sleep(1.0);
10226
10227 f_establish_fully(omit, omit);
10228 f_bssap_le_register_imsi(g_pars.imsi, omit);
10229
10230 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10231 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10232
10233 var PDU_BSSAP_LE plr;
10234 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10235
10236 if (not do_ta_request) {
10237 /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
10238 var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
10239 if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
10240 log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
10241 log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
10242 setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
10243 mtc.stop;
10244 }
10245 var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
10246 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
10247 if (not match(bsslap, expect_ta_layer3)) {
10248 log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
10249 log("GOT BSSLAP: ", bsslap);
10250 setverdict(fail, "BSSLAP is not as expected");
10251 mtc.stop;
10252 }
10253 /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
10254 * has no need to request the TA from the BSC and directly responds. */
10255 } else {
10256 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10257 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10258 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10259 }
10260
10261 /* SMLC got the TA from the BSC, now responds with geo information data. */
10262 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10263 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10264 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10265
10266 /* The LCS was using an active A-interface conn. It should still remain active after this. */
10267 f_mo_l3_transceive();
10268
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010269 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010270
10271 f_sleep(2.0);
10272 setverdict(pass);
10273}
10274
10275/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10276 * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
10277private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
10278 f_lcs_loc_req_for_active_ms(false);
10279}
10280testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
10281 var MSC_ConnHdlr vc_conn;
10282 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10283
10284 f_init(1, true);
10285 f_sleep(1.0);
10286 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
10287 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010288 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010289}
10290
10291/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10292 * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
10293private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
10294 f_lcs_loc_req_for_active_ms(true);
10295}
10296testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
10297 var MSC_ConnHdlr vc_conn;
10298 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10299
10300 f_init(1, true);
10301 f_sleep(1.0);
10302 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
10303 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010304 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010305}
10306
10307/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
10308 * conn without an active lchan. */
10309private function f_clear_A_conn() runs on MSC_ConnHdlr
10310{
10311 var BssmapCause cause := 0;
10312 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10313 BSSAP.receive(tr_BSSMAP_ClearComplete);
10314 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10315
10316 timer no_more_bssap := 5.0;
10317 no_more_bssap.start;
10318 alt {
10319 [] no_more_bssap.timeout { break; }
10320 [] BSSAP.receive(tr_BSSAP_BSSMAP) {
10321 setverdict(fail, "Expected no more BSSAP after Clear Complete");
10322 mtc.stop;
10323 }
10324 }
10325 setverdict(pass);
10326}
10327
10328/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
10329 * for LCS, for cases where there is only an A conn without an active lchan. */
10330private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
10331{
10332 f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
10333
10334 /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
10335 * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
10336 * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
10337 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10338 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10339 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10340
10341 /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
10342 f_clear_A_conn();
10343 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10344 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10345}
10346
10347/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10348 * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
10349 */
10350private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
10351 f_sleep(1.0);
10352
10353 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10354 f_bssap_le_register_imsi(g_pars.imsi, omit);
10355
10356 /* Register to receive the Paging Command */
10357 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10358 g_chan_nr := new_chan_nr;
10359 f_rslem_register(0, g_chan_nr);
10360
10361 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10362 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10363 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10364 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10365
10366 var PDU_BSSAP_LE plr;
10367 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10368
10369 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10370 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10371
10372 /* OsmoBSC needs to Page */
10373 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
10374 f_logp(BSCVTY, "got Paging Command");
10375
10376 /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
10377 * the MSC, and releases the lchan directly. */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +020010378 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 +020010379 f_expect_lchan_rel(RSL, RSL_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010380
10381 /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
10382
10383 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10384
10385 /* SMLC got the TA from the BSC, now responds with geo information data. */
10386 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10387 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10388
10389 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10390
10391 /* The lchan is gone, the A-interface conn was created for the LCS only.
10392 * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
10393 f_verify_active_A_conn_and_clear();
10394
10395 f_sleep(2.0);
10396 setverdict(pass);
10397}
10398testcase TC_lcs_loc_req_for_idle_ms() runs on test_CT {
10399 var MSC_ConnHdlr vc_conn;
10400 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10401
10402 f_init(1, true);
10403 f_sleep(1.0);
10404
10405 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10406 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10407
10408 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
10409 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010410 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010411}
10412
10413/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
10414 */
10415private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
10416 f_sleep(1.0);
10417
10418 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10419 f_bssap_le_register_imsi(g_pars.imsi, omit);
10420
10421 /* provoke an abort by omitting both IMSI and IMEI */
10422 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10423 valueof(ts_BSSMAP_Perform_Location_Request(omit,
10424 ts_CellId_CGI('262'H, '42'H, 23, 42)))));
10425 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10426
10427 /* BSC tells MSC about failure */
10428 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10429 locationEstimate := omit, positioningData := omit,
10430 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
10431
10432 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10433 f_verify_active_A_conn_and_clear();
10434
10435 f_sleep(2.0);
10436 setverdict(pass);
10437}
10438testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
10439 var MSC_ConnHdlr vc_conn;
10440 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10441
10442 f_init(1, true);
10443 f_sleep(1.0);
10444
10445 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10446 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10447
10448 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
10449 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010450 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010451}
10452
10453/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10454 * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
10455private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
10456 f_sleep(1.0);
10457
10458 f_establish_fully(omit, omit);
10459 f_bssap_le_register_imsi(g_pars.imsi, omit);
10460
10461 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10462 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10463
10464 var PDU_BSSAP_LE plr;
10465 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10466
10467 if (do_ta) {
10468 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10469 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10470 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10471 }
10472
10473 /* SMLC fails to respond, BSC runs into timeout */
10474 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
10475 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10476
10477 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10478 locationEstimate := omit, positioningData := omit,
10479 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
10480
10481 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10482 f_verify_active_A_conn_and_clear();
10483
10484 f_sleep(2.0);
10485 setverdict(pass);
10486}
10487
10488/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10489 * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
10490private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
10491 f_lcs_loc_req_for_active_ms_le_timeout(false);
10492}
10493
10494testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
10495 var MSC_ConnHdlr vc_conn;
10496 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10497
10498 f_init(1, true);
10499 f_sleep(1.0);
10500 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
10501 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010502 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010503}
10504
10505/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10506 * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
10507private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
10508 f_lcs_loc_req_for_active_ms_le_timeout(true);
10509}
10510
10511testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
10512 var MSC_ConnHdlr vc_conn;
10513 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10514
10515 f_init(1, true);
10516 f_sleep(1.0);
10517 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
10518 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010519 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010520}
10521
10522/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
10523private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
10524 f_sleep(1.0);
10525
10526 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10527 f_bssap_le_register_imsi(g_pars.imsi, omit);
10528
10529 /* Register to receive the Paging Command */
10530 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10531 g_chan_nr := new_chan_nr;
10532 f_rslem_register(0, g_chan_nr);
10533
10534 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10535 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10536 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10537 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10538
10539 var PDU_BSSAP_LE plr;
10540 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10541
10542 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10543 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10544
10545 /* OsmoBSC needs to Page */
10546 var PDU_BSSAP_LE rx_bsslap;
10547 alt {
10548 [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
10549 f_logp(BSCVTY, "got Paging Command");
10550 repeat;
10551 }
10552 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10553 /* MS does not respond to Paging, TA Req runs into timeout. */
10554 f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
10555 }
10556 }
10557
10558 /* SMLC responds with failure */
10559 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10560 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10561
10562 /* BSC tells MSC about failure */
10563 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10564 locationEstimate := omit, positioningData := omit,
10565 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
10566
10567 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10568 f_verify_active_A_conn_and_clear();
10569
10570 f_sleep(2.0);
10571 setverdict(pass);
10572}
10573testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
10574 var MSC_ConnHdlr vc_conn;
10575 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10576
10577 f_init(1, true);
10578 f_sleep(1.0);
10579
10580 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10581 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10582
10583 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
10584 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010585 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010586}
10587
10588/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
10589 * over. */
10590private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10591 f_sleep(1.0);
10592
10593 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10594 f_bssap_le_register_imsi(g_pars.imsi, omit);
10595
10596 /* Register to receive the Paging Command */
10597 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10598 g_chan_nr := new_chan_nr;
10599 f_rslem_register(0, g_chan_nr);
10600
10601 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10602 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10603 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10604 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10605
10606 var PDU_BSSAP_LE plr;
10607 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10608
10609 /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
10610 * and establish Layer 3. It should use the existing A-interface conn. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010611 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 +020010612 do_clear := false, expect_bssmap_l3 := true);
10613
10614 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10615 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10616
10617 /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
10618 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10619
10620 /* SMLC got the TA from the BSC, now responds with geo information data. */
10621 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10622 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10623 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10624
10625 /* The lchan should still exist, it was from a CM Service Request. */
10626 f_mo_l3_transceive();
10627
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010628 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010629
10630 f_sleep(2.0);
10631 setverdict(pass);
10632}
10633testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
10634 var MSC_ConnHdlr vc_conn;
10635 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10636
10637 f_init(1, true);
10638 f_sleep(1.0);
10639
10640 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10641 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10642
10643 vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
10644 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010645 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010646}
10647
10648/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
10649 * the new lchan after handover. */
10650private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10651 f_sleep(1.0);
10652
10653 f_establish_fully(omit, omit);
10654 f_bssap_le_register_imsi(g_pars.imsi, omit);
10655
10656 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10657 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10658
10659 var PDU_BSSAP_LE plr;
10660 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10661
10662 /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
10663 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
10664
10665 var HandoverState hs := {
10666 rr_ho_cmpl_seen := false,
10667 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +020010668 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010669 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010670 };
10671 /* issue hand-over command on VTY */
10672 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
10673 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
10674 f_rslem_suspend(RSL1_PROC);
10675
10676 /* From the MGW perspective, a handover is is characterized by
10677 * performing one MDCX operation with the MGW. So we expect to see
10678 * one more MDCX during handover. */
10679 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
10680
10681 alt {
10682 [] as_handover(hs);
10683 }
10684
10685 var PDU_BSSAP_LE rx_bsslap;
10686
10687 interleave {
10688 /* Expect the BSC to inform the MSC about the handover */
10689 [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
10690
10691 /* Expect the BSC to inform the SMLC about the handover */
10692 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10693 f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
10694 }
10695 }
10696
10697 /* SMLC now responds with geo information data. */
10698 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10699 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10700 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10701
10702 /* lchan still active */
10703 f_mo_l3_transceive(RSL1);
10704
10705 /* MSC decides it is done now. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010706 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010707
10708 f_sleep(2.0);
10709 setverdict(pass);
10710}
10711testcase TC_ho_during_lcs_loc_req() runs on test_CT {
10712 var MSC_ConnHdlr vc_conn;
10713 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10714
10715 f_init(2, true);
10716 f_sleep(1.0);
10717 vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
10718 vc_conn.done;
Oliver Smith39f53072022-10-27 14:44:04 +020010719 f_shutdown_helper(ho := true);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010720}
10721
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010722private function f_tc_emerg_call_and_lcs_loc_req(charstring id) runs on MSC_ConnHdlr
10723{
10724 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
10725 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
10726 * another lchan. */
Pau Espin Pedrol1809bce2023-01-03 16:54:41 +010010727 g_pars.ra := f_rnd_ra_emerg();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010728 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010729 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010730
10731 /* Here would usually be a CC Call Proceeding from the MSC, but what does the BSC care about DTAP. */
10732
10733 /* Do a Location Request in-between the CC call setup */
10734 f_bssap_le_register_imsi(g_pars.imsi, omit);
10735 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10736 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10737 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10738 /* SMLC got the TA from the BSC, now responds with geo information data. */
10739 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10740 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10741 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10742
Pau Espin Pedrol14076d32023-01-03 17:07:59 +010010743 f_assignment_emerg_setup_voice();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010744
10745 setverdict(pass);
10746 f_perform_clear();
10747}
10748
10749testcase TC_emerg_call_and_lcs_loc_req() runs on test_CT {
10750 var MSC_ConnHdlr vc_conn;
10751 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10752
10753 f_init(1, true);
10754 f_sleep(1.0);
10755 f_vty_allow_emerg_msc(true);
10756 f_vty_allow_emerg_bts(true, 0);
10757 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req), pars);
10758 vc_conn.done;
10759 f_shutdown_helper();
10760}
10761
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010762private altstep no_bssmap_clear_req() runs on MSC_ConnHdlr {
10763 [] BSSAP.receive(tr_BSSMAP_ClearRequest) {
10764 setverdict(fail, "unexpected BSSMAP Clear Request");
10765 mtc.stop;
10766 }
10767}
10768
10769private type enumerated RslRel {
10770 RSLREL_REL_IND,
10771 RSLREL_CONN_FAIL
10772};
10773
10774private function f_emerg_call_and_lcs_loc_req_early_lchan_release(RslRel rsl_rel) runs on MSC_ConnHdlr
10775{
10776 g_pars.ra := f_rnd_ra_emerg();
10777 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010778 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010779
10780 /* Start a Location Request to locate the emergency */
10781 f_bssap_le_register_imsi(g_pars.imsi, omit);
10782 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10783 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10784 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10785
10786 /* 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
10787 * do a Clear Command when the Location Response arrives. */
10788 activate(no_bssmap_clear_req());
10789
10790 /* the lchan gets interrupted while the Location Request has no response */
10791 select (rsl_rel) {
10792 case (RSLREL_REL_IND) {
10793 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
10794 f_expect_lchan_rel(RSL, RSL_PROC);
10795 }
10796 case (RSLREL_CONN_FAIL) {
10797 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
10798 }
10799 case else {
10800 setverdict(fail, "Unknown RslRel type");
10801 mtc.stop;
10802 }
10803 }
10804
10805 /* Still expect the Location Response to find its way to the MSC. */
10806 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10807 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10808 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10809
10810 setverdict(pass);
10811
10812 select (rsl_rel) {
10813 case (RSLREL_REL_IND) {
10814 f_perform_clear_no_lchan();
10815 }
10816 case (RSLREL_CONN_FAIL) {
10817 f_perform_clear();
10818 }
10819 }
10820}
10821
10822private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind(charstring id) runs on MSC_ConnHdlr
10823{
10824 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_REL_IND);
10825}
10826
10827testcase TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() runs on test_CT {
10828 var MSC_ConnHdlr vc_conn;
10829 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10830
10831 f_init(1, true);
10832 f_sleep(1.0);
10833 f_vty_allow_emerg_msc(true);
10834 f_vty_allow_emerg_bts(true, 0);
10835 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind), pars);
10836 vc_conn.done;
10837 f_shutdown_helper();
10838}
10839
10840private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail(charstring id) runs on MSC_ConnHdlr
10841{
10842 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_CONN_FAIL);
10843}
10844
10845testcase TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() runs on test_CT {
10846 var MSC_ConnHdlr vc_conn;
10847 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10848
10849 f_init(1, true);
10850 f_sleep(1.0);
10851 f_vty_allow_emerg_msc(true);
10852 f_vty_allow_emerg_bts(true, 0);
10853 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail), pars);
10854 vc_conn.done;
10855 f_shutdown_helper();
10856}
10857
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010858/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
10859private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
10860 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10861
10862 /* Also disable attach for the single connected MSC */
10863 f_vty_msc_allow_attach(BSCVTY, { false });
10864
10865 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) ));
10866 f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
10867
10868 /* No MSC is found, expecting a proper release on RSL */
10869 interleave {
10870 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
10871 f_logp(BSCVTY, "Got RSL RR Release");
10872 }
10873 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10874 f_logp(BSCVTY, "Got RSL Deact SACCH");
10875 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010876 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010877 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
10878 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010879 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010880 }
10881 }
10882 setverdict(pass);
10883}
10884testcase TC_no_msc() runs on test_CT {
10885
10886 f_init(1, true);
10887 f_sleep(1.0);
10888 var MSC_ConnHdlr vc_conn;
10889 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10890
10891 f_ctrs_bsc_init(counternames_bsc_mscpool);
10892
10893 vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
10894 vc_conn.done;
10895
10896 f_ctrs_bsc_add("mscpool:subscr:no_msc");
10897 f_ctrs_bsc_verify();
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010898 f_shutdown_helper();
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010899}
10900
Harald Welte0ea2d5e2018-04-07 21:40:29 +020010901/* Dyn PDCH todo:
10902 * activate OSMO as TCH/F
10903 * activate OSMO as TCH/H
10904 * does the BSC-located PCU socket get the updated INFO?
10905 * what if no PCU is connected at the time?
10906 * is the info correct on delayed PCU (re)connect?
10907 */
Harald Welte94e0c342018-04-07 11:33:23 +020010908
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010909private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +020010910 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020010911 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010912
10913 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
10914 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10915 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
10916 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
10917 g_pars.ass_codec_list.codecElements[0];
10918 if (isvalue(g_pars.expect_mr_s0_s7)) {
10919 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
10920 g_pars.expect_mr_s0_s7;
10921 }
10922 }
10923 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
10924 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
10925 log("expecting ASS COMPL like this: ", exp_compl);
10926
10927 f_establish_fully(ass_cmd, exp_compl);
10928
Neels Hofmeyr8746b0d2021-06-01 17:25:39 +020010929 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 +000010930
10931 var RSL_Message rsl;
10932
10933 timer T := 5.0;
10934 T.start;
10935 alt {
10936 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
10937 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
10938 log("Rx L3 from net: ", l3);
10939 if (ischosen(l3.msgs.rrm.channelModeModify)) {
10940 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10941 mtc.stop;
10942 }
10943 }
10944 [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
10945 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10946 mtc.stop;
10947 }
10948 [] T.timeout {
10949 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
10950 setverdict(pass);
10951 }
10952 }
10953 T.stop;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010954
10955 f_perform_clear();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010956}
10957
10958/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
10959 * osmo-bsc. */
10960testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
10961 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10962 var MSC_ConnHdlr vc_conn;
10963
10964 f_init(1, true);
10965 f_sleep(1.0);
10966
10967 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10968 vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
10969 vc_conn.done;
10970 f_shutdown_helper();
10971}
10972
10973/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
10974 */
10975testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
10976 f_init_vty();
10977
10978 f_init(1, false);
10979 f_sleep(1.0);
10980
10981 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
10982
10983 var ASP_RSL_Unitdata rx_rsl_ud;
10984 timer T := 5.0;
10985
10986 T.start;
10987 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010988 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010989 if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
10990 T.stop;
10991 setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
10992 mtc.stop;
10993 }
10994 repeat;
10995 }
10996 [] T.timeout {
10997 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
10998 setverdict(pass);
10999 }
11000 }
11001}
11002
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011003private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
11004 /* First fully set up a speech lchan */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011005 f_assignment_codec(id, do_perform_clear := false);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011006
11007 /* Trigger re-assignment to another lchan */
11008 var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
11009
11010 /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
11011 * one MDCX on MGCP. */
11012 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
11013
11014 /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
11015 * as the old lchan used. */
11016 g_media.bts.ipa_crcx_seen := false;
11017 g_media.bts.ipa_mdcx_seen := false;
11018
11019 /* Send different BTS side RTP port number for the new lchan */
11020 g_media.bts.bts.port_nr := 4223;
11021
11022 f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
11023
11024 /* Trigger re-assignment. */
11025 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
11026
11027 timer T := 5.0;
11028 T.start;
11029 alt {
11030 [] as_assignment(assignment_st);
11031 [] as_Media();
11032 [] T.timeout {
11033 break;
11034 }
11035 }
11036
11037 if (not assignment_st.assignment_done) {
11038 setverdict(fail, "Assignment did not complete");
11039 mtc.stop;
11040 }
11041
11042 f_check_mgcp_expectations()
11043 setverdict(pass);
11044
11045 f_sleep(2.0);
11046 log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
11047
11048 /* Instruct BSC to clear channel */
11049 var BssmapCause cause := 0;
11050 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
11051 interleave {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011052 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
11053 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020011054 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011055 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020011056 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011057 }
11058 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
11059 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11060 }
11061 }
Neels Hofmeyr40a45d12021-09-23 22:57:12 +020011062 f_expect_dlcx_conns();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011063
11064 f_sleep(0.5);
11065}
11066
11067testcase TC_reassignment_fr() runs on test_CT {
11068 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11069 var MSC_ConnHdlr vc_conn;
11070
11071 f_init(1, true);
11072 f_sleep(1.0);
11073
Neels Hofmeyrac432fa2021-11-02 16:45:56 +010011074 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011075
11076 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11077 vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
11078 vc_conn.done;
11079
11080 /* from f_establish_fully() */
11081 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
11082 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
11083 /* from re-assignment */
11084 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
11085 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
11086 f_ctrs_bsc_and_bts_verify();
11087 f_shutdown_helper();
11088}
11089
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011090const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
11091const charstring REEST_CLEAR := "REEST_CLEAR";
11092const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
11093
11094/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
11095 * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
11096 * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
11097 * the MSC as the CM Re-Establishment is handled.
11098 *
11099 * MS bts0 bts1 bsc msc test-component
11100 * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
11101 * | | _1 wait a bit, to settle down
11102 * |<-x x--| | _1 "lose connection"
11103 * | | REEST_LOST_CONNECTION
11104 * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
11105 * | | REEST_CLEAR
11106 * | |<-0---| _1 Clear Command on first A-conn
11107 * | |--0-->| _1 Clear Complete
11108 * | |<----------------->| | _1 Release first channel
11109 * | | REEST_CLEAR_DONE
11110 * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
11111 * |<-----------------|<-------|<-1---| _2 Clear Command, Release
11112 *
11113 */
11114private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
11115 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
11116 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11117
11118 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11119 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11120
11121 f_establish_fully(ass_cmd, exp_compl);
11122
11123 /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
11124 * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
11125 * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
11126 f_sleep(2.0);
11127 COORD.send(REEST_LOST_CONNECTION);
11128
11129 alt {
11130 [] COORD.receive(REEST_CLEAR);
11131 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
11132 setverdict(fail, "Unexpected channel release");
11133 mtc.stop;
11134 }
11135 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
11136 setverdict(fail, "Unexpected channel release");
11137 mtc.stop;
11138 }
11139 }
11140 f_perform_clear()
Neels Hofmeyr969abd02021-09-23 22:24:08 +020011141 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011142 COORD.send(REEST_CLEAR_DONE);
11143}
11144
11145private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
11146 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
11147
11148 /* The MS lost the connection on the first channel, now establishes another one */
11149 COORD.receive(REEST_LOST_CONNECTION);
11150
11151 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
11152 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
11153 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
11154
11155 f_create_bssmap_exp(l3_enc);
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011156 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 +020011157 BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
11158
11159 /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
11160 COORD.send(REEST_CLEAR);
11161 COORD.receive(REEST_CLEAR_DONE);
11162
11163 f_sleep(2.0);
11164
11165 /* Answer the CM Re-Establishment with an Assignment Command. */
11166 var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
11167 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11168 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11169 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11170
11171 var AssignmentState st := valueof(ts_AssignmentStateInit);
Oliver Smithce2dd692023-04-17 10:25:50 +020011172 st.rtp_stream := true;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011173 st.is_assignment := true;
11174
11175 var ExpectCriteria mgcpcrit := {
11176 connid := omit,
11177 endpoint := omit,
11178 transid := omit
11179 };
11180 f_create_mgcp_expect(mgcpcrit);
11181
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011182 f_rslem_dchan_queue_enable(RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011183
11184 BSSAP.send(ass_cmd);
11185
11186 var PDU_BSSAP bssap;
11187
11188 alt {
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011189 [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
11190 [] as_Media_ipacc(RSL1, RSL2);
11191 [] as_Media_mgw();
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011192 [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
11193 break;
11194 }
11195 }
11196
11197 f_sleep(3.0);
11198
11199 f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011200 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011201}
11202
11203testcase TC_cm_reestablishment() runs on test_CT {
11204 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
11205 var MSC_ConnHdlr vc_conn1;
11206
11207 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
11208 var MSC_ConnHdlr vc_conn2;
11209 pars2.imsi := pars1.imsi;
11210 pars2.media_nr := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011211 pars2.expect_tsc := c_BtsParams[1].tsc;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011212
11213 f_init(2, true, guard_timeout := 40.0);
11214 f_sleep(1.0);
11215
11216 vc_conn1 := f_start_handler_create(pars1);
11217 vc_conn2 := f_start_handler_create(pars2);
11218 connect(vc_conn1:COORD, vc_conn2:COORD);
11219 f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
11220 f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
11221 vc_conn1.done;
11222 vc_conn2.done;
11223
11224 f_shutdown_helper();
11225}
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011226
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011227function f_exp_ipa_rx_nonfatal(template (present) RSL_Message t_rx,
11228 boolean ignore_other_rx := true,
11229 BtsTrxIdx idx := {0, 0},
11230 float Tval := 2.0)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011231runs on test_CT return template (omit) RSL_Message {
11232 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011233 timer T := Tval;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011234
11235 T.start;
11236 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011237 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011238 T.stop;
11239 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011240 [ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
11241 [not ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011242 log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
11243 T.stop;
11244 return omit;
11245 }
11246 [] T.timeout {
11247 return omit;
11248 }
11249 }
11250 return rx_rsl_ud.rsl;
11251}
11252
11253private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
11254 f_vty_enter_cfg_bts(pt, bts_nr);
11255 f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
11256 f_vty_transceive(pt, "exit");
11257 f_vty_transceive(pt, "exit");
11258 f_vty_transceive(pt, "exit");
11259}
11260
11261private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +030011262 template (present) RslChannelNr chan_nr := ?,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011263 template (present) uint12_t arfcn := ?,
11264 template (present) uint3_t tsc := ?)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011265{
11266 var RSL_IE_Body full_imm_ass_info;
11267 if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
11268 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
11269 mtc.stop;
11270 }
11271
11272 var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
11273 var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
11274 fn := fn,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011275 ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011276 page_mode := ?);
11277 if (not match(rr_imm_ass, expect_imm_ass)) {
11278 log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
11279 setverdict(fail, "Failed to match Immediate Assignment");
11280 mtc.stop;
11281 }
11282}
11283
11284testcase TC_imm_ass_post_chan_ack() runs on test_CT {
11285 var RSL_Message chan_act;
11286 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011287 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011288
11289 f_init(1, false);
11290 f_sleep(1.0);
11291
11292 /* (should be the default anyway, just to make things clear) */
11293 f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
11294
11295 /* RA containing reason=LU */
11296 var GsmFrameNumber fn := 2342;
11297 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011298 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011299
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011300 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011301
11302 /* First send the Chan Act ACK */
11303 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011304 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011305 var RSL_IE_Body chan_ident_ie;
11306 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11307 setverdict(fail, "RSL Channel Identification IE is absent");
11308 mtc.stop;
11309 }
11310
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011311 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011312
11313 /* Then expect the Immediate Assignment, after we ACKed the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011314 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011315
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011316 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11317 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011318
11319 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011320 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011321
11322 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011323 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011324 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011325 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11326
11327 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011328 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011329 f_shutdown_helper();
11330}
11331
11332testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
11333 var RSL_Message chan_act;
11334 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011335 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011336
11337 f_init(1, false);
11338 f_sleep(1.0);
11339
11340 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11341
11342 /* RA containing reason=LU */
11343 var GsmFrameNumber fn := 2342;
11344 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011345 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011346
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011347 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011348 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011349 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011350 var RSL_IE_Body chan_ident_ie;
11351 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11352 setverdict(fail, "RSL Channel Identification IE is absent");
11353 mtc.stop;
11354 }
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011355
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011356 /* (set bts 0 cfg back to default) */
11357 f_vty_set_imm_ass(BSCVTY);
11358
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011359 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011360 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011361 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11362 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011363
11364 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011365 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011366
11367 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011368 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011369
11370 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011371 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011372 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011373 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11374
11375 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011376 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011377 f_shutdown_helper();
11378}
11379
Neels Hofmeyr23158742021-09-07 19:08:07 +020011380testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
11381 var RSL_Message chan_act;
11382 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011383 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr23158742021-09-07 19:08:07 +020011384
11385 f_init(1, false);
11386 f_sleep(1.0);
11387
11388 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11389
11390 /* RA containing reason=LU */
11391 var GsmFrameNumber fn := 2342;
11392 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011393 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011394
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011395 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011396 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011397 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr23158742021-09-07 19:08:07 +020011398 var RSL_IE_Body chan_ident_ie;
11399 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11400 setverdict(fail, "RSL Channel Identification IE is absent");
11401 mtc.stop;
11402 }
11403
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011404 /* (set bts 0 cfg back to default) */
11405 f_vty_set_imm_ass(BSCVTY);
11406
Neels Hofmeyr23158742021-09-07 19:08:07 +020011407 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011408 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011409 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11410 chan_ident_ie.chan_ident.ch_desc.v.tsc);
11411
11412 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011413 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011414
11415 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011416 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011417
11418 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011419 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011420 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr23158742021-09-07 19:08:07 +020011421 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11422
11423 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011424 f_perform_clear_test_ct(dt);
Neels Hofmeyr23158742021-09-07 19:08:07 +020011425 f_shutdown_helper();
11426}
11427
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011428testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
11429 /* change Timeslot 6 before f_init() starts RSL */
11430 f_init_vty();
11431 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11432 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11433
11434 f_init(1, false);
11435 f_sleep(1.0);
11436
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011437 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011438 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11439 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011440 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11441 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011442
11443 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11444 f_ts_set_chcomb(0, 0, 6, "PDCH");
11445
11446 /* block all static timeslots so that the dyn TS will be used */
11447 f_disable_all_tch_f();
11448 f_disable_all_tch_h();
11449 f_disable_all_sdcch();
11450
11451 var RSL_Message chan_act;
11452 var RSL_Message imm_ass;
11453
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011454 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11455
11456 /* RA containing reason=LU */
11457 var GsmFrameNumber fn := 2342;
11458 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011459 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011460
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011461 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011462 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
11463 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011464
11465 /* Now activation as SDCCH8 */
11466 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011467 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011468
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011469 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011470 var RSL_IE_Body chan_ident_ie;
11471 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11472 setverdict(fail, "RSL Channel Identification IE is absent");
11473 mtc.stop;
11474 }
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011475
11476 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011477 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011478 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11479 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011480
11481 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011482 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011483
11484 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011485 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011486
11487 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011488 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011489 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011490 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11491
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011492 /* (set bts 0 cfg back to default) */
11493 f_vty_set_imm_ass(BSCVTY);
11494
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011495 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011496 f_perform_clear_test_ct(dt);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011497 f_shutdown_helper();
11498}
11499
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011500testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
11501 /* change Timeslot 6 before f_init() starts RSL */
11502 f_init_vty();
11503 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11504 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11505
11506 f_init(1, false);
11507 f_sleep(1.0);
11508
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011509 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011510 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11511 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011512 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11513 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011514
11515 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11516 f_ts_set_chcomb(0, 0, 6, "PDCH");
11517
11518 /* block all static timeslots so that the dyn TS will be used */
11519 f_disable_all_tch_f();
11520 f_disable_all_tch_h();
11521 f_disable_all_sdcch();
11522
11523 var RSL_Message chan_act;
11524 var RSL_Message imm_ass;
11525
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011526 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11527
11528 /* RA containing reason=LU */
11529 var GsmFrameNumber fn := 2342;
11530 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011531 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011532
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011533 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011534 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011535
11536 /* And already the Immediate Assignment even before the PDCH Deact ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011537 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011538
11539 /* continue the Osmo style PDCH Deact (usual chan rel) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011540 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011541
11542 /* Now activation as SDCCH8 */
11543 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011544 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011545
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011546 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011547 var RSL_IE_Body chan_ident_ie;
11548 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11549 setverdict(fail, "RSL Channel Identification IE is absent");
11550 mtc.stop;
11551 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011552 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011553
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011554 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11555 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011556
11557 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011558 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011559
11560 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011561 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011562 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011563 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11564
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011565 /* (set bts 0 cfg back to default) */
11566 f_vty_set_imm_ass(BSCVTY);
11567
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011568 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011569 f_perform_clear_test_ct(dt);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011570 f_shutdown_helper();
11571}
11572
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011573/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
11574testcase TC_ctrl_trx_rf_locked() runs on test_CT {
11575 var MSC_ConnHdlr vc_conn;
11576
11577 f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
11578 f_sleep(1.0);
11579
11580 /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
11581 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11582 "0,0,operational,unlocked,on,rsl-up;" &
11583 "1,0,operational,unlocked,on,rsl-up;" &
11584 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011585 "2,1,operational,unlocked,on,rsl-down;" &
11586 "2,2,operational,unlocked,on,rsl-down;" &
11587 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011588 "3,0,inoperational,locked,on,rsl-down;");
11589
11590 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock BTS 1 TRX 0");
11591 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11592 /* give it a moment to settle the FSM status */
11593 f_sleep(1.0);
11594
11595 /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
11596 * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
11597 * of "off"? But that's for a future patch if at all. */
11598 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11599 "0,0,operational,unlocked,on,rsl-up;" &
11600 "1,0,operational,locked,on,rsl-up;" &
11601 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011602 "2,1,operational,unlocked,on,rsl-down;" &
11603 "2,2,operational,unlocked,on,rsl-down;" &
11604 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011605 "3,0,inoperational,locked,on,rsl-down;");
11606
11607 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
11608 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11609 f_sleep(1.0);
11610 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11611 "0,0,operational,unlocked,on,rsl-up;" &
11612 "1,0,operational,locked,on,rsl-up;" &
11613 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011614 "2,1,operational,unlocked,on,rsl-down;" &
11615 "2,2,operational,unlocked,on,rsl-down;" &
11616 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011617 "3,0,inoperational,locked,on,rsl-down;");
11618
11619 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
11620 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
11621 f_sleep(1.0);
11622 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11623 "0,0,operational,unlocked,on,rsl-up;" &
11624 "1,0,operational,unlocked,on,rsl-up;" &
11625 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011626 "2,1,operational,unlocked,on,rsl-down;" &
11627 "2,2,operational,unlocked,on,rsl-down;" &
11628 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011629 "3,0,inoperational,locked,on,rsl-down;");
11630
11631 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
11632 f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
11633 f_sleep(1.0);
11634 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11635 "0,0,operational,unlocked,on,rsl-up;" &
11636 "1,0,operational,unlocked,on,rsl-up;" &
11637 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011638 "2,1,operational,unlocked,on,rsl-down;" &
11639 "2,2,operational,unlocked,on,rsl-down;" &
11640 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011641 "3,0,inoperational,locked,on,rsl-down;");
11642
11643 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
11644 f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
11645 f_sleep(1.0);
11646 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11647 "0,0,operational,unlocked,on,rsl-up;" &
11648 "1,0,operational,unlocked,on,rsl-up;" &
11649 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011650 "2,1,operational,unlocked,on,rsl-down;" &
11651 "2,2,operational,unlocked,on,rsl-down;" &
11652 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011653 "3,0,inoperational,locked,on,rsl-down;");
11654
11655 f_shutdown_helper();
11656}
11657
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011658const CounterNameVals counternames_cm_serv_rej := {
11659 { "cm_serv_rej", 0 },
11660 { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
11661 { "cm_serv_rej:illegal_ms", 0 },
11662 { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
11663 { "cm_serv_rej:imei_not_accepted", 0 },
11664 { "cm_serv_rej:illegal_me", 0 },
11665 { "cm_serv_rej:plmn_not_allowed", 0 },
11666 { "cm_serv_rej:loc_not_allowed", 0 },
11667 { "cm_serv_rej:roaming_not_allowed", 0 },
11668 { "cm_serv_rej:network_failure", 0 },
11669 { "cm_serv_rej:synch_failure", 0 },
11670 { "cm_serv_rej:congestion", 0 },
11671 { "cm_serv_rej:srv_opt_not_supported", 0 },
11672 { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
11673 { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
11674 { "cm_serv_rej:call_can_not_be_identified", 0 },
11675 { "cm_serv_rej:incorrect_message", 0 },
11676 { "cm_serv_rej:invalid_mandantory_inf", 0 },
11677 { "cm_serv_rej:msg_type_not_implemented", 0 },
11678 { "cm_serv_rej:msg_type_not_compatible", 0 },
11679 { "cm_serv_rej:inf_eleme_not_implemented", 0 },
11680 { "cm_serv_rej:condtional_ie_error", 0 },
11681 { "cm_serv_rej:msg_not_compatible", 0 },
11682 { "cm_serv_rej:protocol_error", 0 },
11683 { "cm_serv_rej:retry_in_new_cell", 0 }
11684};
11685
11686private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
11687{
11688 f_create_chan_and_exp();
Vadim Yanitskiya7fc5a62021-12-04 20:10:08 +030011689 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011690 BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011691 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_CM_SERV_REJ));
11692 f_perform_clear();
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011693 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011694}
11695testcase TC_cm_serv_rej() runs on test_CT {
11696 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11697 var MSC_ConnHdlr vc_conn;
11698
11699 f_init(1, true);
11700 f_sleep(1.0);
11701
11702 f_ctrs_bts_init(1, counternames_cm_serv_rej);
11703
11704 vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
11705 vc_conn.done;
11706
11707 f_ctrs_bts_add(0, "cm_serv_rej", 1);
11708 f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
11709 f_ctrs_bts_verify();
11710
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011711 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011712 f_shutdown_helper();
11713}
11714
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011715/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
11716 * Activ Ack (SYS#5627). */
11717private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
11718 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Vadim Yanitskiyf0310e32021-10-26 00:30:59 +030011719
11720 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11721 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011722
11723 var BSSMAP_FIELD_CodecType codecType;
11724 codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
11725
11726 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
11727
11728 /* First establish a signalling lchan */
11729 f_create_chan_and_exp();
11730 f_rslem_dchan_queue_enable();
11731
11732 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011733
11734 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
Oliver Smith735b47c2023-02-15 16:03:54 +010011735 activate(as_Media_mgw());
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011736
11737 var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
11738 f_rslem_register(0, chan_nr);
11739
11740 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
11741 BSSAP.send(ass_cmd);
11742
11743
11744 /* Wait for the Channel Activ for the TCH channel */
11745 var ASP_RSL_Unitdata rx_rsl_ud;
11746 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
11747
11748 /* make the original SDCCH disappear */
11749 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
11750
11751 /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
11752 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
11753
11754 interleave {
11755 [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
11756 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
11757 }
11758
11759 BSSAP.send(ts_BSSMAP_ClearCommand(0));
11760 BSSAP.receive(tr_BSSMAP_ClearComplete);
11761 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11762
11763 var MgcpCommand mgcp;
Vadim Yanitskiy6be4cf42022-06-04 21:25:47 +060011764 var MGCP_RecvFrom mrf;
11765 var template MgcpMessage msg_dlcx := { command := tr_DLCX };
11766 alt {
11767 [g_pars.aoip] MGCP.receive(tr_DLCX) -> value mgcp {
11768 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
11769 }
11770 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
11771 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
11772 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
11773 }));
11774 }
11775 }
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011776
11777 f_sleep(0.5);
11778}
11779testcase TC_lost_sdcch_during_assignment() runs on test_CT {
11780 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11781 var MSC_ConnHdlr vc_conn;
11782
Oliver Smith735b47c2023-02-15 16:03:54 +010011783 pars.fail_on_dlcx := false;
11784
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011785 f_init(1, true);
11786 f_sleep(1.0);
11787
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011788 vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
11789 vc_conn.done;
11790
11791 f_shutdown_helper();
11792}
11793
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011794const CounterNameVals counternames_bsc_bts_all_available_allocated := {
11795 { "all_allocated:sdcch", 0 },
11796 { "all_allocated:static_sdcch", 0 },
11797 { "all_allocated:tch", 0 },
11798 { "all_allocated:static_tch", 0 }
11799}
11800
11801private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
11802{
11803 /* Make sure counters settle first */
11804 f_sleep(1.0);
11805
11806 /* Take a baseline of counters */
11807 f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
11808
11809 /* Elapse some time so that we see changes in counters, hopefully where expected */
11810 f_sleep(2.0);
11811
11812 /* Get new counters */
11813 var charstring_list all_changed := {};
11814 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
11815 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
11816
11817 /* Compare with expectations */
11818 var charstring_list all_expect_changed := {};
11819 for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
11820 all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
11821 }
11822 f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
11823}
11824
11825testcase TC_ratectr_all_available_allocated() runs on test_CT {
11826 var ASP_RSL_Unitdata rsl_ud;
11827 var integer i;
11828 var integer chreq_total, chreq_nochan;
11829
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011830 f_init(1, guard_timeout := 60.0);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011831 f_sleep(1.0);
11832
11833 /* Exhaust all dedicated SDCCH lchans.
11834 /* GSM 44.018 Table 9.1.8.2:
11835 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11836 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011837 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011838 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011839 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 +020011840 }
11841
11842 /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
11843 * level.
11844 * All SDCCH are now occupied. */
11845 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11846
11847 /* Also fill up all remaining (TCH) channels */
11848 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011849 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 +020011850 }
11851
11852 /* All TCH are now also occupied */
11853 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11854 "all_allocated:tch", "all_allocated:static_tch"});
11855
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011856 /* Clean up SDCCH lchans */
11857 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11858 f_perform_clear_test_ct(chan_cleanup[i]);
11859 }
11860
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011861 f_shutdown_helper();
11862}
11863
11864testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
11865 var ASP_RSL_Unitdata rsl_ud;
11866 var integer i;
11867 var integer chreq_total, chreq_nochan;
11868
11869 f_init_vty();
11870 f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
11871 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11872 /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
11873
11874 f_init(1, guard_timeout := 60.0);
11875 f_sleep(1.0);
11876
11877 /* The dyn TS wants to activate PDCH mode, ACK that. */
11878 var RslChannelNr chan_nr;
11879 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011880 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11881 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011882
11883 /* Exhaust all dedicated SDCCH lchans.
11884 /* GSM 44.018 Table 9.1.8.2:
11885 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11886 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011887 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011888 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011889 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 +020011890 }
11891
11892 /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
11893 * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
11894 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
11895
11896 /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
11897 * Will release them later, so remember all the DchanTuples. */
11898 var DchanTuples dyn_sddch := {};
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011899 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 +020011900
11901 /* Also occupy the seven other SDCCH of the dyn TS */
11902 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011903 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 +020011904 }
11905
11906 /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
11907 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11908
11909 /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
11910 for (i := 0; i < 5; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011911 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 +020011912 }
11913
11914 /* All TCH lchans are now also occupied, both static and dynamic */
11915 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11916 "all_allocated:tch", "all_allocated:static_tch"});
11917
11918 /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
11919 * incrementing. */
11920 var BssmapCause cause := 0;
11921 var DchanTuple dt := dyn_sddch[0];
11922 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011923 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011924
11925 /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
11926 * count as occupied, so those still both increment. */
11927 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
11928 "all_allocated:tch", "all_allocated:static_tch"});
11929
11930 /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
11931 for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
11932 dt := dyn_sddch[i];
11933 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011934 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011935 }
11936
11937 /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
11938 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011939 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11940 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011941
11942 /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
11943 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
11944
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011945 /* Clean up SDCCH lchans */
11946 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11947 f_perform_clear_test_ct(chan_cleanup[i]);
11948 }
11949
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011950 /* clean up config */
11951 f_ts_reset_chcomb(0);
11952
11953 f_shutdown_helper();
11954}
11955
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011956private function f_TC_chan_alloc_algo(DchanTuple dt, BtsTrxIdx idx)
11957runs on test_CT {
11958 /* MSC sends an Assignment Request */
11959 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11960 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11961 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11962 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
11963
11964 /* Expect the BSC to allocate a TCH channel on the given BTS/TRX */
11965 var RSL_Message rsl_chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
11966 /* Send CHAN ACT NACK, so that the requested TCH channel becomes BORKEN */
11967 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(rsl_chan_act.ies[0].body.chan_nr, RSL_ERR_EQUIPMENT_FAIL), idx);
11968 /* Expect to receive an Assignment Failure */
11969 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail));
11970}
11971
11972testcase TC_chan_alloc_algo_ascending() runs on test_CT {
11973 /* We need to access BTS2, which has 4 TRXs */
11974 f_init(nr_bts := 3);
11975
11976 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020011977 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011978
11979 f_vty_enter_cfg_bts(BSCVTY, 2);
11980 f_vty_transceive(BSCVTY, "channel allocator ascending");
11981 f_vty_transceive(BSCVTY, "end");
11982
11983 /* Expect the BSC to allocate 4 x TCH/F channels on BTS2/TRX0 */
11984 for (var integer i := 0; i < 4; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011985 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011986 f_TC_chan_alloc_algo(dt, {2, 0});
11987 f_perform_clear_test_ct(dt);
11988 }
11989
11990 /* At this point all 4 x TCH/F channels are BORKEN, but they will be
11991 * resurrected upon the A-bis/OML link re-establishment. */
11992 f_shutdown_helper();
11993}
11994
11995testcase TC_chan_alloc_algo_descending() runs on test_CT {
11996 /* We need to access BTS2, which has 4 TRXs */
11997 f_init(nr_bts := 3);
11998
11999 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012000 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012001
12002 f_vty_enter_cfg_bts(BSCVTY, 2);
12003 f_vty_transceive(BSCVTY, "channel allocator descending");
12004 f_vty_transceive(BSCVTY, "end");
12005
12006 /* Expect the BSC to allocate 5 x TCH/F channels on BTS2/TRX3 */
12007 for (var integer i := 0; i < 5; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012008 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012009 f_TC_chan_alloc_algo(dt, {2, 3});
12010 f_perform_clear_test_ct(dt);
12011 }
12012
12013 /* At this point all 5 x TCH/F channels are BORKEN, but they will be
12014 * resurrected upon the A-bis/OML link re-establishment. */
12015 f_shutdown_helper();
12016}
12017
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012018testcase TC_chan_alloc_algo_ass_dynamic() runs on test_CT {
12019 const BtsTrxIdx TRX0 := {2, 0};
12020 const BtsTrxIdx TRX3 := {2, 3};
12021
12022 /* We need to access BTS2, which has 4 TRXs */
12023 f_init(nr_bts := 3);
12024
12025 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012026 vc_MGCP[0].stop;
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012027
12028 f_vty_enter_cfg_bts(BSCVTY, 2);
12029 f_vty_transceive(BSCVTY, "channel allocator mode assignment dynamic");
12030 f_vty_transceive(BSCVTY, "channel allocator dynamic-param ul-rxlev thresh 50 avg-num 2");
12031 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 0");
12032 f_vty_transceive(BSCVTY, "end");
12033
12034 var DchanTuple dt;
12035
12036 f_logp(BSCVTY, "Case a) Unknown Uplink RxLev, fall-back to ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012037 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012038 f_TC_chan_alloc_algo(dt, TRX0);
12039 f_perform_clear_test_ct(dt);
12040
12041 f_logp(BSCVTY, "Case b) Not enough RxLev samples, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012042 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012043 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12044 ts_RSL_IE_UplinkMeas(30, 0),
12045 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012046 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012047 f_TC_chan_alloc_algo(dt, TRX0);
12048 f_perform_clear_test_ct(dt);
12049
12050 f_logp(BSCVTY, "Case c) Uplink RxLev below the threshold, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012051 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012052 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12053 ts_RSL_IE_UplinkMeas(45, 0),
12054 ts_RSL_IE_BS_Power(0)), TRX0);
12055 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12056 ts_RSL_IE_UplinkMeas(48, 0),
12057 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012058 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012059 f_TC_chan_alloc_algo(dt, TRX0);
12060 f_perform_clear_test_ct(dt);
12061
12062 f_logp(BSCVTY, "Case d) Uplink RxLev above the threshold, use descending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012063 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012064 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12065 ts_RSL_IE_UplinkMeas(50, 0),
12066 ts_RSL_IE_BS_Power(0)), TRX0);
12067 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12068 ts_RSL_IE_UplinkMeas(58, 0),
12069 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012070 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012071 f_TC_chan_alloc_algo(dt, TRX3);
12072 f_perform_clear_test_ct(dt);
12073
12074 f_vty_enter_cfg_bts(BSCVTY, 2);
12075 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 90");
12076 f_vty_transceive(BSCVTY, "end");
12077
12078 f_logp(BSCVTY, "Case e) Uplink RxLev above the threshold, but C0 load is not");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012079 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012080 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12081 ts_RSL_IE_UplinkMeas(50, 0),
12082 ts_RSL_IE_BS_Power(0)), TRX0);
12083 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12084 ts_RSL_IE_UplinkMeas(58, 0),
12085 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012086 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012087 f_TC_chan_alloc_algo(dt, TRX0);
12088 f_perform_clear_test_ct(dt);
12089
12090 f_vty_enter_cfg_bts(BSCVTY, 2);
12091 f_vty_transceive(BSCVTY, "channel allocator ascending");
12092 f_vty_transceive(BSCVTY, "end");
12093
12094 /* At this point some TCH/F channels are BORKEN, but they will be
12095 * resurrected upon the A-bis/OML link re-establishment. */
12096 f_shutdown_helper();
12097}
12098
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012099private function f_vty_mgw_enable(integer mgw_nr := 1) runs on test_CT {
12100 var rof_charstring cmds := {
12101 "remote-ip " & mp_test_ip,
12102 "remote-port " & int2str(2427 + mgw_nr)
12103 };
12104 f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
12105 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " reconnect")
12106}
12107private function f_vty_mgw_disable(integer mgw_nr := 1) runs on test_CT {
12108 f_vty_config3(BSCVTY, {"network"}, { "no mgw " &int2str(mgw_nr) });
12109}
12110private function f_vty_mgw_block(integer mgw_nr := 1, boolean blocked := true) runs on test_CT {
12111 var charstring arg;
12112 if (blocked) {
12113 arg := "block";
12114 } else {
12115 arg := "unblock";
12116 }
12117 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " " & arg);
12118}
12119private const charstring COORD_CMD_ESTABLISHED := "COORD_CMD_ESTABLISHED";
12120private function f_TC_mgwpool_call_seq_1(charstring id) runs on MSC_ConnHdlr {
12121 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12122 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12123 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12124 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12125
12126 f_establish_fully(ass_cmd, exp_compl);
12127 COORD.send(COORD_CMD_ESTABLISHED);
12128
12129 COORD.receive(COORD_CMD_ESTABLISHED);
12130 f_perform_clear()
12131 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12132}
12133private function f_TC_mgwpool_call_seq_2(charstring id) runs on MSC_ConnHdlr {
12134 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12135 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12136 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12137 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12138
12139
12140 COORD.receive(COORD_CMD_ESTABLISHED);
12141 f_establish_fully(ass_cmd, exp_compl);
12142 COORD.send(COORD_CMD_ESTABLISHED);
12143
12144 f_perform_clear()
12145 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12146}
12147/* Test load is spread around 2 available MGWs */
12148testcase TC_mgwpool_all_used() runs on test_CT {
12149 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12150 var MSC_ConnHdlr vc_conn1;
12151 pars1.mgwpool_idx := 0;
12152
12153 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12154 var MSC_ConnHdlr vc_conn2;
12155 pars2.mgwpool_idx := 1;
12156
12157 f_init(1, true, nr_mgw := 2);
12158 f_sleep(1.0);
12159
12160 f_vty_mgw_enable(1);
12161
12162 vc_conn1 := f_start_handler_create(pars1);
12163 vc_conn2 := f_start_handler_create(pars2);
12164 connect(vc_conn1:COORD, vc_conn2:COORD);
12165 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12166 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12167 vc_conn1.done;
12168 vc_conn2.done;
12169
12170 f_vty_mgw_disable(1);
12171
12172 f_shutdown_helper();
12173}
12174
12175/* Test blocked MGW in the pool are not selected */
12176testcase TC_mgwpool_blocked_not_used() runs on test_CT {
12177 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12178 var MSC_ConnHdlr vc_conn1;
12179 pars1.mgwpool_idx := 0;
12180
12181 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12182 var MSC_ConnHdlr vc_conn2;
12183 pars2.mgwpool_idx := 0; /* expect it in the first one, since the second will be blocked */
12184 pars2.media_nr := 2;
12185
12186 f_init(1, true, nr_mgw := 2);
12187 f_sleep(1.0);
12188
12189 f_vty_mgw_enable(1);
12190 f_vty_mgw_block(1, true);
12191
12192 vc_conn1 := f_start_handler_create(pars1);
12193 vc_conn2 := f_start_handler_create(pars2);
12194 connect(vc_conn1:COORD, vc_conn2:COORD);
12195 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12196 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12197 vc_conn1.done;
12198 vc_conn2.done;
12199
12200 f_vty_mgw_disable(1);
12201
12202 f_shutdown_helper();
12203}
12204
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012205/* Test BTS pinning to an MGW is applied */
12206testcase TC_mgwpool_pin_bts() runs on test_CT {
12207 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12208 var MSC_ConnHdlr vc_conn1;
12209 pars1.mgwpool_idx := 0;
12210
12211 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12212 var MSC_ConnHdlr vc_conn2;
12213 pars2.mgwpool_idx := 0; /* expect it in the first one, since the BTS is pinned to the first MGW */
12214 pars2.media_nr := 2;
12215
12216 f_init(1, true, nr_mgw := 2);
12217 f_sleep(1.0);
12218
12219 f_vty_mgw_enable(1);
12220 f_vty_cfg_bts(BSCVTY, 0, { "mgw pool-target 0" });
12221
12222 vc_conn1 := f_start_handler_create(pars1);
12223 vc_conn2 := f_start_handler_create(pars2);
12224 connect(vc_conn1:COORD, vc_conn2:COORD);
12225 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12226 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12227 vc_conn1.done;
12228 vc_conn2.done;
12229
12230 f_vty_cfg_bts(BSCVTY, 0, { "no mgw pool-target" } );
Vadim Yanitskiy389d7e02022-10-25 17:44:05 +070012231 f_vty_mgw_disable(1);
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012232
12233 f_shutdown_helper();
12234}
12235
Oliver Smithc9a5f532022-10-21 11:32:23 +020012236private function f_tc_ho_meas_rep_multi_band(charstring id) runs on MSC_ConnHdlr {
12237 g_pars := f_gen_test_hdlr_pars();
12238 var PDU_BSSAP ass_req := f_gen_ass_req();
12239 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12240 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12241 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12242 f_establish_fully(ass_req, exp_compl);
12243
12244 /* Send a measurement report with bad rxlev except on 3rd entry. The
12245 * measurement report is divided into two sub lists, as described in
12246 * 3GPP TS 04.08 § 10.5.2.20. */
12247 var NcellReports neighbor_rep := {
12248 /* Sub list 1: same band */
Oliver Smitha6773042022-10-24 12:56:30 +020012249 { rxlev := 0, bcch_freq := 0, bsic := 12 }, /* ARFCN 800, band 1800, LAC 98 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012250 /* Sub list 2: different band */
Oliver Smitha6773042022-10-24 12:56:30 +020012251 { rxlev := 0, bcch_freq := 1, bsic := 13 }, /* ARFCN 200, band 850, LAC 97 */
12252 { rxlev := 40, bcch_freq := 2, bsic := 14 }, /* ARFCN 1000, band 900, LAC 99 */
12253 { rxlev := 0, bcch_freq := 3, bsic := 11 } /* ARFCN 0, band 900, LAC 96 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012254 };
12255 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
12256 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
12257 l3_mr, 0));
12258
12259 /* Expect a handover to the third entry. If the BSC parsed the report
Oliver Smitha6773042022-10-24 12:56:30 +020012260 * correctly, the third entry has LAC 99. */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012261 var template BSSMAP_FIELD_CellIdentificationList cid_list := {
Oliver Smitha6773042022-10-24 12:56:30 +020012262 cIl_LAC := { ts_BSSMAP_CI_LAC(99) }
Oliver Smithc9a5f532022-10-21 11:32:23 +020012263 };
12264 alt {
12265 [] BSSAP.receive(tr_BSSMAP_HandoverRequired(cid_list := cid_list)) {
12266 setverdict(pass);
12267 }
12268 [] BSSAP.receive(tr_BSSMAP_HandoverRequired()) {
12269 setverdict(fail, "Handover has unexpected LAC in Cell Identification List. The BSC probably"
12270 & " didn't parse the multi-band measurement report correctly.");
12271 }
12272 }
12273
12274 f_ho_out_of_this_bsc(skip_meas_rep := true);
12275}
12276testcase TC_ho_meas_rep_multi_band() runs on test_CT {
12277 /* Verify that the BSC parses the measurement report correctly when
12278 * neighbors in multiple bands are configured (OS#5717). See
12279 * gsm_arfcn2band_rc() in libosmocore src/gsm/gsm_utils.c for the
12280 * ARFCN -> band mapping. The MS is connected to band 1800. */
12281 var MSC_ConnHdlr vc_conn;
12282
12283 f_init_vty();
12284 f_bts_0_cfg(BSCVTY,
12285 {"neighbor-list mode automatic",
12286 "handover 1",
12287 "handover algorithm 2",
12288 "handover2 window rxlev averaging 1",
12289 "no neighbors",
12290 "neighbor lac 99 arfcn 1000 bsic any", /* band 900 */
12291 "neighbor lac 98 arfcn 800 bsic any", /* band 1800 */
12292 "neighbor lac 97 arfcn 200 bsic any", /* band 850 */
Oliver Smitha6773042022-10-24 12:56:30 +020012293 "neighbor lac 96 arfcn 0 bsic any"}); /* band 900 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012294 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
12295
12296 f_init(1, true);
12297 f_sleep(1.0);
12298
12299 f_ctrs_bsc_and_bts_handover_init();
12300
12301 vc_conn := f_start_handler(refers(f_tc_ho_meas_rep_multi_band));
12302 vc_conn.done;
12303
12304 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
12305 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
12306 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
12307 f_ctrs_bsc_and_bts_add(0, "handover:completed");
12308 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
12309 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
12310 f_ctrs_bsc_and_bts_verify();
12311 f_shutdown_helper(ho := true);
12312}
12313
Harald Welte28d943e2017-11-25 15:00:50 +010012314control {
Harald Welte898113b2018-01-31 18:32:21 +010012315 /* CTRL interface testing */
Harald Welte4003d112017-12-09 22:35:39 +010012316 execute( TC_ctrl_msc_connection_status() );
Stefan Sperlingb041b3d2018-01-03 17:14:55 +010012317 execute( TC_ctrl_msc0_connection_status() );
Neels Hofmeyrf65ce872021-09-23 18:40:10 +020012318 /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
12319 * these in the AoIP test suite. */
12320 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12321 execute( TC_stat_num_msc_connected_1() );
12322 execute( TC_stat_num_msc_connected_2() );
12323 execute( TC_stat_num_msc_connected_3() );
12324 }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020012325 execute( TC_stat_num_bts_connected_1() );
12326 execute( TC_stat_num_bts_connected_2() );
12327 execute( TC_stat_num_bts_connected_3() );
Harald Welte96c94412017-12-09 03:12:45 +010012328 execute( TC_ctrl() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012329 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +020012330 execute( TC_ctrl_location() );
12331 }
Harald Welte898113b2018-01-31 18:32:21 +010012332
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012333 execute( TC_si_default() );
Neels Hofmeyr66aeba42020-07-06 02:21:21 +020012334 execute( TC_si2quater_2_earfcns() );
12335 execute( TC_si2quater_3_earfcns() );
12336 execute( TC_si2quater_4_earfcns() );
12337 execute( TC_si2quater_5_earfcns() );
12338 execute( TC_si2quater_6_earfcns() );
Neels Hofmeyrad132f22020-07-08 02:20:16 +020012339 execute( TC_si2quater_12_earfcns() );
12340 execute( TC_si2quater_23_earfcns() );
12341 execute( TC_si2quater_32_earfcns() );
12342 execute( TC_si2quater_33_earfcns() );
12343 execute( TC_si2quater_42_earfcns() );
12344 execute( TC_si2quater_48_earfcns() );
12345 execute( TC_si2quater_49_earfcns() );
Pau Espin Pedrol85a84432020-07-20 18:45:03 +020012346 execute( TC_si_acc_rotate() );
Alexander Couzens4ad3a352020-09-10 22:29:12 +020012347 execute( TC_si_acc_ramp_rotate() );
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012348
Harald Welte898113b2018-01-31 18:32:21 +010012349 /* RSL DCHAN Channel ACtivation / Deactivation */
Harald Welteae026692017-12-09 01:03:01 +010012350 execute( TC_chan_act_noreply() );
Harald Welte4003d112017-12-09 22:35:39 +010012351 execute( TC_chan_act_counter() );
Harald Welteae026692017-12-09 01:03:01 +010012352 execute( TC_chan_act_ack_noest() );
Philipp Maier9c60a622020-07-09 15:08:46 +020012353 execute( TC_chan_act_ack_noest_emerg() );
Philipp Maier606f07d2020-08-12 17:21:58 +020012354 execute( TC_chan_rqd_emerg_deny() );
Harald Welteae026692017-12-09 01:03:01 +010012355 execute( TC_chan_act_ack_est_ind_noreply() );
12356 execute( TC_chan_act_ack_est_ind_refused() );
Harald Welte618ef642017-12-14 14:58:20 +010012357 execute( TC_chan_act_nack() );
Harald Welte799c97b2017-12-14 17:50:30 +010012358 execute( TC_chan_exhaustion() );
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +070012359 execute( TC_chan_deact_silence() );
Harald Welte4003d112017-12-09 22:35:39 +010012360 execute( TC_chan_rel_rll_rel_ind() );
12361 execute( TC_chan_rel_conn_fail() );
12362 execute( TC_chan_rel_hard_clear() );
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +020012363 execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
12364 execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
Harald Welte99787102019-02-04 10:41:36 +010012365 execute( TC_chan_rel_hard_clear_csfb() );
Harald Welted8c36cd2017-12-09 23:05:31 +010012366 execute( TC_chan_rel_hard_rlsd() );
Harald Welte550daf92018-06-11 19:22:13 +020012367 execute( TC_chan_rel_hard_rlsd_ms_dead() );
Harald Welte85804d42017-12-10 14:11:58 +010012368 execute( TC_chan_rel_a_reset() );
Pau Espin Pedrolc675b612020-01-09 19:55:40 +010012369 execute( TC_chan_rel_sccp_tiar_timeout() );
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +020012370 execute( TC_chan_rel_rr_cause() );
Harald Welte6f521d82017-12-11 19:52:02 +010012371
Harald Weltecfe2c962017-12-15 12:09:32 +010012372 execute( TC_outbound_connect() );
Harald Welte898113b2018-01-31 18:32:21 +010012373
12374 /* Assignment related */
Harald Welte16a4adf2017-12-14 18:54:01 +010012375 execute( TC_assignment_cic_only() );
Harald Welte235ebf12017-12-15 14:18:16 +010012376 execute( TC_assignment_csd() );
12377 execute( TC_assignment_ctm() );
12378 execute( TC_assignment_sign() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012379 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12380 execute( TC_assignment_aoip_tla_v6() );
12381 }
Harald Welte235ebf12017-12-15 14:18:16 +010012382 execute( TC_assignment_fr_a5_0() );
12383 execute( TC_assignment_fr_a5_1() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012384 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte8f67d1d2018-05-25 20:38:42 +020012385 execute( TC_assignment_fr_a5_1_codec_missing() );
12386 }
Harald Welte235ebf12017-12-15 14:18:16 +010012387 execute( TC_assignment_fr_a5_3() );
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +020012388 execute( TC_assignment_fr_a5_4() );
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +020012389 execute( TC_assignment_fr_a5_4_fail() );
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +020012390 execute( TC_assignment_fr_a5_not_sup() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012391 execute( TC_ciph_mode_a5_0() );
12392 execute( TC_ciph_mode_a5_1() );
Oliver Smith50b98122021-07-09 15:00:28 +020012393 execute( TC_ciph_mode_a5_2_0() );
Oliver Smith1dff88d2021-07-09 08:45:51 +020012394 execute( TC_ciph_mode_a5_2_1() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012395 execute( TC_ciph_mode_a5_3() );
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +020012396 execute( TC_ciph_mode_a5_4() );
Harald Welte16a4adf2017-12-14 18:54:01 +010012397
Harald Welte60aa5762018-03-21 19:33:13 +010012398 execute( TC_assignment_codec_fr() );
Neels Hofmeyr559d5d02021-04-16 16:50:49 +020012399 execute( TC_assignment_codec_fr_by_mode_modify() );
Harald Welte60aa5762018-03-21 19:33:13 +010012400 execute( TC_assignment_codec_hr() );
12401 execute( TC_assignment_codec_efr() );
12402 execute( TC_assignment_codec_amr_f() );
12403 execute( TC_assignment_codec_amr_h() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012404
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012405 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier8a581d22019-03-26 18:32:48 +010012406 execute( TC_assignment_codec_amr_f_S1() );
12407 execute( TC_assignment_codec_amr_h_S1() );
12408 execute( TC_assignment_codec_amr_f_S124() );
12409 execute( TC_assignment_codec_amr_h_S124() );
12410 execute( TC_assignment_codec_amr_f_S0() );
12411 execute( TC_assignment_codec_amr_f_S02() );
12412 execute( TC_assignment_codec_amr_f_S024() );
12413 execute( TC_assignment_codec_amr_f_S0247() );
12414 execute( TC_assignment_codec_amr_h_S0() );
12415 execute( TC_assignment_codec_amr_h_S02() );
12416 execute( TC_assignment_codec_amr_h_S024() );
12417 execute( TC_assignment_codec_amr_h_S0247() );
12418 execute( TC_assignment_codec_amr_f_S01234567() );
12419 execute( TC_assignment_codec_amr_f_S0234567() );
12420 execute( TC_assignment_codec_amr_f_zero() );
12421 execute( TC_assignment_codec_amr_f_unsupp() );
12422 execute( TC_assignment_codec_amr_h_S7() );
Neels Hofmeyr21863562020-11-26 00:34:33 +000012423 execute( TC_assignment_codec_amr_f_start_mode_auto() );
12424 execute( TC_assignment_codec_amr_h_start_mode_auto() );
Neels Hofmeyr3eb94562020-11-26 02:40:26 +000012425 execute( TC_assignment_codec_amr_f_start_mode_4() );
12426 execute( TC_assignment_codec_amr_h_start_mode_4() );
Neels Hofmeyr454d7922020-11-26 02:24:57 +000012427 execute( TC_assignment_codec_amr_startmode_cruft() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012428 }
Harald Welte60aa5762018-03-21 19:33:13 +010012429
Philipp Maierac09bfc2019-01-08 13:41:39 +010012430 execute( TC_assignment_codec_fr_exhausted_req_hr() );
12431 execute( TC_assignment_codec_fr_exhausted_req_fr() );
12432 execute( TC_assignment_codec_fr_exhausted_req_fr_hr() );
12433 execute( TC_assignment_codec_fr_exhausted_req_hr_fr() );
12434 execute( TC_assignment_codec_hr_exhausted_req_fr() );
12435 execute( TC_assignment_codec_hr_exhausted_req_hr() );
12436 execute( TC_assignment_codec_hr_exhausted_req_hr_fr() );
12437 execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
12438 execute( TC_assignment_codec_req_hr_fr() );
12439 execute( TC_assignment_codec_req_fr_hr() );
Pau Espin Pedrol14475352021-07-22 15:48:16 +020012440 execute( TC_assignment_sdcch_exhausted_req_signalling() );
12441 execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
12442 execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
Philipp Maierac09bfc2019-01-08 13:41:39 +010012443
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +020012444 execute( TC_assignment_codec_hr_osmux_on() );
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +020012445 execute( TC_assignment_osmux() );
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020012446 execute( TC_assignment_osmux_cn() );
12447 execute( TC_assignment_osmux_bts() );
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +020012448
Harald Welte898113b2018-01-31 18:32:21 +010012449 /* RLL Establish Indication on inactive DCHAN / SAPI */
Harald Welte5cd20ed2017-12-13 21:03:20 +010012450 execute( TC_rll_est_ind_inact_lchan() );
12451 execute( TC_rll_est_ind_inval_sapi1() );
12452 execute( TC_rll_est_ind_inval_sapi3() );
12453 execute( TC_rll_est_ind_inval_sacch() );
12454
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +070012455 /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
12456 execute( TC_tch_dlci_link_id_sapi() );
12457
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012458 /* SAPI N Reject triggered by RLL establishment failures */
12459 execute( TC_rll_rel_ind_sapi_n_reject() );
12460 execute( TC_rll_err_ind_sapi_n_reject() );
12461 execute( TC_rll_timeout_sapi_n_reject() );
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +070012462 execute( TC_rll_sapi_n_reject_dlci_cc() );
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012463
Harald Welte898113b2018-01-31 18:32:21 +010012464 /* Paging related tests */
Harald Welte6f521d82017-12-11 19:52:02 +010012465 execute( TC_paging_imsi_nochan() );
12466 execute( TC_paging_tmsi_nochan() );
12467 execute( TC_paging_tmsi_any() );
12468 execute( TC_paging_tmsi_sdcch() );
12469 execute( TC_paging_tmsi_tch_f() );
12470 execute( TC_paging_tmsi_tch_hf() );
12471 execute( TC_paging_imsi_nochan_cgi() );
12472 execute( TC_paging_imsi_nochan_lac_ci() );
12473 execute( TC_paging_imsi_nochan_ci() );
12474 execute( TC_paging_imsi_nochan_lai() );
12475 execute( TC_paging_imsi_nochan_lac() );
12476 execute( TC_paging_imsi_nochan_all() );
Harald Welte751d3eb2018-01-31 15:51:06 +010012477 execute( TC_paging_imsi_nochan_plmn_lac_rnc() );
12478 execute( TC_paging_imsi_nochan_rnc() );
12479 execute( TC_paging_imsi_nochan_lac_rnc() );
12480 execute( TC_paging_imsi_nochan_lacs() );
12481 execute( TC_paging_imsi_nochan_lacs_empty() );
Stefan Sperling049a86e2018-03-20 15:51:00 +010012482 execute( TC_paging_imsi_nochan_cgi_unknown_cid() );
Harald Welte10985002017-12-12 09:29:15 +010012483 execute( TC_paging_imsi_a_reset() );
Harald Weltee65d40e2017-12-13 00:09:06 +010012484 execute( TC_paging_imsi_load() );
Philipp Maier779a7922018-02-16 11:00:37 +010012485 execute( TC_paging_counter() );
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +010012486 execute( TC_paging_resp_unsol() );
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +020012487 execute( TC_paging_500req() );
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +020012488 execute( TC_paging_450req_no_paging_load_ind() );
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +010012489 execute( TC_paging_imsi_nochan_ci_resp_invalid_mi() );
Harald Welte4e9b9cc2017-12-14 18:31:02 +010012490
12491 execute( TC_rsl_drop_counter() );
Stefan Sperling830dc9d2018-02-12 21:08:28 +010012492 execute( TC_rsl_unknown_unit_id() );
12493
12494 execute( TC_oml_unknown_unit_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012495
12496 execute( TC_classmark() );
Harald Welteeddf0e92020-06-21 19:42:15 +020012497 execute( TC_common_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012498 execute( TC_unsol_ass_fail() );
Harald Welteea99a002018-01-31 20:46:43 +010012499 execute( TC_unsol_ass_compl() );
Harald Weltefbf9b5e2018-01-31 20:41:23 +010012500 execute( TC_unsol_ho_fail() );
Harald Weltee3bd6582018-01-31 22:51:25 +010012501 execute( TC_err_82_short_msg() );
Harald Weltee9e02e42018-01-31 23:36:25 +010012502 execute( TC_err_84_unknown_msg() );
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012503
Harald Welte261af4b2018-02-12 21:20:39 +010012504 execute( TC_ho_int() );
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +020012505 execute( TC_ho_int_a5_0() );
12506 execute( TC_ho_int_a5_1() );
12507 execute( TC_ho_int_a5_3() );
12508 execute( TC_ho_int_a5_4() );
Neels Hofmeyr5f144212020-11-03 15:41:58 +000012509 execute( TC_ho_int_radio_link_failure() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012510
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012511 /* TC_ho_out_of_this_bsc is run last, see comment below */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +020012512 execute( TC_ho_out_fail_no_msc_response() );
12513 execute( TC_ho_out_fail_rr_ho_failure() );
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +020012514 execute( TC_ho_out_fail_no_result_after_ho_cmd() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012515
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012516 execute( TC_ho_into_this_bsc() );
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +020012517 execute( TC_ho_into_this_bsc_a5_0() );
12518 execute( TC_ho_into_this_bsc_a5_1() );
12519 execute( TC_ho_into_this_bsc_a5_3() );
12520 execute( TC_ho_into_this_bsc_a5_4() );
Neels Hofmeyr93182e02022-02-17 21:59:07 +010012521 execute( TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() );
12522 execute( TC_ho_into_this_bsc_a5_1_3() );
Neels Hofmeyr907b23b2022-02-17 21:58:47 +010012523 execute( TC_ho_into_this_bsc_a5_mismatch() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012524 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12525 execute( TC_ho_into_this_bsc_tla_v6() );
12526 }
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +020012527 execute( TC_srvcc_eutran_to_geran() );
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +030012528 execute( TC_srvcc_eutran_to_geran_a5_3() );
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +010012529 execute( TC_srvcc_eutran_to_geran_src_sai() );
Pau Espin Pedrol35801c32021-04-19 13:03:20 +020012530 execute( TC_srvcc_eutran_to_geran_ho_out() );
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +020012531 execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
12532 execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012533 execute( TC_ho_in_fail_msc_clears() );
12534 execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
12535 execute( TC_ho_in_fail_no_detect() );
12536 execute( TC_ho_in_fail_no_detect2() );
Oliver Smith7a8594a2023-02-13 14:30:49 +010012537 execute( TC_ho_in_fail_mgw_mdcx_timeout() );
Oliver Smith4eed06f2023-02-15 15:43:19 +010012538 execute( TC_ho_in_fail_ipa_crcx_timeout() );
Neels Hofmeyra23f3b12022-03-02 19:57:12 +010012539 execute( TC_ho_into_this_bsc_sccp_cr_without_bssap() );
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012540
Neels Hofmeyr91401012019-07-11 00:42:35 +020012541 execute( TC_ho_neighbor_config_1() );
12542 execute( TC_ho_neighbor_config_2() );
12543 execute( TC_ho_neighbor_config_3() );
12544 execute( TC_ho_neighbor_config_4() );
12545 execute( TC_ho_neighbor_config_5() );
12546 execute( TC_ho_neighbor_config_6() );
12547 execute( TC_ho_neighbor_config_7() );
12548
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012549 execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() );
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010012550 execute( TC_bssmap_clear_does_not_cause_bssmap_reset() );
Neels Hofmeyrfd445c32018-03-09 15:39:31 +010012551 execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() );
Harald Welte94e0c342018-04-07 11:33:23 +020012552
12553 execute( TC_dyn_pdch_ipa_act_deact() );
12554 execute( TC_dyn_pdch_ipa_act_nack() );
12555 execute( TC_dyn_pdch_osmo_act_deact() );
12556 execute( TC_dyn_pdch_osmo_act_nack() );
Pau Espin Pedrol37a4c152021-11-16 19:02:23 +010012557 execute( TC_dyn_ts_sdcch8_act_deact() );
12558 execute( TC_dyn_ts_sdcch8_all_subslots_used() );
12559 execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
12560 execute( TC_dyn_ts_sdcch8_act_nack() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012561
Stefan Sperling0796a822018-10-05 13:01:39 +020012562 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +020012563 execute( TC_chopped_ipa_payload() );
Stefan Sperling0796a822018-10-05 13:01:39 +020012564
Pau Espin Pedrol8f773632019-11-05 11:46:53 +010012565 /* Power control related */
12566 execute( TC_assignment_verify_ms_power_params_ie() );
Vadim Yanitskiy4b233042021-06-30 00:58:43 +020012567 execute( TC_c0_power_red_mode() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012568
12569 /* MSC pooling */
12570 /* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
12571 * RESET->RESET-ACK is unconditionally negotiated for all configured MSCs, they always all appear as connected
12572 * to osmo-bsc. The MSC pooling tests however require disconnecting selected MSCs, and hence don't work out as
12573 * intended on SCCPlite. So for now, run these only for SCCP/M3UA. */
12574 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12575 execute( TC_mscpool_L3Compl_on_1_msc() );
12576 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
12577 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
12578 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
12579 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
12580 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
12581 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
12582 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
12583 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
12584 execute( TC_mscpool_paging_and_response_imsi() );
12585 execute( TC_mscpool_paging_and_response_tmsi() );
12586 execute( TC_mscpool_no_allow_attach_round_robin() );
12587 execute( TC_mscpool_no_allow_attach_valid_nri() );
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +020012588
12589 execute( TC_mscpool_sccp_n_pcstate_detaches_msc() );
Neels Hofmeyr38632aa2023-04-05 03:50:51 +020012590 execute( TC_mscpool_sccp_n_pcstate_attaches_msc() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012591 }
12592
Harald Welte99f3ca02018-06-14 13:40:29 +020012593 execute( TC_early_conn_fail() );
12594 execute( TC_late_conn_fail() );
Oliver Smithaf03bef2021-08-24 15:34:51 +020012595 execute( TC_stats_conn_fail() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012596
Philipp Maier783681c2020-07-16 16:47:06 +020012597 /* Emergency call handling (deny / allow) */
12598 execute( TC_assignment_emerg_setup_allow() );
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +010012599 execute( TC_assignment_emerg_setup_allow_imei() );
Philipp Maier783681c2020-07-16 16:47:06 +020012600 execute( TC_assignment_emerg_setup_deny_msc() );
12601 execute( TC_assignment_emerg_setup_deny_bts() );
Philipp Maier82812002020-08-13 18:48:27 +020012602 execute( TC_emerg_premption() );
12603
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +070012604 /* Frequency hopping parameters handling */
12605 execute( TC_fh_params_chan_activ() );
12606 execute( TC_fh_params_imm_ass() );
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070012607 execute( TC_fh_params_assignment_cmd() );
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070012608 execute( TC_fh_params_handover_cmd() );
Vadim Yanitskiyca974032020-09-01 07:20:39 +070012609 execute( TC_fh_params_si4_cbch() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012610
12611 if (mp_enable_lcs_tests) {
12612 execute( TC_lcs_loc_req_for_active_ms() );
12613 execute( TC_lcs_loc_req_for_active_ms_ta_req() );
12614 execute( TC_lcs_loc_req_for_idle_ms() );
12615 execute( TC_lcs_loc_req_no_subscriber() );
12616 execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
12617 execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
12618 execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
12619 execute( TC_cm_service_during_lcs_loc_req() );
12620 execute( TC_ho_during_lcs_loc_req() );
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020012621 execute( TC_emerg_call_and_lcs_loc_req() );
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020012622 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() );
12623 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012624 }
Neels Hofmeyrbf037052020-10-28 22:52:02 +000012625
12626 execute( TC_no_msc() );
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000012627
12628 execute( TC_refuse_chan_act_to_vamos() );
12629 execute( TC_refuse_mode_modif_to_vamos() );
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000012630
12631 execute( TC_reassignment_fr() );
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020012632
12633 execute( TC_cm_reestablishment() );
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020012634
12635 execute( TC_imm_ass_post_chan_ack() );
12636 execute( TC_imm_ass_pre_chan_ack() );
Neels Hofmeyr23158742021-09-07 19:08:07 +020012637 execute( TC_imm_ass_pre_ts_ack() );
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020012638 execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020012639 execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020012640
12641 execute( TC_ctrl_trx_rf_locked() );
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012642
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012643 execute( TC_ratectr_all_available_allocated() );
12644 execute( TC_ratectr_all_available_allocated_dyn() );
12645
Neels Hofmeyrb7581872021-11-07 14:02:49 +010012646 execute( TC_cm_serv_rej() );
12647
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012648 execute( TC_lost_sdcch_during_assignment() );
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012649
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012650 /* Channel allocator */
12651 execute( TC_chan_alloc_algo_ascending() );
12652 execute( TC_chan_alloc_algo_descending() );
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012653 execute( TC_chan_alloc_algo_ass_dynamic() );
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012654
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012655 /* MGW pool */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +010012656 execute( TC_mgwpool_all_used() );
12657 execute( TC_mgwpool_blocked_not_used() );
12658 execute( TC_mgwpool_pin_bts() );
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012659
Oliver Smithc9a5f532022-10-21 11:32:23 +020012660 execute( TC_ho_meas_rep_multi_band() );
12661
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012662 /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
12663 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
12664 execute( TC_ho_out_of_this_bsc() );
Harald Welte28d943e2017-11-25 15:00:50 +010012665}
12666
12667}