blob: 3861f34a02b57e3837c1b6e2e62280060ca896d9 [file] [log] [blame]
Harald Welte28d943e2017-11-25 15:00:50 +01001module BSC_Tests {
2
Harald Welte21b46bd2017-12-17 19:46:32 +01003/* Integration Tests for OsmoBSC
Harald Weltea0630032018-03-20 21:09:55 +01004 * (C) 2017-2018 by Harald Welte <laforge@gnumonks.org>
Harald Welte21b46bd2017-12-17 19:46:32 +01005 * All rights reserved.
6 *
7 * Released under the terms of GNU General Public License, Version 2 or
8 * (at your option) any later version.
9 *
Harald Welte34b5a952019-05-27 11:54:11 +020010 * SPDX-License-Identifier: GPL-2.0-or-later
11 *
Harald Welte21b46bd2017-12-17 19:46:32 +010012 * This test suite tests OsmoBSC while emulating both multiple BTS + MS as
13 * well as the MSC. See README for more details.
14 *
15 * There are test cases that run in so-called 'handler mode' and test cases
16 * that run directly on top of the BSSAP and RSL CodecPorts. The "handler mode"
17 * tests abstract the multiplexing/demultiplexing of multiple SCCP connections
18 * and/or RSL channels and are hence suitable for higher-level test cases, while
19 * the "raw" tests directly on top of the CodecPorts are more suitable for lower-
20 * level testing.
21 */
22
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +020023friend module BSC_Tests_VAMOS;
Vadim Yanitskiy5eb06a32022-06-23 18:39:46 +070024friend module BSC_Tests_CBSP;
Vadim Yanitskiy3cc065b2023-01-06 21:35:12 +070025friend module BSC_Tests_LCLS;
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +020026
Neels Hofmeyr4f118412020-06-04 15:25:10 +020027import from Misc_Helpers all;
Harald Welte4003d112017-12-09 22:35:39 +010028import from General_Types all;
Harald Welte28d943e2017-11-25 15:00:50 +010029import from Osmocom_Types all;
Harald Welteae026692017-12-09 01:03:01 +010030import from GSM_Types all;
Harald Welte28d943e2017-11-25 15:00:50 +010031import from IPL4asp_Types all;
32
Harald Welte6f521d82017-12-11 19:52:02 +010033import from BSSAP_Types all;
Harald Welte6811d102019-04-14 22:23:14 +020034import from RAN_Adapter all;
Harald Welte47cd0e32020-08-21 12:39:11 +020035import from BSSAP_LE_Adapter all;
36import from BSSAP_LE_CodecPort all;
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020037import from BSSAP_LE_Types all;
38import from BSSLAP_Types all;
Harald Welteae026692017-12-09 01:03:01 +010039import from BSSAP_CodecPort all;
40import from BSSMAP_Templates all;
Harald Welte28d943e2017-11-25 15:00:50 +010041import from IPA_Emulation all;
Stefan Sperling830dc9d2018-02-12 21:08:28 +010042import from IPA_CodecPort all;
Harald Welteae026692017-12-09 01:03:01 +010043import from IPA_Types all;
Stefan Sperling0796a822018-10-05 13:01:39 +020044import from IPA_Testing all;
Harald Welteae026692017-12-09 01:03:01 +010045import from RSL_Types all;
Harald Welte624f9632017-12-16 19:26:04 +010046import from RSL_Emulation all;
Daniel Willmann191e0d92018-01-17 12:44:35 +010047import from MGCP_Emulation all;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010048import from MGCP_Templates all;
49import from MGCP_Types all;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +020050import from MGCP_CodecPort all;
Harald Welte28d943e2017-11-25 15:00:50 +010051
Harald Welte96c94412017-12-09 03:12:45 +010052import from Osmocom_CTRL_Functions all;
Harald Weltea5d2ab22017-12-09 14:21:42 +010053import from Osmocom_CTRL_Types all;
Harald Welteffe55fc2018-01-17 22:39:54 +010054import from Osmocom_CTRL_Adapter all;
Harald Welte96c94412017-12-09 03:12:45 +010055
Daniel Willmannebdecc02020-08-12 15:30:17 +020056import from StatsD_Types all;
57import from StatsD_CodecPort all;
58import from StatsD_CodecPort_CtrlFunct all;
59import from StatsD_Checker all;
60
Harald Weltebc03c762018-02-12 18:09:38 +010061import from Osmocom_VTY_Functions all;
62import from TELNETasp_PortType all;
63
Harald Welte6f521d82017-12-11 19:52:02 +010064import from MobileL3_CommonIE_Types all;
Harald Weltee3bd6582018-01-31 22:51:25 +010065import from MobileL3_Types all;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010066import from MobileL3_RRM_Types all;
Harald Welte6f521d82017-12-11 19:52:02 +010067import from L3_Templates all;
68import from GSM_RR_Types all;
69
Stefan Sperlingc307e682018-06-14 15:15:46 +020070import from SCCP_Templates all;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010071import from BSSMAP_Templates all;
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020072import from BSSMAP_LE_Templates all;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010073
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010074import from SCCPasp_Types all;
75
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020076import from GSM_SystemInformation all;
77import from GSM_RestOctets all;
Neels Hofmeyrad132f22020-07-08 02:20:16 +020078import from TCCConversion_Functions all;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020079
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060080const integer NUM_TRX := 4;
Harald Welte5d1a2202017-12-13 19:51:29 +010081const integer NUM_BTS := 3;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020082const integer NUM_BTS_CFG := 4; /* we have 4 BTS in the osmo-bsc.cfg (for inter-BSC HO tests) but use only 3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060083const integer NUM_TRX_CFG := 1; /* we support up to 4 TRX per BTS, but have only 1 TRX per BTS in osmo-bsc.cfg */
Neels Hofmeyrf246a922020-05-13 02:27:10 +020084const integer NUM_MSC := 3;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020085const integer NUM_MGW := 2;
Harald Welteae026692017-12-09 01:03:01 +010086const float T3101_MAX := 12.0;
Harald Welte28d943e2017-11-25 15:00:50 +010087
Harald Welte799c97b2017-12-14 17:50:30 +010088/* make sure to sync this with the osmo-bts.cfg you're using */
Philipp Maiercb6cc482018-03-26 13:08:00 +020089const integer NUM_TCHH_PER_BTS := 2;
90const integer NUM_TCHF_PER_BTS := 4;
Neels Hofmeyr74083c22020-07-29 00:43:01 +020091const integer NUM_SDCCH_PER_BTS := 3;
Harald Welte799c97b2017-12-14 17:50:30 +010092
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060093friend type record BtsTrxIdx {
94 uint8_t bts,
95 uint8_t trx
96}
97
98private type record BtsParams {
99 integer trx_num,
100 integer tsc
101}
102
Neels Hofmeyrbf720202021-10-02 12:58:24 +0200103/* Default Training Sequence Code expected for bts[i]:
104 * BTS 0 has BSIC 10 (and no explicit timeslot training_sequence_code config), so expecting TSC = (BSIC & 7) = 2.
105 * BTS 1 has BSIC 11, TSC = (BSIC & 7) = 3.
106 * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
107 * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
108 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600109private const BtsParams c_BtsParams[NUM_BTS_CFG] := {
110 /* BTS0 */ { trx_num := 1, tsc := 2 },
111 /* BTS1 */ { trx_num := 1, tsc := 3 },
Vadim Yanitskiy7a3d2932022-05-29 20:37:46 +0600112 /* BTS2 */ { trx_num := 4, tsc := 4 },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600113 /* BTS3 */ { trx_num := 1, tsc := 4 }
Neels Hofmeyrbf720202021-10-02 12:58:24 +0200114}
Harald Welte4003d112017-12-09 22:35:39 +0100115
Vadim Yanitskiy59494702022-09-14 15:29:04 +0700116private const RSL_IE_Body c_mr_conf_5_90 :=
Pau Espin Pedrolf7634dc2022-09-02 17:56:00 +0200117 valueof(RSL_IE_Body:{multirate_cfg := ts_RSL_MultirateCfg(true, 0, '00000100'B /* 5,90k */)});
118
Harald Welte21b46bd2017-12-17 19:46:32 +0100119/* per-BTS state which we keep */
Harald Welte96c94412017-12-09 03:12:45 +0100120type record BTS_State {
Harald Welte21b46bd2017-12-17 19:46:32 +0100121 /* component reference to the IPA_Client component used for RSL */
Harald Weltea5d2ab22017-12-09 14:21:42 +0100122 IPA_Client rsl
Harald Welte96c94412017-12-09 03:12:45 +0100123}
124
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200125/* Default list of counters for an 'msc' entity. */
126const CounterNameVals counternames_msc_mscpool := {
127 { "mscpool:subscr:new", 0 },
128 { "mscpool:subscr:known", 0 },
129 { "mscpool:subscr:reattach", 0 },
130 { "mscpool:subscr:attach_lost", 0 },
131 { "mscpool:subscr:paged", 0 }
132};
133
Neels Hofmeyrbf037052020-10-28 22:52:02 +0000134/* List of global mscpool counters, not related to a specific 'msc' entity. */
135const CounterNameVals counternames_bsc_mscpool := {
136 { "mscpool:subscr:no_msc", 0 }
137};
138
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000139/* Default list of counters for 'bsc' and 'bts' entities. */
140const CounterNameVals counternames_bsc_bts_handover := {
141 { "assignment:attempted", 0 },
142 { "assignment:completed", 0 },
143 { "assignment:stopped", 0 },
144 { "assignment:no_channel", 0 },
145 { "assignment:timeout", 0 },
146 { "assignment:failed", 0 },
147 { "assignment:error", 0 },
148
149 { "handover:attempted", 0 },
150 { "handover:completed", 0 },
151 { "handover:stopped", 0 },
152 { "handover:no_channel", 0 },
153 { "handover:timeout", 0 },
154 { "handover:failed", 0 },
155 { "handover:error", 0 },
156
157 { "intra_cell_ho:attempted", 0 },
158 { "intra_cell_ho:completed", 0 },
159 { "intra_cell_ho:stopped", 0 },
160 { "intra_cell_ho:no_channel", 0 },
161 { "intra_cell_ho:timeout", 0 },
162 { "intra_cell_ho:failed", 0 },
163 { "intra_cell_ho:error", 0 },
164
165 { "intra_bsc_ho:attempted", 0 },
166 { "intra_bsc_ho:completed", 0 },
167 { "intra_bsc_ho:stopped", 0 },
168 { "intra_bsc_ho:no_channel", 0 },
169 { "intra_bsc_ho:timeout", 0 },
170 { "intra_bsc_ho:failed", 0 },
171 { "intra_bsc_ho:error", 0 },
172
173 { "interbsc_ho_out:attempted", 0 },
174 { "interbsc_ho_out:completed", 0 },
175 { "interbsc_ho_out:stopped", 0 },
176 { "interbsc_ho_out:timeout", 0 },
177 { "interbsc_ho_out:failed", 0 },
178 { "interbsc_ho_out:error", 0 },
179
180 { "interbsc_ho_in:attempted", 0 },
181 { "interbsc_ho_in:completed", 0 },
182 { "interbsc_ho_in:stopped", 0 },
183 { "interbsc_ho_in:no_channel", 0 },
184 { "interbsc_ho_in:timeout", 0 },
185 { "interbsc_ho_in:failed", 0 },
186 { "interbsc_ho_in:error", 0 }
187};
188
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100189const CounterNameVals counternames_bts_handover := {
190 { "incoming_intra_bsc_ho:attempted", 0 },
191 { "incoming_intra_bsc_ho:completed", 0 },
192 { "incoming_intra_bsc_ho:stopped", 0 },
193 { "incoming_intra_bsc_ho:no_channel", 0 },
194 { "incoming_intra_bsc_ho:timeout", 0 },
195 { "incoming_intra_bsc_ho:failed", 0 },
196 { "incoming_intra_bsc_ho:error", 0 }
197};
198
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200199/* Set of all System Information received during one RSL port's startup.
200 * Note that some System Information may be sent on RSL, but lacking actual SI data, to indicate that the BTS should not
201 * broadcast that SI type. That will be reflected as 'omit' here.
202 */
203type record SystemInformationConfig {
204 SystemInformationType1 si1 optional,
205 SystemInformationType2 si2 optional,
206 SystemInformationType2bis si2bis optional,
207 SystemInformationType2ter si2ter optional,
Neels Hofmeyrad132f22020-07-08 02:20:16 +0200208 SI2quaterRestOctetsList si2quater optional,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200209 SystemInformationType3 si3 optional,
210 SystemInformationType4 si4 optional,
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100211 SystemInformationType13 si13 optional,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200212 SystemInformationType5 si5 optional,
213 SystemInformationType5bis si5bis optional,
214 SystemInformationType5ter si5ter optional,
215 SystemInformationType6 si6 optional
216};
217
218const SystemInformationConfig SystemInformationConfig_omit := {
219 si1 := omit,
220 si2 := omit,
221 si2bis := omit,
222 si2ter := omit,
223 si2quater := omit,
224 si3 := omit,
225 si4 := omit,
226 si13 := omit,
227 si5 := omit,
228 si5bis := omit,
229 si5ter := omit,
230 si6 := omit
231};
232
233/* tr_EUTRAN_CellDesc with defaults used in BSC_Tests.ttcn */
234template EUTRAN_CellDesc tr_EUTRAN_CellDesc_default(template (present) uint16_t e_arfcn := ?,
235 template uint3_t meas_bw := 3)
236:= tr_EUTRAN_CellDesc(e_arfcn := e_arfcn,
237 meas_bw_presence := '1'B,
238 meas_bw := meas_bw);
239
240/* tr_EUTRAN_NeighbourCells with defaults used in BSC_Tests.ttcn */
Harald Welte65e419a2020-08-21 12:38:33 +0200241template EUTRAN_NeighbourCells tr_EUTRAN_NeighbourCells_default(template (present) EUTRAN_CellDescs cell_desc_list := { tr_EUTRAN_CellDesc_default },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200242 template uint3_t prio := 3,
243 template (present) uint5_t thresh_high := 20,
244 template uint5_t thresh_low := 10,
245 template uint5_t qrxlevmin := 22)
246:= tr_EUTRAN_NeighbourCells(
247 cell_desc_list := cell_desc_list,
248 prio_presence := '1'B,
249 prio := prio,
250 thresh_high := thresh_high,
251 thresh_low_presence := '1'B,
252 thresh_low := thresh_low,
253 qrxlevmin_presence := '1'B,
254 qrxlevmin := qrxlevmin);
255
256template SystemInformationConfig SystemInformationConfig_default := {
257 si1 := {
258 cell_chan_desc := '8FB38000000000000000000000000000'O,
259 rach_control := {
260 max_retrans := RACH_MAX_RETRANS_7,
261 tx_integer := '1001'B,
262 cell_barr_access := false,
263 re_not_allowed := true,
264 acc := '0000010000000000'B
265 },
266 rest_octets := ?
267 },
268 si2 := {
269 bcch_freq_list := '00000000000000000000000000000000'O,
270 ncc_permitted := '11111111'B,
271 rach_control := {
272 max_retrans := RACH_MAX_RETRANS_7,
273 tx_integer := '1001'B,
274 cell_barr_access := false,
275 re_not_allowed := true,
276 acc := '0000010000000000'B
277 }
278 },
279 si2bis := omit,
280 si2ter := {
281 extd_bcch_freq_list := '8E320000000000000000000000000800'O,
282 rest_octets := ?
283 },
284 si2quater := {
285 tr_SI2quaterRestOctets_EUTRAN( repeated_neigh_cells := { tr_EUTRAN_NeighbourCells_default } )
286 },
287 si3 := {
288 cell_id := 0,
289 lai := {
290 mcc_mnc := '001F01'H,
291 lac := 1
292 },
293 ctrl_chan_desc := {
294 msc_r99 := true,
295 att := true,
296 bs_ag_blks_res := 1,
297 ccch_conf := CCHAN_DESC_1CCCH_COMBINED,
298 si22ind := false,
299 cbq3 := CBQ3_IU_MODE_NOT_SUPPORTED,
300 spare := '00'B,
301 bs_pa_mfrms := 3,
302 t3212 := 30
303 },
304 cell_options := {
305 dn_ind := false,
306 pwrc := false,
307 dtx := MS_SHALL_USE_UL_DTX,
308 radio_link_tout_div4 := 7
309 },
310 cell_sel_par := {
311 cell_resel_hyst_2dB := 2,
312 ms_txpwr_max_cch := 7,
313 acs := '0'B,
314 neci := true,
315 rxlev_access_min := 0
316 },
317 rach_control := {
318 max_retrans := RACH_MAX_RETRANS_7,
319 tx_integer := '1001'B,
320 cell_barr_access := false,
321 re_not_allowed := true,
322 acc := '0000010000000000'B
323 },
324 rest_octets := {
325 sel_params := {
326 presence := '0'B,
327 params := omit
328 },
329 pwr_offset := {
330 presence := '0'B,
331 offset := omit
332 },
333 si_2ter_ind := '1'B,
334 early_cm_ind := '0'B,
335 sched_where := {
336 presence := '0'B,
337 where := omit
338 },
339 gprs_ind := {
340 presence := '1'B,
341 ind := {
342 ra_colour := 0,
343 si13_pos := '0'B
344 }
345 },
346 umts_early_cm_ind := '1'B,
347 si2_quater_ind := {
348 presence := '1'B,
349 ind := '0'B
350 },
351 iu_mode_ind := omit,
352 si21_ind := {
353 presence := '0'B,
354 pos := omit
355 }
356 }
357 },
358 si4 := {
359 lai := {
360 mcc_mnc := '001F01'H,
361 lac := 1
362 },
363 cell_sel_par := {
364 cell_resel_hyst_2dB := 2,
365 ms_txpwr_max_cch := 7,
366 acs := '0'B,
367 neci := true,
368 rxlev_access_min := 0
369 },
370 rach_control := {
371 max_retrans := RACH_MAX_RETRANS_7,
372 tx_integer := '1001'B,
373 cell_barr_access := false,
374 re_not_allowed := true,
375 acc := '0000010000000000'B
376 },
Neels Hofmeyr74083c22020-07-29 00:43:01 +0200377 cbch_chan_desc := {
378 iei := '64'O,
379 v := {
380 chan_nr := {
381 u := {
382 sdcch4 := {
383 tag := '001'B,
384 sub_chan := 2
385 }
386 },
387 tn := 0
388 },
389 tsc := 2,
390 h := false,
391 arfcn := 871,
392 maio_hsn := omit
393 }
394 },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200395 cbch_mobile_alloc := omit,
396 rest_octets := {
397 sel_params := {
398 presence := '0'B,
399 params := omit
400 },
401 pwr_offset := {
402 presence := '0'B,
403 offset := omit
404 },
405 gprs_ind := {
406 presence := '1'B,
407 ind := {
408 ra_colour := 0,
409 si13_pos := '0'B
410 }
411 },
412 s_presence := '0'B,
413 s := omit
414 }
415 },
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100416 si13 := {
417 rest_octets := {
418 presence := '1'B,
419 bcch_change_mark := ?,
420 si_change_field := '0000'B,
421 presence2 := '0'B,
422 si13_change_mark := omit,
423 gprs_ma := omit,
424 zero := '0'B, /* PBCCH not present in cell */
425 rac := 0,
426 spgc_ccch_sup := '0'B,
427 priority_access_thr := '110'B,
428 network_control_order := '00'B,
429 gprs_cell_opts := {
430 nmo := '01'B,
431 t3168 := '011'B,
432 t3192 := '010'B,
433 drx_timer_max := '011'B,
434 access_burst_type := '0'B,
435 control_ack_type := '1'B,
436 bs_cv_max := 15,
437 pan_presence := '1'B,
438 pan_dec := 1,
439 pan_inc := 1,
440 pan_max := '111'B,
441 ext_info_presence := ?,
442 ext_info_length := *,
443 ext_info := *
444 },
445 gprs_pwr_ctrl_params := {
446 alpha := 0,
447 t_avg_w := '10000'B,
448 t_avg_t := '10000'B,
449 pc_meas_chan := '0'B,
450 n_avg_i := '1000'B
451 }
452 }
453 },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200454 si5 := {
455 bcch_freq_list := '10000000000000000000000000000000'O
456 },
457 si5bis := omit,
458 si5ter := {
459 extd_bcch_freq_list := '9E050020000000000000000000000000'O
460 },
461 si6 := {
462 cell_id := 0,
463 lai := {
464 mcc_mnc := '001F01'H,
465 lac := 1
466 },
467 cell_options := {
468 dtx_ext := '1'B,
469 pwrc := false,
470 dtx := '01'B,
471 radio_link_timeout := '0111'B
472 },
473 ncc_permitted := '11111111'B,
Vadim Yanitskiy348b07c2022-03-10 17:11:22 +0300474 rest_octets := {
475 pch_nch_info := ?,
476 vbs_vgcs_options := ?,
477 dtm_support := '0'B,
478 rac := omit,
479 max_lapdm := omit,
480 band_ind := '0'B /* C0 ARFCN indicates 1800 band */
481 }
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200482 }
483 };
484
485
486/* List of all the System Information received on all RSL ports */
487type record of SystemInformationConfig SystemInformationConfig_list;
488
489function f_sysinfo_dec_raw(inout SystemInformationConfig si, RSL_Message rsl)
490{
491 var RSL_IE_Body sysinfo_type_ie;
492 var RSL_IE_SysinfoType si_type;
493 var octetstring data;
494
495 if (f_rsl_find_ie(rsl, RSL_IE_SYSINFO_TYPE, sysinfo_type_ie) == false) {
496 setverdict(fail, "Cannot find RSL_IE_SYSINFO_TYPE");
497 mtc.stop;
498 }
499 si_type := sysinfo_type_ie.sysinfo_type;
500
501 if (rsl.msg_type == RSL_MT_BCCH_INFO) {
502 var RSL_IE_Body bcch_ie;
503 if (f_rsl_find_ie(rsl, RSL_IE_FULL_BCCH_INFO, bcch_ie)) {
504 data := bcch_ie.other.payload;
505 }
506 } else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
507 var RSL_IE_Body l3_ie;
508 if (f_rsl_find_ie(rsl, RSL_IE_L3_INFO, l3_ie)) {
509 data := l3_ie.l3_info.payload;
510 }
511 } else {
512 setverdict(fail, "Don't understand this System Information message");
513 mtc.stop;
514 }
515
516 var boolean handled := false;
517
518 if (rsl.msg_type == RSL_MT_BCCH_INFO) {
519 handled := true;
520
521 if (si_type == RSL_SYSTEM_INFO_1) {
522 if (not isbound(data)) {
523 si.si1 := omit;
524 } else {
525 si.si1 := dec_SystemInformation(data).payload.si1;
526 }
527 } else if (si_type == RSL_SYSTEM_INFO_2) {
528 if (not isbound(data)) {
529 si.si2 := omit;
530 } else {
531 si.si2 := dec_SystemInformation(data).payload.si2;
532 }
533 } else if (si_type == RSL_SYSTEM_INFO_2bis) {
534 if (not isbound(data)) {
535 si.si2bis := omit;
536 } else {
537 si.si2bis := dec_SystemInformation(data).payload.si2bis;
538 }
539 } else if (si_type == RSL_SYSTEM_INFO_2ter) {
540 if (not isbound(data)) {
541 si.si2ter := omit;
542 } else {
543 si.si2ter := dec_SystemInformation(data).payload.si2ter;
544 }
545 } else if (si_type == RSL_SYSTEM_INFO_2quater) {
546 if (not isbound(data)) {
547 si.si2quater := {};
548 } else {
549 var SystemInformationType2quater decoded := dec_SystemInformation(data).payload.si2quater;
550 /* this is a *record* of SI2quaterRestOctets! (multiplexed) */
551 si.si2quater[decoded.rest_octets.si2quater_index] := decoded.rest_octets;
552 }
553 } else if (si_type == RSL_SYSTEM_INFO_3) {
554 if (not isbound(data)) {
555 si.si3 := omit;
556 } else {
557 si.si3 := dec_SystemInformation(data).payload.si3;
558 }
559 } else if (si_type == RSL_SYSTEM_INFO_4) {
560 if (not isbound(data)) {
561 si.si4 := omit;
562 } else {
563 si.si4 := dec_SystemInformation(data).payload.si4;
564 }
565 } else if (si_type == RSL_SYSTEM_INFO_13) {
566 if (not isbound(data)) {
567 si.si13 := omit;
568 } else {
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100569 si.si13 := dec_SystemInformation(data).payload.si13;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200570 }
571 } else {
572 handled := false;
573 }
574 } else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
575 handled := true;
576
577 if (si_type == RSL_SYSTEM_INFO_5) {
578 if (not isbound(data)) {
579 si.si5 := omit;
580 } else {
581 si.si5 := dec_SystemInformation(data).payload.si5;
582 }
583 } else if (si_type == RSL_SYSTEM_INFO_5bis) {
584 if (not isbound(data)) {
585 si.si5bis := omit;
586 } else {
587 si.si5bis := dec_SystemInformation(data).payload.si5bis;
588 }
589 } else if (si_type == RSL_SYSTEM_INFO_5ter) {
590 if (not isbound(data)) {
591 si.si5ter := omit;
592 } else {
593 si.si5ter := dec_SystemInformation(data).payload.si5ter;
594 }
595 } else if (si_type == RSL_SYSTEM_INFO_6) {
596 if (not isbound(data)) {
597 si.si6 := omit;
598 } else {
599 si.si6 := dec_SystemInformation(data).payload.si6;
600 }
601 } else {
602 handled := false;
603 }
604 }
605
606 if (not handled) {
607 setverdict(fail, "Unexpected SI type in ", rsl.msg_type, " message: ", si_type);
608 }
609}
610
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +0100611friend function gen_l3_valid_payload(hexstring imsi := ''H) return octetstring {
612 var octetstring l3_payload;
613 if (lengthof(imsi) == 0) {
614 imsi := f_rnd_imsi('00101'H);
615 }
616 l3_payload := enc_PDU_ML3_MS_NW(valueof(ts_LU_REQ(LU_Type_IMSI_Attach, ts_MI_LV(ts_MI_IMSI(imsi)))));
617 return l3_payload;
618}
619
Harald Weltea4ca4462018-02-09 00:17:14 +0100620type component test_CT extends CTRL_Adapter_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600621 /* Array of per-BTS/TRX state */
622 var BTS_State bts[NUM_BTS][NUM_TRX];
Harald Welte89ab1912018-02-23 18:56:29 +0100623 /* RSL common Channel Port (for RSL_Emulation) */
624 port RSL_CCHAN_PT RSL_CCHAN[NUM_BTS];
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600625 /* array of per-BTS/TRX RSL test ports */
626 port IPA_RSL_PT IPA_RSL[NUM_BTS][NUM_TRX];
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100627 port IPA_CODEC_PT IPA; /* Required for compilation of TC_rsl_unknown_unit_id() */
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +0200628 /* CTRL muxed over IPA in SCCPlite conn BSC<->MSC (or BSC-NAT) */
629 port IPA_CTRL_PT SCCPLITE_IPA_CTRL;
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200630 /* Configure/manage IPA_Emulation per-BTS/TRX port: */
631 port IPA_CFG_PT IPA_CFG_PORT[NUM_BTS][NUM_TRX];
Harald Weltea5d2ab22017-12-09 14:21:42 +0100632
Pau Espin Pedrol3c630532022-10-20 19:00:11 +0200633 var MGCP_Emulation_CT vc_MGCP[NUM_MGW];
634 var integer g_nr_mgw; /* number of vc_MGCP to initialize */
Harald Weltebc03c762018-02-12 18:09:38 +0100635 port TELNETasp_PT BSCVTY;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100636
Daniel Willmannebdecc02020-08-12 15:30:17 +0200637 /* StatsD */
638 var StatsD_Checker_CT vc_STATSD;
639
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200640 var RAN_Adapter g_bssap[NUM_MSC];
Harald Welte47cd0e32020-08-21 12:39:11 +0200641 var BSSAP_LE_Adapter g_bssap_le;
Harald Weltea4ca4462018-02-09 00:17:14 +0100642 /* for old legacy-tests only */
643 port BSSAP_CODEC_PT BSSAP;
Harald Welte47cd0e32020-08-21 12:39:11 +0200644 port BSSAP_LE_CODEC_PT BSSAP_LE;
Harald Weltea4ca4462018-02-09 00:17:14 +0100645
Harald Welte21b46bd2017-12-17 19:46:32 +0100646 /* are we initialized yet */
Harald Welte28d943e2017-11-25 15:00:50 +0100647 var boolean g_initialized := false;
Harald Welte21b46bd2017-12-17 19:46:32 +0100648
Neels Hofmeyr38632aa2023-04-05 03:50:51 +0200649 var boolean g_handler_mode := false;
650
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200651 /* Osmux is enabled through VTY */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200652 var boolean g_osmux_enabled_cn := false;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +0200653 var boolean g_osmux_enabled_bts := false;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200654
Pau Espin Pedrolc675b612020-01-09 19:55:40 +0100655 /*Configure T(tias) over VTY, seconds */
656 var integer g_bsc_sccp_timer_ias := 7 * 60;
657 /*Configure T(tiar) over VTY, seconds */
658 var integer g_bsc_sccp_timer_iar := 15 * 60;
659
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +0200660 /* global test case guard timer (actual timeout value is set in f_init()) */
Harald Welteae026692017-12-09 01:03:01 +0100661 timer T_guard := 30.0;
662
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200663 var CounterNameValsList g_ctr_msc;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000664 var CounterNameValsList g_ctr_bsc;
665 var CounterNameValsList g_ctr_bts;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200666
667 /* System Information bytes as received during RSL startup, for each RSL[idx]. */
668 var SystemInformationConfig_list g_system_information := {};
Harald Welte28d943e2017-11-25 15:00:50 +0100669}
670
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200671type record of charstring phys_chan_configs;
Harald Welte28d943e2017-11-25 15:00:50 +0100672modulepar {
Harald Welte21b46bd2017-12-17 19:46:32 +0100673 /* IP address at which the BSC can be reached */
Harald Welte696ddb62017-12-08 14:01:43 +0100674 charstring mp_bsc_ip := "127.0.0.1";
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100675 /* port number to which to establish the IPA OML connections */
676 integer mp_bsc_oml_port := 3002;
Harald Welte21b46bd2017-12-17 19:46:32 +0100677 /* port number to which to establish the IPA RSL connections */
Harald Welte696ddb62017-12-08 14:01:43 +0100678 integer mp_bsc_rsl_port := 3003;
Harald Welte21b46bd2017-12-17 19:46:32 +0100679 /* port number to which to establish the IPA CTRL connection */
Harald Welte96c94412017-12-09 03:12:45 +0100680 integer mp_bsc_ctrl_port := 4249;
Daniel Willmannebdecc02020-08-12 15:30:17 +0200681 /* port number to which to listen for STATSD metrics */
682 integer mp_bsc_statsd_port := 8125;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100683 /* IP address at which the test binds */
684 charstring mp_test_ip := "127.0.0.1";
Harald Weltea4ca4462018-02-09 00:17:14 +0100685
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200686 RAN_Configurations mp_bssap_cfg := {
687 {
688 transport := BSSAP_TRANSPORT_AoIP,
689 sccp_service_type := "mtp3_itu",
690 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
691 own_pc := 185, /* 0.23.1 first MSC emulation */
692 own_ssn := 254,
693 peer_pc := 187, /* 0.23.3 osmo-bsc */
694 peer_ssn := 254,
695 sio := '83'O,
Harald Weltecb0cc432020-06-21 19:42:31 +0200696 rctx := 1
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200697 },
698 {
699 transport := BSSAP_TRANSPORT_AoIP,
700 sccp_service_type := "mtp3_itu",
701 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
702 own_pc := 2, /* 0.0.2 second MSC emulation */
703 own_ssn := 254,
704 peer_pc := 187, /* 0.23.3 osmo-bsc */
705 peer_ssn := 254,
706 sio := '83'O,
707 rctx := 2
708 },
709 {
710 transport := BSSAP_TRANSPORT_AoIP,
711 sccp_service_type := "mtp3_itu",
712 sctp_addr := { 23907, "127.0.0.1", 2905, "127.0.0.1" },
713 own_pc := 3, /* 0.0.3 third MSC emulation */
714 own_ssn := 254,
715 peer_pc := 187, /* 0.23.3 osmo-bsc */
716 peer_ssn := 254,
717 sio := '83'O,
718 rctx := 3
719 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100720 };
Pau Espin Pedrol58cf6822019-05-28 18:11:33 +0200721
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200722 /* Must match per BTS config in osmo-bsc.cfg */
723 phys_chan_configs phys_chan_config := {
724 "CCCH+SDCCH4+CBCH",
725 "TCH/F",
726 "TCH/F",
727 "TCH/F",
728 "TCH/F",
Vadim Yanitskiy343c9eb2021-07-16 18:36:01 +0600729 "TCH/H",
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200730 "PDCH",
731 "PDCH"
732 };
733
Harald Welte47cd0e32020-08-21 12:39:11 +0200734 BSSAP_LE_Configuration mp_bssap_le_cfg := {
735 sccp_service_type := "mtp3_itu",
736 sctp_addr := { 23908, "127.0.0.1", 2905, "127.0.0.1" },
Neels Hofmeyrac086c12020-09-18 23:46:42 +0200737 own_pc := 190, /* 0.23.6 SMLC emulation */
Harald Welte47cd0e32020-08-21 12:39:11 +0200738 own_ssn := 252, /* SMLC side SSN */
739 peer_pc := 187, /* 0.23.3 osmo-bsc */
740 peer_ssn := 250, /* BSC side SSN */
741 sio := '83'O,
742 rctx := 6
743 };
Neels Hofmeyrcfe44062020-10-15 02:28:08 +0200744 boolean mp_enable_lcs_tests := true;
Harald Welte47cd0e32020-08-21 12:39:11 +0200745
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100746 /* Value set in osmo-bsc.cfg "ms max power" */
747 uint8_t mp_exp_ms_power_level := 7;
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600748
749 /* Whether to check for memory leaks */
750 boolean mp_verify_talloc_count := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100751}
752
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200753friend function f_gen_test_hdlr_pars(integer bssap_idx := 0) return TestHdlrParams {
Philipp Maier48604732018-10-09 15:00:37 +0200754
755 var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200756 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier48604732018-10-09 15:00:37 +0200757 pars.aoip := true;
758 } else {
759 pars.aoip := false;
760 }
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100761 pars.exp_ms_power_level := mp_exp_ms_power_level;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200762 pars.mscpool.bssap_idx := bssap_idx;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600763 pars.expect_tsc := c_BtsParams[0].tsc;
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300764 pars.imsi := f_rnd_imsi('00101'H);
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +0100765 pars.imei := f_rnd_imei('00101'H);
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300766
767 log(testcasename(), ": using IMSI ", pars.imsi);
Neels Hofmeyrb5b7a6e2021-06-04 19:03:45 +0200768
Philipp Maier48604732018-10-09 15:00:37 +0200769 return pars;
770}
771
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200772/* Convenience functions for rate counters using g_ctr_msc. */
773
774private function f_ctrs_msc_init(integer mscs_count := NUM_MSC, CounterNameVals counternames := counternames_msc_mscpool) runs on test_CT {
775 g_ctr_msc := f_counter_name_vals_get_n(IPA_CTRL, "msc", mscs_count, counternames);
776 log("initial msc rate counters: ", g_ctr_msc);
777}
778
779private function f_ctrs_msc_add(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr9656e922020-06-30 01:27:01 +0200780 f_counter_name_vals_list_add(g_ctr_msc, msc_nr, countername, val);
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200781}
782
783/* f_ctrs_msc_init();
784 * f_do_thing(on_msc := 0);
785 * f_do_thing(on_msc := 0);
786 * f_do_other(on_msc := 1);
787 * f_ctrs_msc_add(0, "thing", 2);
788 * f_ctrs_msc_add(1, "other");
789 * f_ctrs_msc_verify();
790 */
791private function f_ctrs_msc_verify() runs on test_CT {
792 log("verifying msc rate counters: ", g_ctr_msc);
793 f_counter_name_vals_expect_n(IPA_CTRL, "msc", g_ctr_msc);
794}
795
796/* convenience: f_ctrs_msc_add() and f_ctrs_msc_verify() in one call.
797 * f_ctrs_msc_init();
798 * f_do_thing(on_msc := 0);
799 * f_do_thing(on_msc := 0);
800 * f_do_thing(on_msc := 0);
801 * f_ctrs_msc_expect(0, "thing", 3);
802 */
803private function f_ctrs_msc_expect(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
804 f_ctrs_msc_add(msc_nr, countername, val);
805 f_ctrs_msc_verify();
806}
807
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000808/* Convenience functions for rate counters using g_ctr_bts, always also including g_ctr_bsc. */
809
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100810private function f_ctrs_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000811 g_ctr_bts := f_counter_name_vals_get_n(IPA_CTRL, "bts", bts_count, counternames);
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100812 log("initial bts rate counters: ", g_ctr_bts);
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100813}
814
815function f_ctrs_bsc_and_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
816 f_ctrs_bts_init(bts_count, counternames);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000817 f_ctrs_bsc_init(counternames);
818}
819
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100820private function f_ctrs_bsc_and_bts_handover_init(integer bts_count := NUM_BTS) runs on test_CT {
821 var CounterNameVals bts_names := counternames_bsc_bts_handover & counternames_bts_handover;
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100822 f_ctrs_bts_init(bts_count, bts_names);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100823 f_ctrs_bsc_init(counternames_bsc_bts_handover);
824}
825
826private function f_ctrs_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000827 f_counter_name_vals_list_add(g_ctr_bts, bts_nr, countername, val);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100828}
829
830private function f_ctrs_bsc_and_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
831 f_ctrs_bts_add(bts_nr, countername, val);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000832 f_ctrs_bsc_add(countername, val);
833}
834
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100835function f_ctrs_bts_verify() runs on test_CT {
836 f_counter_name_vals_expect_n(IPA_CTRL, "bts", g_ctr_bts);
837}
838
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000839/* f_ctrs_bsc_and_bts_init();
840 * f_do_thing(on_bts := 0);
841 * f_do_thing(on_bts := 0);
842 * f_do_other(on_bts := 1);
843 * f_ctrs_bsc_and_bts_add(0, "thing", 2);
844 * f_ctrs_bsc_and_bts_add(1, "other");
845 * f_ctrs_bsc_and_bts_verify();
846 */
847private function f_ctrs_bsc_and_bts_verify() runs on test_CT {
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100848 f_ctrs_bts_verify();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000849 f_ctrs_bsc_verify();
850}
851
852/* convenience: f_ctrs_bsc_and_bts_add() and f_ctrs_bsc_and_bts_verify() in one call.
853 * f_ctrs_bsc_and_bts_init();
854 * f_do_thing(on_bts := 0);
855 * f_do_thing(on_bts := 0);
856 * f_do_thing(on_bts := 0);
857 * f_ctrs_bsc_and_bts_expect(0, "thing", 3);
858 */
859private function f_ctrs_bsc_and_bts_expect(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
860 f_ctrs_bsc_and_bts_add(bts_nr, countername, val);
861 f_ctrs_bsc_and_bts_verify();
862}
863
864
865/* Convenience functions for rate counters using g_ctr_bsc. */
866
867private function f_ctrs_bsc_init(CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
868 g_ctr_bsc := f_counter_name_vals_get_n(IPA_CTRL, "bsc", 1, counternames);
869 log("initial bsc rate counters: ", g_ctr_bsc);
870}
871
872private function f_ctrs_bsc_add(charstring countername, integer val := 1) runs on test_CT {
873 f_counter_name_vals_list_add(g_ctr_bsc, 0, countername, val);
874}
875
876/* f_ctrs_bsc_init();
877 * f_do_thing();
878 * f_do_thing();
879 * f_do_other();
880 * f_ctrs_bsc_add("thing", 2);
881 * f_ctrs_bsc_add("other");
882 * f_ctrs_bsc_verify();
883 */
884private function f_ctrs_bsc_verify() runs on test_CT {
885 f_counter_name_vals_expect_n(IPA_CTRL, "bsc", g_ctr_bsc);
886}
887
888/* convenience: f_ctrs_bsc_add() and f_ctrs_bsc_verify() in one call.
889 * f_ctrs_bsc_init();
890 * f_do_thing();
891 * f_ctrs_bsc_expect("thing", 1);
892 */
893private function f_ctrs_bsc_expect(charstring countername, integer val := 1) runs on test_CT {
894 f_ctrs_bsc_add(countername, val);
895 f_ctrs_bsc_verify();
896}
897
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200898
Oliver Smith39f53072022-10-27 14:44:04 +0200899friend function f_shutdown_helper(boolean ho := false) runs on test_CT {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100900 /* Run the subscr and conn leak test only when the VTY is initialized */
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600901 if (BSCVTY.checkstate("Mapped") and mp_verify_talloc_count) {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100902 f_verify_talloc_count(BSCVTY, {"struct bsc_subscr", "struct gsm_subscriber_connection"});
903 }
904
Oliver Smith39f53072022-10-27 14:44:04 +0200905 /* Reset handover related configuration */
906 if (ho) {
907 f_bts_0_cfg(BSCVTY,
908 {"no neighbors",
909 "neighbor-list mode manual-si5",
910 "neighbor-list add arfcn 100",
911 "neighbor-list add arfcn 200",
912 "si5 neighbor-list add arfcn 10",
913 "si5 neighbor-list add arfcn 20",
914 "handover algorithm 1"});
915 }
916
Daniel Willmann637ef6c2018-07-25 10:49:09 +0200917 all component.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100918 setverdict(pass);
Daniel Willmannafce8662018-07-06 23:11:32 +0200919 mtc.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100920}
921
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200922private function f_legacy_bssap_reset(integer bssap_idx := 0) runs on test_CT {
Harald Weltea4ca4462018-02-09 00:17:14 +0100923 var BSSAP_N_UNITDATA_ind ud_ind;
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200924 var boolean reset_received := false;
Harald Weltea4ca4462018-02-09 00:17:14 +0100925 timer T := 5.0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200926 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200927 ts_BSSMAP_Reset(0, g_osmux_enabled_cn)));
Harald Weltea4ca4462018-02-09 00:17:14 +0100928 T.start;
929 alt {
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200930 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[bssap_idx].sccp_addr_own, g_bssap[bssap_idx].sccp_addr_peer,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200931 tr_BSSMAP_ResetAck(g_osmux_enabled_cn))) {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200932 log("BSSMAP: Received RESET-ACK in response to RESET, we're ready to go!");
Harald Weltea4ca4462018-02-09 00:17:14 +0100933 }
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200934 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200935 log("BSSMAP: Respoding to inbound RESET with RESET-ACK");
Harald Weltea4ca4462018-02-09 00:17:14 +0100936 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200937 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200938 reset_received := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100939 repeat;
940 }
941 [] BSSAP.receive { repeat; }
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200942 [] T.timeout {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200943 log("BSSMAP: Timeout waiting for RESET-ACK after sending RESET");
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200944 /* If we received a RESET after ours was sent, it
945 may be a race condition where the other peer beacame
946 available after we sent it, but we are in a desired
947 state anyway, so go forward. */
948 if (not reset_received) {
949 setverdict(fail);
950 }
951 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100952 }
Harald Welte28d943e2017-11-25 15:00:50 +0100953}
954
Harald Welteae026692017-12-09 01:03:01 +0100955type record IPA_Client {
Harald Welte21b46bd2017-12-17 19:46:32 +0100956 /* IPA Emulation component reference */
Harald Welteae026692017-12-09 01:03:01 +0100957 IPA_Emulation_CT vc_IPA,
Harald Welte21b46bd2017-12-17 19:46:32 +0100958 /* Unit-ID and other CCM parameters to use for IPA client emulation */
Harald Welteae026692017-12-09 01:03:01 +0100959 IPA_CCM_Parameters ccm_pars,
Harald Welte21b46bd2017-12-17 19:46:32 +0100960 /* String identifier for this IPA Client */
Harald Welte624f9632017-12-16 19:26:04 +0100961 charstring id,
Harald Welte21b46bd2017-12-17 19:46:32 +0100962 /* Associated RSL Emulation Component (if any). Only used in "Handler mode" */
Harald Welte624f9632017-12-16 19:26:04 +0100963 RSL_Emulation_CT vc_RSL optional
Harald Welte28d943e2017-11-25 15:00:50 +0100964}
965
Harald Welte21b46bd2017-12-17 19:46:32 +0100966/*! Start the IPA/RSL related bits for one IPA_Client.
967 * \param clnt IPA_Client for which to establish
968 * \param bsc_host IP address / hostname of the BSC
969 * \param bsc_port TCP port number of the BSC
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600970 * \param idx BTS/TRX index values
Harald Welte21b46bd2017-12-17 19:46:32 +0100971 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600972function f_ipa_rsl_start(inout IPA_Client clnt, charstring bsc_host, PortNumber bsc_port,
973 BtsTrxIdx idx := {0, 0}, boolean handler_mode := false)
Harald Welte28d943e2017-11-25 15:00:50 +0100974runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +0100975 timer T := 10.0;
976
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600977 clnt.id := "IPA-BTS" & int2str(idx.bts) & "-TRX" & int2str(idx.trx) & "-RSL";
Harald Welte71389132021-12-09 21:58:18 +0100978 clnt.vc_IPA := IPA_Emulation_CT.create(clnt.id & "-IPA") alive;
Harald Welteae026692017-12-09 01:03:01 +0100979 clnt.ccm_pars := c_IPA_default_ccm_pars;
980 clnt.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600981 clnt.ccm_pars.unit_id := int2str(1234 + idx.bts) & "/0/" & int2str(idx.trx);
Harald Welte624f9632017-12-16 19:26:04 +0100982 if (handler_mode) {
Harald Welte71389132021-12-09 21:58:18 +0100983 clnt.vc_RSL := RSL_Emulation_CT.create(clnt.id & "-RSL") alive;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600984 connect(clnt.vc_RSL:CCHAN_PT, self:RSL_CCHAN[idx.bts]);
Harald Welte624f9632017-12-16 19:26:04 +0100985 }
Harald Welteae026692017-12-09 01:03:01 +0100986
987 map(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200988 connect(clnt.vc_IPA:CFG_PORT, self:IPA_CFG_PORT[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100989 if (handler_mode) {
990 connect(clnt.vc_IPA:IPA_RSL_PORT, clnt.vc_RSL:IPA_PT);
991 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600992 connect(clnt.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100993 }
Harald Welteae026692017-12-09 01:03:01 +0100994
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600995 var integer local_port := 10000 + idx.bts * 1000 + idx.trx;
996 clnt.vc_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", local_port, clnt.ccm_pars));
Harald Welte624f9632017-12-16 19:26:04 +0100997 if (handler_mode) {
998 clnt.vc_RSL.start(RSL_Emulation.main());
999 return;
1000 }
Harald Welteae026692017-12-09 01:03:01 +01001001
1002 /* wait for IPA RSL link to connect and send ID ACK */
1003 T.start;
1004 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001005 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) {
Harald Welteae026692017-12-09 01:03:01 +01001006 T.stop;
Harald Welteae026692017-12-09 01:03:01 +01001007 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001008 [] IPA_RSL[idx.bts][idx.trx].receive(ASP_IPA_Event:?) { repeat }
1009 [] IPA_RSL[idx.bts][idx.trx].receive { repeat }
Harald Welteae026692017-12-09 01:03:01 +01001010 [] T.timeout {
Harald Welte96c94412017-12-09 03:12:45 +01001011 setverdict(fail, "Timeout RSL waiting for ASP_IPA_EVENT_ID_ACK");
Daniel Willmannafce8662018-07-06 23:11:32 +02001012 mtc.stop;
Harald Welteae026692017-12-09 01:03:01 +01001013 }
1014 }
1015}
1016
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001017function f_ipa_rsl_stop(inout IPA_Client clnt, BtsTrxIdx idx := {0, 0}) runs on test_CT {
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001018 var IPL4asp_Types.Result res := {
1019 errorCode := omit,
1020 connId := omit,
1021 os_error_code := omit,
1022 os_error_text := omit
1023 };
1024
Harald Welte12055472018-03-17 20:10:08 +01001025 if (not isbound(clnt) or not isbound(clnt.vc_IPA)) {
1026 return;
1027 }
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001028
1029 /* Alive components don't finish sockets (TCP FIN) when they are
1030 * stopped. Hence, we need to manually call close() on them to make sure
1031 * the IUT knows about it. */
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001032 f_ipa_cfg_disconnect(IPA_CFG_PORT[idx.bts][idx.trx], res);
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001033
Harald Welte12055472018-03-17 20:10:08 +01001034 clnt.vc_IPA.stop;
1035 if (isbound(clnt.vc_RSL)) {
1036 clnt.vc_RSL.stop;
1037 }
1038}
1039
Harald Welte21b46bd2017-12-17 19:46:32 +01001040/* Wait for the OML connection to be brought up by the external osmo-bts-omldummy */
Harald Weltea5d2ab22017-12-09 14:21:42 +01001041function f_wait_oml(integer bts_nr, charstring status, float secs_max) runs on test_CT {
1042 timer T := secs_max;
1043 T.start;
1044 while (true) {
1045 if (f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-connection-state") == status) {
1046 T.stop;
Harald Weltebd868bd2017-12-10 18:28:40 +01001047 /* the 'degraded' state exists from OML connection time, and we have to wait
1048 * until all MO's are initialized */
1049 T.start(1.0);
1050 T.timeout;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001051 return;
1052 }
Harald Weltef0d6ac62017-12-17 17:02:21 +01001053 f_sleep(0.1);
Harald Weltea5d2ab22017-12-09 14:21:42 +01001054 if (not T.running) {
Max99253902018-11-16 17:57:39 +01001055 setverdict(fail, "Timeout waiting for BTS" & int2str(bts_nr) & " oml-connection-state ", status);
Daniel Willmannafce8662018-07-06 23:11:32 +02001056 mtc.stop;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001057 }
1058 }
1059}
1060
Harald Welte21b46bd2017-12-17 19:46:32 +01001061/* global altstep for global guard timer; also takes care of responding RESET witH RESET-ACK */
Harald Welteae026692017-12-09 01:03:01 +01001062altstep as_Tguard() runs on test_CT {
Harald Welte60e823a2017-12-10 14:10:59 +01001063 var BSSAP_N_UNITDATA_ind ud_ind;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001064 [] T_guard.timeout {
1065 setverdict(fail, "Timeout of T_guard");
Daniel Willmannafce8662018-07-06 23:11:32 +02001066 mtc.stop;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001067 }
Harald Welte60e823a2017-12-10 14:10:59 +01001068 /* always respond with RESET ACK to RESET */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001069 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Harald Welte60e823a2017-12-10 14:10:59 +01001070 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001071 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Harald Welte69c1c262017-12-13 21:02:08 +01001072 repeat;
Harald Welte60e823a2017-12-10 14:10:59 +01001073 }
Harald Welte28d943e2017-11-25 15:00:50 +01001074}
1075
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001076altstep no_bssmap_reset() runs on test_CT {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001077 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001078 setverdict(fail, "unexpected BSSMAP Reset");
Daniel Willmannafce8662018-07-06 23:11:32 +02001079 mtc.stop;
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001080 }
1081}
1082
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001083function f_init_mgcp(integer mgw_nr, charstring id) runs on test_CT {
1084 id := id & "-MGCP-" & int2str(mgw_nr);
Daniel Willmann191e0d92018-01-17 12:44:35 +01001085
1086 var MGCPOps ops := {
1087 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
1088 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
1089 };
1090 var MGCP_conn_parameters mgcp_pars := {
1091 callagent_ip := mp_bsc_ip,
Harald Welte9e4273e2018-01-29 22:01:22 +01001092 callagent_udp_port := -1,
Daniel Willmann191e0d92018-01-17 12:44:35 +01001093 mgw_ip := mp_test_ip,
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001094 mgw_udp_port := 2427 + mgw_nr,
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02001095 /* Enable it for SCCPlite, since we have 2 MGCP sockets towards MGW (UDP one +
Pau Espin Pedrol36eeaf72022-10-20 16:50:31 +02001096 the one with MGCP over IPA forwarded from MSC one) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001097 multi_conn_mode := (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER)
Daniel Willmann191e0d92018-01-17 12:44:35 +01001098 };
1099
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001100 vc_MGCP[mgw_nr] := MGCP_Emulation_CT.create(id) alive;
1101 vc_MGCP[mgw_nr].start(MGCP_Emulation.main(ops, mgcp_pars, id));
Daniel Willmann191e0d92018-01-17 12:44:35 +01001102}
1103
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001104/* Enable or disable (current default) Osmux. When enabling, BSSMAP Reset
1105 * contains extra IE (OsmuxSupport) and osmo-bsc will handle AssignReq with
1106 * OsmuxCID IE.
1107 */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001108private function f_vty_allow_osmux_cn(boolean allow) runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001109 f_vty_enter_cfg_msc(BSCVTY, 0);
1110 if (allow) {
1111 f_vty_transceive(BSCVTY, "osmux on");
1112 } else {
1113 f_vty_transceive(BSCVTY, "osmux off");
1114 }
1115 f_vty_transceive(BSCVTY, "exit");
1116 f_vty_transceive(BSCVTY, "exit");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001117}
1118
Max2253c0b2018-11-06 19:28:05 +01001119function f_init_vty(charstring id := "foo") runs on test_CT {
Harald Welte94e0c342018-04-07 11:33:23 +02001120 if (BSCVTY.checkstate("Mapped")) {
1121 /* skip initialization if already executed once */
1122 return;
1123 }
Harald Weltebc03c762018-02-12 18:09:38 +01001124 map(self:BSCVTY, system:BSCVTY);
1125 f_vty_set_prompts(BSCVTY);
1126 f_vty_transceive(BSCVTY, "enable");
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01001127 f_cs7_inst_0_cfg(BSCVTY, {"sccp-timer ias " & int2str(g_bsc_sccp_timer_ias),
1128 "sccp-timer iar " & int2str(g_bsc_sccp_timer_iar)});
Harald Weltebc03c762018-02-12 18:09:38 +01001129}
1130
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +02001131friend function f_logp(TELNETasp_PT pt, charstring log_msg)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001132{
1133 // log on TTCN3 log output
1134 log(log_msg);
1135 // log in stderr log
Neels Hofmeyr8bdafe52021-12-14 17:25:48 +01001136 if (pt.checkstate("Mapped")) {
1137 f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
1138 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001139}
1140
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001141private function f_sysinfo_seen(integer rsl_idx, RSL_Message rsl) runs on test_CT
1142{
1143 if (rsl_idx >= lengthof(g_system_information)) {
1144 g_system_information[rsl_idx] := SystemInformationConfig_omit
1145 }
1146 f_sysinfo_dec_raw(g_system_information[rsl_idx], rsl);
1147}
1148
1149altstep as_catch_RSL_sysinfo(integer rsl_idx) runs on test_CT {
1150 var ASP_RSL_Unitdata rx_rsl_ud;
1151
1152 /* For handler_mode := false, receiving the RSL bootstrap messages directly on IPA_RSL */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001153 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001154 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1155 repeat;
1156 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001157 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001158 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1159 repeat;
1160 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001161 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001162 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1163 repeat;
1164 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001165 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001166 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1167 repeat;
1168 }
1169
1170 /* For handler_mode := true, receiving the RSL bootstrap messages via RSL_Emulation */
1171 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
1172 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1173 repeat;
1174 }
1175 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
1176 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1177 repeat;
1178 }
1179 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
1180 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1181 repeat;
1182 }
1183 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
1184 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1185 repeat;
1186 }
1187}
1188
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001189/* TODO: use BooleanList from COMMON/src/General_Types.ttcn */
1190private type record of boolean my_BooleanList;
1191
1192private function f_vty_msc_allow_attach(TELNETasp_PT pt, my_BooleanList allow_attach_list)
1193{
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001194 var charstring config := f_vty_transceive_ret(pt, "show running-config");
1195
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001196 for (var integer msc_nr := 0; msc_nr < sizeof(allow_attach_list); msc_nr := msc_nr+1) {
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001197 if (f_strstr(config, "\nmsc " & int2str(msc_nr) & "\n") < 0) {
1198 /* There is no 'msc N' for this msc_nr in the running config, so don't create an empty msc by
1199 * stepping into that config node. */
1200 log("msc ", msc_nr, " is not configured, skipping");
1201 continue;
1202 }
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001203 f_vty_enter_cfg_msc(pt, msc_nr);
1204 if (allow_attach_list[msc_nr]) {
1205 /* strict := false: ignore if osmo-bsc does not support this config option (latest build) */
1206 f_vty_transceive(pt, "allow-attach", strict := false);
1207 } else {
1208 f_vty_transceive(pt, "no allow-attach", strict := false);
1209 }
1210 f_vty_transceive(pt, "exit");
1211 f_vty_transceive(pt, "exit");
1212 }
1213}
1214
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02001215private function f_bssap_idx_init(integer bssap_idx) runs on test_CT {
1216 /* Call a function of our 'parent component' RAN_Adapter_CT to start the
1217 * MSC-side BSSAP emulation */
1218 if (g_handler_mode) {
1219 var RanOps ranops := MSC_RanOps;
1220 ranops.use_osmux := g_osmux_enabled_cn;
1221 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", ranops);
1222 connect(self:SCCPLITE_IPA_CTRL, g_bssap[bssap_idx].vc_RAN:CTRL_CLIENT);
1223 f_ran_adapter_start(g_bssap[bssap_idx]);
1224 } else {
1225 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", omit);
1226 connect(self:BSSAP, g_bssap[bssap_idx].vc_SCCP:SCCP_SP_PORT);
1227 f_ran_adapter_start(g_bssap[bssap_idx]);
1228 f_legacy_bssap_reset();
1229 }
1230}
1231
1232private function f_bssap_idx_disconnect(integer bssap_idx) runs on test_CT {
1233 f_ran_adapter_cleanup(g_bssap[bssap_idx]);
1234}
1235
Harald Welte21b46bd2017-12-17 19:46:32 +01001236/* global initialization function
1237 * \param nr_bts Number of BTSs we should start/bring up
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001238 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false).
1239 * \param nr_msc Number of virtual MSCs to bring up to connect to osmo-bsc.
1240 */
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001241function f_init(integer nr_bts := NUM_BTS, boolean handler_mode := false,
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001242 integer nr_msc := 1, integer nr_mgw := 1, float guard_timeout := 30.0) runs on test_CT {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001243 var integer bssap_idx;
Harald Welte28d943e2017-11-25 15:00:50 +01001244
Harald Welteae026692017-12-09 01:03:01 +01001245 if (g_initialized) {
1246 return;
Harald Welte28d943e2017-11-25 15:00:50 +01001247 }
Harald Welteae026692017-12-09 01:03:01 +01001248 g_initialized := true;
1249
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +02001250 T_guard.start(guard_timeout);
Daniel Willmanne68f9272018-11-27 15:15:28 +01001251 activate(as_Tguard());
1252
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001253 f_init_vty("VirtMSC");
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001254 f_vty_allow_osmux_cn(g_osmux_enabled_cn);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001255
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001256 var my_BooleanList allow_attach := { false, false, false };
Daniel Willmannebdecc02020-08-12 15:30:17 +02001257 f_init_statsd("VirtMSC", vc_STATSD, mp_test_ip, mp_bsc_statsd_port);
1258
Neels Hofmeyr9db8e0e2021-08-23 20:45:58 +02001259 /* Make sure each MSC's internal state is "DISCONNECTED" at first */
1260 for (bssap_idx := 0; bssap_idx < NUM_MSC; bssap_idx := bssap_idx+1) {
1261 f_vty_transceive(BSCVTY, "msc " & int2str(bssap_idx) & " bssmap reset", strict := false);
1262 }
1263
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02001264 g_handler_mode := handler_mode;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001265 for (bssap_idx := 0; bssap_idx < nr_msc; bssap_idx := bssap_idx+1) {
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001266 allow_attach[bssap_idx] := true;
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02001267 f_bssap_idx_init(bssap_idx);
Harald Welte67089ee2018-01-17 22:19:03 +01001268 }
Harald Welted5833a82018-05-27 16:52:56 +02001269
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02001270 if (mp_enable_lcs_tests) {
1271 if (handler_mode) {
1272 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", SMLC_BssapLeOps);
1273 } else {
1274 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", omit);
1275 connect(self:BSSAP_LE, g_bssap_le.vc_SCCP:SCCP_SP_PORT);
1276 }
1277 f_bssap_le_adapter_start(g_bssap_le);
Harald Welte47cd0e32020-08-21 12:39:11 +02001278 }
Harald Welte47cd0e32020-08-21 12:39:11 +02001279
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001280 /* start the test with exactly all enabled MSCs allowed to attach */
1281 f_vty_msc_allow_attach(BSCVTY, allow_attach);
1282
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01001283 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Harald Welte28d943e2017-11-25 15:00:50 +01001284
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001285 g_nr_mgw := nr_mgw;
1286 for (var integer i := 0; i < g_nr_mgw; i := i+1) {
1287 f_init_mgcp(i, "VirtMGW");
1288 }
Daniel Willmann191e0d92018-01-17 12:44:35 +01001289
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001290 for (var integer i := 0; i < nr_bts; i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001291 f_init_bts(i, c_BtsParams[i].trx_num, handler_mode);
Harald Welte696ddb62017-12-08 14:01:43 +01001292 }
Neels Hofmeyr9c0f9c82022-01-23 01:20:28 +01001293
1294 /* Emit a marker to appear in the SUT's own logging output */
1295 f_logp(BSCVTY, testcasename() & "() start");
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001296}
Harald Welte696ddb62017-12-08 14:01:43 +01001297
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001298function f_init_bts(integer bts_idx := 0,
1299 integer trx_num := NUM_TRX_CFG,
1300 boolean handler_mode := false)
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001301runs on test_CT {
1302 /* wait until osmo-bts-omldummy has respawned */
1303 f_wait_oml(bts_idx, "degraded", 5.0);
1304
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001305 /* start RSL connection(s) */
1306 for (var integer trx_idx := 0; trx_idx < trx_num; trx_idx := trx_idx + 1) {
1307 f_ipa_rsl_start(bts[bts_idx][trx_idx].rsl,
1308 mp_bsc_ip, mp_bsc_rsl_port,
1309 {bts_idx, trx_idx}, handler_mode);
1310 }
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001311 /* wait until BSC tells us "connected" */
1312 f_wait_oml(bts_idx, "connected", 5.0);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001313
1314 /* Set up BTS with VTY commands: */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01001315 f_vty_enter_cfg_bts(BSCVTY, bts_idx);
1316 if (g_osmux_enabled_bts) {
1317 f_vty_transceive(BSCVTY, "osmux on");
1318 } else {
1319 f_vty_transceive(BSCVTY, "osmux off");
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001320 }
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01001321 f_vty_transceive(BSCVTY, "end");
Harald Welte28d943e2017-11-25 15:00:50 +01001322}
1323
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001324function f_init_bts_and_check_sysinfo(integer bts_idx := 0,
1325 integer trx_num := NUM_TRX_CFG,
1326 boolean handler_mode := false,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001327 template SystemInformationConfig expect_si)
1328runs on test_CT {
1329 var default sysinfo := activate(as_catch_RSL_sysinfo(bts_idx));
1330
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001331 f_init_bts(bts_idx, trx_num, handler_mode);
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001332
1333 /* Give some time to (hopefully/most likely) collect all system informations from RSL startup.
1334 * We could stop as soon as all expected SI are received, but then we might miss SI that we don't expect and
1335 * that might be sent afterwards. So rather give a generous timeout and be quite sure to catch all SI.
1336 */
1337 f_sleep(5.0);
1338 log("RSL ", bts_idx, " SYSTEM INFORMATION: ", g_system_information[bts_idx]);
1339
1340 deactivate(sysinfo);
1341
1342 if (match(g_system_information[bts_idx], expect_si)) {
1343 setverdict(pass);
1344 } else {
1345 log("RSL ", bts_idx, ": EXPECTED SI: ", expect_si);
1346 log("RSL ", bts_idx, ": GOT SI: ", g_system_information[bts_idx]);
1347 setverdict(fail, "received SI does not match expectations");
1348 return;
1349 }
1350}
1351
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001352/* expect to receive a RSL message matching a specified template on a given BTS / TRX */
1353function f_exp_ipa_rx(template (present) RSL_Message t_rx,
1354 BtsTrxIdx idx := {0, 0},
1355 float Tval := 2.0)
Harald Welteae026692017-12-09 01:03:01 +01001356runs on test_CT return RSL_Message {
1357 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001358 timer T := Tval;
Harald Welteae026692017-12-09 01:03:01 +01001359
1360 T.start;
1361 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001362 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Harald Welteae026692017-12-09 01:03:01 +01001363 T.stop;
1364 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001365 [] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
Harald Welteb2917702017-12-10 15:48:52 +01001366 [] T.timeout {
1367 setverdict(fail, "Timeout expecting ", t_rx);
Daniel Willmannafce8662018-07-06 23:11:32 +02001368 mtc.stop;
Harald Welteb2917702017-12-10 15:48:52 +01001369 }
Harald Welteae026692017-12-09 01:03:01 +01001370 }
1371 return rx_rsl_ud.rsl;
1372}
1373
Harald Welte21b46bd2017-12-17 19:46:32 +01001374/* helper function to transmit RSL on a given BTS/stream */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001375function f_ipa_tx(template (value) RSL_Message t_tx,
1376 BtsTrxIdx idx := {0, 0},
1377 IpaStreamId sid := IPAC_PROTO_RSL_TRX0)
Harald Welteae026692017-12-09 01:03:01 +01001378runs on test_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001379 IPA_RSL[idx.bts][idx.trx].send(ts_ASP_RSL_UD(t_tx, sid));
Harald Welteae026692017-12-09 01:03:01 +01001380}
1381
1382
Harald Welte4003d112017-12-09 22:35:39 +01001383/* verify we get a CHAN_ACT after CHAN RQD */
Harald Welteae026692017-12-09 01:03:01 +01001384testcase TC_chan_act_noreply() runs on test_CT {
1385 var BSSAP_N_UNITDATA_ind ud_ind;
Harald Welte930d0a72018-03-22 22:08:40 +01001386 var RSL_Message rsl_unused;
Harald Welte28d943e2017-11-25 15:00:50 +01001387
Harald Welte89d42e82017-12-17 16:42:41 +01001388 f_init(1);
Harald Welte28d943e2017-11-25 15:00:50 +01001389
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001390 f_ipa_tx(ts_RSL_CHAN_RQD('23'O, 23));
1391 rsl_unused := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001392 f_shutdown_helper();
Harald Welte28d943e2017-11-25 15:00:50 +01001393}
1394
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001395const CounterNameVals counternames_bts_chreq := {
1396 { "chreq:total", 0 },
1397 { "chreq:attempted_emerg", 0 },
1398 { "chreq:attempted_call", 0 },
1399 { "chreq:attempted_location_upd", 0 },
1400 { "chreq:attempted_pag", 0 },
1401 { "chreq:attempted_pdch", 0 },
1402 { "chreq:attempted_other", 0 },
1403 { "chreq:attempted_unknown", 0 },
1404 { "chreq:successful", 0 },
1405 { "chreq:successful_emerg", 0 },
1406 { "chreq:successful_call", 0 },
1407 { "chreq:successful_location_upd", 0 },
1408 { "chreq:successful_pag", 0 },
1409 { "chreq:successful_pdch", 0 },
1410 { "chreq:successful_other", 0 },
1411 { "chreq:successful_unknown", 0 },
1412 { "chreq:no_channel", 0 },
1413 { "chreq:max_delay_exceeded", 0 }
1414};
1415
1416/* verify the "chreq:*" counters */
1417private function f_chan_act_counter(OCT1 ra, charstring chreq_ctr_suffix) runs on test_CT
1418{
1419 var GsmFrameNumber fn := 23;
1420
1421 f_logp(BSCVTY, "f_chan_act_counter(" & chreq_ctr_suffix & ")");
1422
1423 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001424 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn));
1425 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001426 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1427
1428 f_ctrs_bts_add(0, "chreq:total");
1429 f_ctrs_bts_add(0, "chreq:attempted_" & chreq_ctr_suffix);
1430 f_ctrs_bts_verify();
1431
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001432 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
1433 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001434
1435 f_ctrs_bts_add(0, "chreq:successful");
1436 f_ctrs_bts_add(0, "chreq:successful_" & chreq_ctr_suffix);
1437 f_ctrs_bts_verify();
1438
1439 /* test is done, release RSL Conn Fail Ind to clean up */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001440 f_ipa_tx(ts_RSL_CONN_FAIL_IND(chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1441 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
1442 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001443 f_sleep(1.0);
1444}
1445
Harald Welte4003d112017-12-09 22:35:39 +01001446testcase TC_chan_act_counter() runs on test_CT {
1447 var BSSAP_N_UNITDATA_ind ud_ind;
1448 var integer chreq_total;
Harald Welte930d0a72018-03-22 22:08:40 +01001449 var RSL_Message rsl_unused;
Harald Welte4003d112017-12-09 22:35:39 +01001450
Harald Welte89d42e82017-12-17 16:42:41 +01001451 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001452
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001453 f_vty_allow_emerg_bts(true, 0);
1454
1455 f_ctrs_bts_init(1, counternames_bts_chreq);
1456
1457 /* emergency call: RA & 0xe0 == 0xa0 --> CHREQ_T_EMERG_CALL */
1458 f_chan_act_counter('a3'O, "emerg");
1459
1460 /* voice TCH/H: RA & 0xf0 == 0x40 --> CHREQ_T_VOICE_CALL_TCH_H */
1461 f_chan_act_counter('43'O, "call");
1462
1463 /* LU: RA & 0xf0 == 0x00 --> CHREQ_T_LOCATION_UPD */
1464 f_chan_act_counter('03'O, "location_upd");
1465
1466 /* Paging: RA & 0xf0 == 0x20 --> CHREQ_T_PAG_R_TCH_F */
1467 f_chan_act_counter('23'O, "pag");
1468 /* Paging: RA & 0xf0 == 0x30 --> CHREQ_T_PAG_R_TCH_FH */
1469 f_chan_act_counter('33'O, "pag");
1470
1471 /* LU: RA & 0xfc == 0x78 --> CHREQ_T_PDCH_TWO_PHASE */
1472 /* no PCU, so PDCH not allowed. Skip this test for now. */
1473 /* f_chan_act_counter('7b'O, "pdch"); */
1474
1475 /* LU: RA & 0xf0 == 0x10 --> CHREQ_T_SDCCH */
1476 f_chan_act_counter('13'O, "other");
Harald Welte4003d112017-12-09 22:35:39 +01001477
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001478 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001479}
1480
Harald Welteae026692017-12-09 01:03:01 +01001481/* CHAN RQD -> CHAN ACT -> CHAN ACT ACK -> RF CHAN REL */
Philipp Maier9c60a622020-07-09 15:08:46 +02001482private function f_TC_chan_act_ack_noest(OCT1 ra := '23'O) runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +01001483 var RSL_Message rx_rsl;
1484
Harald Welteae026692017-12-09 01:03:01 +01001485 /* Send CHAN RQD and wait for allocation; acknowledge it */
Philipp Maier9c60a622020-07-09 15:08:46 +02001486 var RslChannelNr chan_nr := f_chreq_act_ack(ra);
Harald Welteae026692017-12-09 01:03:01 +01001487
1488 /* expect BSC to disable the channel again if there's no RLL EST IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001489 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := T3101_MAX);
Harald Welteae026692017-12-09 01:03:01 +01001490
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001491 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001492}
1493
Philipp Maier9c60a622020-07-09 15:08:46 +02001494/* Normal variant */
1495testcase TC_chan_act_ack_noest() runs on test_CT {
Philipp Maieraf58db22020-08-12 17:24:40 +02001496 f_init(1);
Philipp Maier9c60a622020-07-09 15:08:46 +02001497 f_TC_chan_act_ack_noest();
1498}
1499
1500/* Emergency call variant */
1501testcase TC_chan_act_ack_noest_emerg() runs on test_CT {
1502 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
Philipp Maieraf58db22020-08-12 17:24:40 +02001503 f_init(1);
1504 f_vty_allow_emerg_bts(true, 0);
Philipp Maier9c60a622020-07-09 15:08:46 +02001505 f_TC_chan_act_ack_noest(ra := 'A5'O);
1506}
1507
Philipp Maier606f07d2020-08-12 17:21:58 +02001508/* Emergency call variant, but emergency calls are not allowed */
1509testcase TC_chan_rqd_emerg_deny() runs on test_CT {
1510 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
1511
1512 var RSL_Message rx_rsl;
1513 var GsmRrMessage rr;
1514
1515 f_init(1);
1516 f_vty_allow_emerg_bts(false, 0);
1517
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001518 IPA_RSL[0][0].clear;
1519 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier606f07d2020-08-12 17:21:58 +02001520
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001521 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Philipp Maier606f07d2020-08-12 17:21:58 +02001522 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
1523 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1524 setverdict(pass);
1525 } else {
1526 setverdict(fail, "immediate assignment not rejected");
1527 }
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01001528
1529 f_shutdown_helper();
Philipp Maier606f07d2020-08-12 17:21:58 +02001530}
1531
Harald Welteae026692017-12-09 01:03:01 +01001532/* Test behavior if MSC never answers to CR */
1533testcase TC_chan_act_ack_est_ind_noreply() runs on test_CT {
Harald Weltef77aef62018-01-28 15:35:42 +01001534 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
1535 var IpaStreamId sid := IPAC_PROTO_RSL_TRX0;
Harald Welteae026692017-12-09 01:03:01 +01001536 var RSL_Message rx_rsl;
Harald Weltef77aef62018-01-28 15:35:42 +01001537 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001538 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welteae026692017-12-09 01:03:01 +01001539
Harald Welte89d42e82017-12-17 16:42:41 +01001540 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001541
1542 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001543 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001544
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001545 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welteae026692017-12-09 01:03:01 +01001546
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001547 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload)));
Harald Welteae026692017-12-09 01:03:01 +01001548
1549 /* expect BSC to disable the channel again if there's no response from MSC */
Harald Weltef77aef62018-01-28 15:35:42 +01001550 /* MS waits 20s (T3210) at LU; 10s (T3230) at CM SERV REQ and 5s (T3220) AT detach */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001551 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001552 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001553}
1554
1555/* Test behavior if MSC answers with CREF to CR */
1556testcase TC_chan_act_ack_est_ind_refused() runs on test_CT {
1557 var BSSAP_N_CONNECT_ind rx_c_ind;
1558 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001559 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welteae026692017-12-09 01:03:01 +01001560
Harald Welte89d42e82017-12-17 16:42:41 +01001561 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001562
1563 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001564 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001565
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001566 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welteae026692017-12-09 01:03:01 +01001567
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001568 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Harald Welteae026692017-12-09 01:03:01 +01001569 BSSAP.send(ts_BSSAP_DISC_req(rx_c_ind.connectionId, 0));
1570
1571 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001572 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001573 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001574}
1575
Harald Welte618ef642017-12-14 14:58:20 +01001576/* CHAN RQD -> CHAN ACT -> CHAN ACT NACK -> RF CHAN REL */
1577testcase TC_chan_act_nack() runs on test_CT {
1578 var RSL_Message rx_rsl;
1579 var integer chact_nack;
1580
Harald Welte89d42e82017-12-17 16:42:41 +01001581 f_init(1);
Harald Welte618ef642017-12-14 14:58:20 +01001582
1583 chact_nack := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack");
1584
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001585 f_ipa_tx(ts_RSL_CHAN_RQD('33'O, 33));
1586 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Harald Welte618ef642017-12-14 14:58:20 +01001587 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1588
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001589 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte618ef642017-12-14 14:58:20 +01001590
1591 /* wait for some time to hope the NACK arrives before the CTRL GET below */
1592 f_sleep(0.5);
1593
1594 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack", chact_nack+1);
1595
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001596 f_shutdown_helper();
Harald Welte618ef642017-12-14 14:58:20 +01001597}
1598
Harald Welte799c97b2017-12-14 17:50:30 +01001599/* Test for channel exhaustion due to RACH overload */
1600testcase TC_chan_exhaustion() runs on test_CT {
1601 var ASP_RSL_Unitdata rsl_ud;
1602 var integer i;
1603 var integer chreq_total, chreq_nochan;
1604
Harald Welte89d42e82017-12-17 16:42:41 +01001605 f_init(1);
Harald Welte799c97b2017-12-14 17:50:30 +01001606
1607 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
1608 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
1609
Neels Hofmeyr85fa37f2021-10-06 13:50:38 +02001610 /* GSM 44.018 Table 9.1.8.2:
Pau Espin Pedrolfe200d72018-12-10 12:41:04 +01001611 * RA = '33'O -> Establishment cause = 0011xxxx (MS dual rate capable and asks for "TCH/H or TCH/F").
1612 * With current setup, expect 4xSDCCH + 4xTCH/F + 1xTCH/H to succeed */
Philipp Maiercb6cc482018-03-26 13:08:00 +02001613 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolfe200d72018-12-10 12:41:04 +01001614 var RslChannelNr chan_nr := f_chreq_act_ack('33'O, i);
Harald Welte799c97b2017-12-14 17:50:30 +01001615 }
1616
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001617 IPA_RSL[0][0].clear;
Harald Welte799c97b2017-12-14 17:50:30 +01001618
Harald Weltedd8cbf32018-01-28 12:07:52 +01001619 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001620 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
Harald Welte799c97b2017-12-14 17:50:30 +01001621
1622 /* now expect additional channel activations to fail */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001623 f_ipa_tx(ts_RSL_CHAN_RQD('42'O, 42));
Harald Welte799c97b2017-12-14 17:50:30 +01001624
1625 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001626 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV))) {
Harald Welte799c97b2017-12-14 17:50:30 +01001627 setverdict(fail, "Received CHAN ACT ACK without resources?!?");
1628 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001629 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) -> value rsl_ud {
Harald Welte799c97b2017-12-14 17:50:30 +01001630 var GsmRrMessage rr;
1631 /* match on IMM ASS REJ */
1632 rr := dec_GsmRrMessage(rsl_ud.rsl.ies[1].body.full_imm_ass_info.payload);
1633 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1634 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001635 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS+1);
Harald Welte799c97b2017-12-14 17:50:30 +01001636 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel",
1637 chreq_nochan+1);
1638 setverdict(pass);
1639 } else {
1640 repeat;
1641 }
1642 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001643 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte799c97b2017-12-14 17:50:30 +01001644 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001645 f_shutdown_helper();
Harald Welte799c97b2017-12-14 17:50:30 +01001646}
1647
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001648/* Test channel deactivation due to silence from MS */
1649testcase TC_chan_deact_silence() runs on test_CT {
1650 var RslChannelNr chan_nr;
1651
1652 f_init(1);
1653
1654 /* Request for a dedicated channel */
1655 chan_nr := f_chreq_act_ack('23'O);
1656
1657 /* Wait some time until the channel is released */
1658 f_sleep(2.0);
1659
1660 /* Expect CHANnel RELease */
1661 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001662 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001663 log("Received CHANnel RELease");
1664 setverdict(pass);
1665 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001666 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001667 /* See OS#3709, OsmoBSC should not send Immediate
1668 * Assignment Reject since a dedicated channel was
1669 * already allocated, and Immediate Assignment was
1670 * already sent. */
1671 setverdict(fail, "Unexpected Immediate Assignment!");
1672 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001673 [] IPA_RSL[0][0].receive {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001674 setverdict(fail, "Unexpected RSL message!");
1675 }
1676 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001677 f_shutdown_helper();
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001678}
1679
Harald Weltecfe2c962017-12-15 12:09:32 +01001680/***********************************************************************
1681 * Assignment Testing
1682 ***********************************************************************/
1683
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02001684/* Verify that the BSC refuses any BSSAP connection from the MSC (They are all BSC->MSC direction,
1685 * except for the inter-BSC handover, MT side) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001686testcase TC_outbound_connect(integer bssap_idx := 0) runs on test_CT {
Harald Welte89d42e82017-12-17 16:42:41 +01001687 f_init(1);
Harald Weltecfe2c962017-12-15 12:09:32 +01001688
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001689 BSSAP.send(ts_BSSAP_CONNECT_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
1690 2342, ts_BSSMAP_AssignmentReq));
Harald Weltecfe2c962017-12-15 12:09:32 +01001691 BSSAP.receive(tr_BSSAP_DISC_ind(2342, ?, ?));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001692 f_shutdown_helper();
Harald Weltecfe2c962017-12-15 12:09:32 +01001693}
1694
Harald Welte16a4adf2017-12-14 18:54:01 +01001695/* Test behavior if MSC answers with CREF to CR */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001696testcase TC_assignment_cic_only(integer bssap_idx := 0) runs on test_CT {
Harald Welte16a4adf2017-12-14 18:54:01 +01001697 var BSSAP_N_CONNECT_ind rx_c_ind;
1698 var RSL_Message rx_rsl;
1699 var DchanTuple dt;
1700
Harald Welte89d42e82017-12-17 16:42:41 +01001701 f_init(1);
Harald Welte16a4adf2017-12-14 18:54:01 +01001702
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001703 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001704 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte17b27da2018-05-25 20:33:53 +02001705 /* send assignment without AoIP IEs */
1706 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(ts_BSSMAP_IE_CIC(0, 1))));
1707 } else {
Pau Espin Pedrol35609792023-01-03 16:56:59 +01001708 /* Send assignment without CIC in IPA case */
Harald Welte17b27da2018-05-25 20:33:53 +02001709 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
1710 valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
1711 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(omit, tla)));
1712 }
Harald Welte16a4adf2017-12-14 18:54:01 +01001713 alt {
1714 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1715 setverdict(fail, "AoIP BSC cannot accept ASSIGNMENT without AoIP Transport IE");
1716 }
Harald Welte235ebf12017-12-15 14:18:16 +01001717 /* TODO: Actually expect GSM0808_CAUSE_REQ_A_IF_TYPE_NOT_SUPP */
Harald Welte16a4adf2017-12-14 18:54:01 +01001718 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1719 setverdict(pass);
1720 }
1721 [] BSSAP.receive { repeat; }
1722 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001723 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001724 f_shutdown_helper();
Harald Welte16a4adf2017-12-14 18:54:01 +01001725}
1726
Harald Welteed848512018-05-24 22:27:58 +02001727/* generate an assignment request for either AoIP or SCCPlite */
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001728function f_gen_ass_req(boolean osmux_enabled := false, integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4") return PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001729 var PDU_BSSAP ass_cmd;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001730 var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001731 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welteed848512018-05-24 22:27:58 +02001732 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001733 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001734 if (osmux_enabled) {
1735 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla, osmux_cid));
1736 } else {
1737 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla));
1738 }
Harald Welteed848512018-05-24 22:27:58 +02001739 } else {
1740 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrol096d73d2019-06-06 12:49:17 +02001741 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(cic, omit));
Harald Welteed848512018-05-24 22:27:58 +02001742 }
1743 return ass_cmd;
1744}
1745
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02001746function f_gen_handover_req(integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4",
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001747 template (value) BSSMAP_IE_CellIdentifier cell_id_source := ts_CellID_LAC_CI(1, 1),
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001748 template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit,
1749 template (omit) TestHdlrEncrParams enc := omit) return PDU_BSSAP {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001750 var PDU_BSSAP ho_req;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001751
1752 var BSSMAP_IE_EncryptionInformation encryptionInformation :=
1753 valueof(ts_BSSMAP_IE_EncrInfo('0000000000000000'O,'01'O));
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03001754 var template (omit) BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := omit;
1755 var template (omit) BSSMAP_IE_KC128 kc128 := omit;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001756 if (ispresent(enc)) {
1757 var TestHdlrEncrParams v_enc := valueof(enc);
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01001758 encryptionInformation := valueof(ts_BSSMAP_IE_EncrInfo(v_enc.enc_key, v_enc.enc_alg_permitted));
1759 if (ispresent(v_enc.enc_alg_chosen)) {
1760 chosenEncryptionAlgorithm := valueof(
1761 ts_BSSMAP_IE_ChosenEncryptionAlgorithm(int2oct(enum2int(
1762 f_cipher_mode_bssmap_to_rsl(v_enc.enc_alg_chosen)), 1)));
1763 }
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001764 if (ispresent(v_enc.enc_kc128)) {
1765 kc128 := ts_BSSMAP_IE_Kc128(v_enc.enc_kc128);
1766 }
1767 }
1768
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001769 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001770 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001771 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001772 ho_req := valueof(ts_BSSMAP_HandoverRequest(omit, tla,
1773 cell_id_source := cell_id_source,
1774 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001775 encryptionInformation := encryptionInformation,
1776 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
Neels Hofmeyr9fe13202022-03-04 00:05:43 +01001777 kC128 := kc128,
1778 /* on AoIP, allow "all" codecs (until we add more concise
1779 * tests) */
1780 codecList := ts_BSSMAP_IE_CodecList(
1781 {ts_CodecAMR_F, ts_CodecAMR_H,
1782 ts_CodecEFR, ts_CodecFR, ts_CodecHR})));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001783 } else {
1784 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001785 ho_req := valueof(ts_BSSMAP_HandoverRequest(cic, omit,
1786 cell_id_source := cell_id_source,
1787 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001788 encryptionInformation := encryptionInformation,
1789 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
1790 kC128 := kc128));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001791 }
1792 return ho_req;
1793}
1794
Harald Welteed848512018-05-24 22:27:58 +02001795/* generate an assignment complete template for either AoIP or SCCPlite */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001796function f_gen_exp_compl(integer bssap_idx := 0)
1797runs on MSC_ConnHdlr return template PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001798 var template PDU_BSSAP exp_compl;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001799 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001800 var template BSSMAP_IE_Osmo_OsmuxCID exp_osmux_cid := omit;
1801 if (g_pars.use_osmux_cn) {
1802 var template (present) INT1 exp_cid := ?;
1803 if (isbound(g_media.mgcp_conn[0].local_osmux_cid) and isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1804 exp_cid := (g_media.mgcp_conn[0].local_osmux_cid, g_media.mgcp_conn[1].local_osmux_cid);
1805 } else if (isbound(g_media.mgcp_conn[0].local_osmux_cid)) {
1806 exp_cid := g_media.mgcp_conn[0].local_osmux_cid;
1807 } else if (isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1808 exp_cid := g_media.mgcp_conn[1].local_osmux_cid;
1809 }
1810 exp_osmux_cid := tr_OsmuxCID(exp_cid);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001811 }
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001812 exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, exp_osmux_cid);
Harald Welteed848512018-05-24 22:27:58 +02001813 } else {
1814 /* CIC is optional "*" as the MSC allocated it */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001815 exp_compl := tr_BSSMAP_AssignmentComplete(*, omit, omit);
Harald Welteed848512018-05-24 22:27:58 +02001816 }
1817 return exp_compl;
1818}
1819
Harald Welte235ebf12017-12-15 14:18:16 +01001820/* Run everything required up to sending a caller-specified assignment command and expect response */
1821function f_assignment_exp(PDU_BSSAP ass_cmd, template PDU_BSSAP exp, charstring fail_text)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001822runs on test_CT return DchanTuple {
Harald Welte235ebf12017-12-15 14:18:16 +01001823 var BSSAP_N_CONNECT_ind rx_c_ind;
1824 var RSL_Message rx_rsl;
1825 var DchanTuple dt;
1826
Harald Welte89d42e82017-12-17 16:42:41 +01001827 f_init(1);
Harald Welte235ebf12017-12-15 14:18:16 +01001828
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001829 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte235ebf12017-12-15 14:18:16 +01001830 /* send assignment without AoIP IEs */
1831 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
1832 alt {
1833 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1834 if (ischosen(exp.pdu.bssmap.assignmentComplete)) {
1835 setverdict(pass);
1836 } else {
1837 setverdict(fail, fail_text);
1838 }
1839 }
1840 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1841 if (ischosen(exp.pdu.bssmap.assignmentFailure)) {
1842 setverdict(pass);
1843 } else {
1844 setverdict(fail, fail_text);
1845 }
1846 }
1847 [] BSSAP.receive { repeat; }
1848 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001849 return dt;
Harald Welte235ebf12017-12-15 14:18:16 +01001850}
Oliver Smithdd002752023-02-21 13:35:00 +01001851
Oliver Smith545492d2023-04-19 13:05:30 +02001852private function f_tc_assignment_csd(charstring data_rate_str, OCT1 data_rate, boolean transp := true) runs on MSC_ConnHdlr {
Oliver Smithdd002752023-02-21 13:35:00 +01001853 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welteed848512018-05-24 22:27:58 +02001854 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Oliver Smithbc392a82023-04-17 14:06:42 +02001855 var SDP_FIELD_PayloadType pt_csd := PT_CSD;
Oliver Smithdd002752023-02-21 13:35:00 +01001856
Harald Welte235ebf12017-12-15 14:18:16 +01001857 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smithdd002752023-02-21 13:35:00 +01001858 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecCSData}));
1859
Oliver Smith545492d2023-04-19 13:05:30 +02001860 /* Non-transparent service (3GPP TS 48.008 § 3.2.2.11, oct 5, bit 7) */
1861 if (not transp) {
1862 data_rate := data_rate or4b '40'O;
1863 }
1864
Oliver Smithcb617912023-04-18 11:29:10 +02001865 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := data_rate;
1866
1867 log("-----------------------------------------------");
1868 log("Assignment req with data rate: " & data_rate_str);
1869 log("-----------------------------------------------");
Oliver Smithdd002752023-02-21 13:35:00 +01001870
1871 f_establish_fully(ass_cmd, exp_compl);
Oliver Smithbc392a82023-04-17 14:06:42 +02001872
1873 if (g_media.bts.rtp_pt != enum2int(pt_csd)) {
1874 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("unexpected RTP payload type: ", g_media.bts.rtp_pt));
1875 }
1876
Oliver Smithdd002752023-02-21 13:35:00 +01001877 f_perform_clear();
Oliver Smithace447a2023-05-08 14:07:21 +02001878 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Oliver Smithdd002752023-02-21 13:35:00 +01001879}
Oliver Smithcb617912023-04-18 11:29:10 +02001880private function f_tc_assignment_csd_all(charstring id) runs on MSC_ConnHdlr {
1881 /* Data rates that require multi-slot HSCSD assignment are not tested
Oliver Smith545492d2023-04-19 13:05:30 +02001882 * on purpose (not supported): T_32k0, T_28k8, NT_43k5, NT_29k0 */
Oliver Smithcb617912023-04-18 11:29:10 +02001883 f_tc_assignment_csd("T_14k4", GSM0808_DATA_RATE_TRANSP_14k4);
1884 f_tc_assignment_csd("T_9k6", GSM0808_DATA_RATE_TRANSP_9k6);
1885 f_tc_assignment_csd("T_4k8", GSM0808_DATA_RATE_TRANSP_4k8);
1886 f_tc_assignment_csd("T_2k4", GSM0808_DATA_RATE_TRANSP_2k4);
1887 f_tc_assignment_csd("T_1k2", GSM0808_DATA_RATE_TRANSP_1k2);
1888 f_tc_assignment_csd("T_600", GSM0808_DATA_RATE_TRANSP_600);
1889 f_tc_assignment_csd("T_1200_75", GSM0808_DATA_RATE_TRANSP_1200_75);
Oliver Smith545492d2023-04-19 13:05:30 +02001890
1891 f_tc_assignment_csd("NT_12000_6000", GSM0808_DATA_RATE_NON_TRANSP_12000_6000, false);
1892 f_tc_assignment_csd("NT_14k5", GSM0808_DATA_RATE_NON_TRANSP_14k5, false);
1893 f_tc_assignment_csd("NT_12k0", GSM0808_DATA_RATE_NON_TRANSP_12k0, false);
1894 f_tc_assignment_csd("NT_6k0", GSM0808_DATA_RATE_NON_TRANSP_6k0, false);
Oliver Smithcb617912023-04-18 11:29:10 +02001895}
Oliver Smithdd002752023-02-21 13:35:00 +01001896testcase TC_assignment_csd() runs on test_CT {
1897 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.10.0 */
1898 var MSC_ConnHdlr vc_conn;
1899 var TestHdlrParams pars := f_gen_test_hdlr_pars();
1900 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
1901
Oliver Smith545492d2023-04-19 13:05:30 +02001902 f_init(1, true, guard_timeout := 120.0);
Oliver Smithdd002752023-02-21 13:35:00 +01001903 f_sleep(1.0);
Oliver Smithcb617912023-04-18 11:29:10 +02001904 vc_conn := f_start_handler(refers(f_tc_assignment_csd_all), pars);
Oliver Smithdd002752023-02-21 13:35:00 +01001905 vc_conn.done;
1906 } else {
1907 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
1908 var PDU_BSSAP ass_cmd := f_gen_ass_req();
1909 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
1910 //exp_fail.pdu.bssmap.assignmentFailure.cause.causeValue := int2bit(enum2int(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL), 7);
1911 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for CSD");
1912 f_perform_clear_test_ct(dt);
1913 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001914 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001915}
1916
1917testcase TC_assignment_ctm() runs on test_CT {
1918 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001919 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001920 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
1921 //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 +01001922 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
1923 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001924 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001925}
1926
Harald Welte4003d112017-12-09 22:35:39 +01001927type record DchanTuple {
1928 integer sccp_conn_id,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001929 RslChannelNr rsl_chan_nr,
1930 BtsTrxIdx idx
Harald Weltea5d2ab22017-12-09 14:21:42 +01001931}
1932
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +02001933type record of DchanTuple DchanTuples;
1934
Harald Welted6939652017-12-13 21:02:46 +01001935/* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001936private function f_chreq_act_ack(OCT1 ra := '23'O,
1937 GsmFrameNumber fn := 23,
1938 BtsTrxIdx idx := {0, 0})
Harald Welted6939652017-12-13 21:02:46 +01001939runs on test_CT return RslChannelNr {
1940 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001941 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
1942 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Harald Welted6939652017-12-13 21:02:46 +01001943 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001944 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10), idx);
1945 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Harald Welted6939652017-12-13 21:02:46 +01001946 return chan_nr;
1947}
1948
Harald Welte4003d112017-12-09 22:35:39 +01001949/* helper function to establish a dedicated channel via BTS and MSC */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001950function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1951 BtsTrxIdx idx := {0, 0})
Harald Welte4003d112017-12-09 22:35:39 +01001952runs on test_CT return DchanTuple {
1953 var BSSAP_N_CONNECT_ind rx_c_ind;
Harald Welte4003d112017-12-09 22:35:39 +01001954 var DchanTuple dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001955
Harald Welte4003d112017-12-09 22:35:39 +01001956 /* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001957 dt.rsl_chan_nr := f_chreq_act_ack(ra, fn, idx);
Harald Welte4003d112017-12-09 22:35:39 +01001958
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001959 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 +01001960
1961 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1962 dt.sccp_conn_id := rx_c_ind.connectionId;
1963 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1964
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001965 dt.idx := idx;
Harald Welte4003d112017-12-09 22:35:39 +01001966 return dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001967}
1968
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001969/* 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 +06001970function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1971 BtsTrxIdx idx := {0, 0})
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001972runs on test_CT return DchanTuple {
1973 var BSSAP_N_CONNECT_ind rx_c_ind;
1974 var DchanTuple dt;
1975
1976 /* Send CHAN RQD */
1977 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001978 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001979
1980 /* The dyn TS first deactivates PDCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001981 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 +02001982 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001983 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001984
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001985 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001986 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1987
1988 /* Now activates the signalling channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001989 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10), idx);
1990 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001991
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001992 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 +02001993
1994 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1995 dt.sccp_conn_id := rx_c_ind.connectionId;
1996 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1997
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001998 dt.idx := idx;
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001999 return dt;
2000}
2001
Harald Welte641fcbe2018-06-14 10:58:35 +02002002/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002003private function f_exp_chan_rel_and_clear(DchanTuple dt)
2004runs on test_CT {
Harald Welte641fcbe2018-06-14 10:58:35 +02002005 var RSL_Message rx_rsl;
2006 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002007 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 +02002008 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002009 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), dt.idx);
Harald Welte641fcbe2018-06-14 10:58:35 +02002010
2011 /* expect Clear Complete from BSC */
2012 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2013
2014 /* MSC disconnects as instructed. */
2015 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2016}
2017
Harald Welte4003d112017-12-09 22:35:39 +01002018/* Test behavior of channel release after unilateral RLL REL IND (DISC from MS) */
2019testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002020 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002021 var DchanTuple dt;
Harald Welte96c94412017-12-09 03:12:45 +01002022
Harald Welte89d42e82017-12-17 16:42:41 +01002023 f_init(1);
Harald Welte96c94412017-12-09 03:12:45 +01002024
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002025 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002026
2027 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002028 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Harald Welte4003d112017-12-09 22:35:39 +01002029
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002030 /* expect Clear Request on MSC side */
2031 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2032
2033 /* Instruct BSC to clear channel */
2034 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2035 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2036
Harald Welte4003d112017-12-09 22:35:39 +01002037 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002038 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr27f64362018-03-12 01:44:00 +01002039
2040 /* wait for SCCP emulation to do its job */
2041 f_sleep(1.0);
Harald Welte4003d112017-12-09 22:35:39 +01002042
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002043 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002044}
2045
2046/* Test behavior of channel release after CONN FAIL IND from BTS */
2047testcase TC_chan_rel_conn_fail() runs on test_CT {
2048 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002049 var DchanTuple dt;
2050
Harald Welte89d42e82017-12-17 16:42:41 +01002051 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002052
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002053 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002054
Vadim Yanitskiy01d0a902022-12-14 22:41:42 +07002055 /* Sending CONN FAIL IND immediately may trigger a race condition.
2056 * Give the BSC some time to process a new SCCP connection (OS#5823). */
2057 f_sleep(0.2);
2058
Harald Welte4003d112017-12-09 22:35:39 +01002059 /* simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002060 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte4003d112017-12-09 22:35:39 +01002061 /* TODO: different cause values? */
2062
Harald Welte4003d112017-12-09 22:35:39 +01002063 /* expect Clear Request from BSC */
2064 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
2065
2066 /* Instruct BSC to clear channel */
2067 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2068 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2069
Harald Welte6ff76ea2018-01-28 13:08:01 +01002070 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002071 f_exp_chan_rel_and_clear(dt);
Harald Welte4003d112017-12-09 22:35:39 +01002072
2073 /* wait for SCCP emulation to do its job */
2074 f_sleep(1.0);
2075
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002076 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002077}
2078
Harald Welte99f3ca02018-06-14 13:40:29 +02002079/* Test behavior of early CONN FAIL IND from BTS (before EST IND!) */
2080/* See also https://www.osmocom.org/issues/3182 */
2081testcase TC_early_conn_fail() runs on test_CT {
2082 var RSL_Message rx_rsl;
2083 var DchanTuple dt;
2084
2085 f_init(1);
2086
2087 /* BTS->BSC: Send CHAN RQD and wait for allocation; acknowledge it */
Harald Weltec46ea3c2020-10-10 18:46:12 +02002088 dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_ra_cs(), 23);
Harald Welte99f3ca02018-06-14 13:40:29 +02002089
2090 /* BTS->BSC: simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002091 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002092
2093 /* BTS->BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002094 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002095
2096 /* BTS<-BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002097 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002098
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002099 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002100}
2101
2102/* Test behavior of late CONN FAIL IND from BTS (ater REL IND!) */
2103/* See also https://www.osmocom.org/issues/3182 */
2104testcase TC_late_conn_fail() runs on test_CT {
2105 var RSL_Message rx_rsl;
2106 var DchanTuple dt;
2107
2108 f_init(1);
2109
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002110 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99f3ca02018-06-14 13:40:29 +02002111
2112 /* BSC<-MSC: Instruct BSC to clear connection */
2113 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(0)));
2114
2115 /* BTS->BSC: expect BSC to deactivate SACCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002116 rx_rsl := f_exp_ipa_rx(tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002117
2118 /* BTS->BSC: simulate a late CONN FAIL IND from BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002119 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002120
2121 /* BTS<-BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002122 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002123 /* BTS->BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002124 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002125
2126 /* BSC->MSC: expect Clear Complete from BSC */
2127 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2128
2129 /* BSC<-MSC: MSC disconnects as requested. */
2130 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2131
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002132 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002133}
2134
Oliver Smithaf03bef2021-08-24 15:34:51 +02002135private function f_TC_stats_conn_fail(charstring id) runs on MSC_ConnHdlr {
2136 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
2137 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2138
2139 f_statsd_reset();
2140
Oliver Smith15890b42023-03-08 14:12:28 +01002141 /* Establish SDCCH (invalid DataIndicator for exp_fail) */
Oliver Smithaf03bef2021-08-24 15:34:51 +02002142 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
Oliver Smith15890b42023-03-08 14:12:28 +01002143 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := 'ff'O;
Oliver Smithaf03bef2021-08-24 15:34:51 +02002144 f_establish_fully(ass_cmd, exp_fail);
2145
2146 /* Expect stats to be 0 */
2147 var StatsDExpects expect := {
2148 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
2149 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
2150 };
2151 f_statsd_expect(expect);
2152
2153 /* Simulate CONN FAIL IND on SDCCH */
2154 RSL.send(ts_ASP_RSL_UD(
2155 ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
2156 IPAC_PROTO_RSL_TRX0));
2157
Neels Hofmeyr58be48a2021-09-07 18:39:21 +02002158 f_sleep(1.0);
2159
Oliver Smithaf03bef2021-08-24 15:34:51 +02002160 /* Expect stats to be 1 */
2161 expect := {
2162 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
2163 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
2164 };
2165 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002166 BSSAP.receive(tr_BSSMAP_ClearRequest);
2167 f_perform_clear();
Oliver Smithaf03bef2021-08-24 15:34:51 +02002168}
2169testcase TC_stats_conn_fail() runs on test_CT {
2170 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2171 var MSC_ConnHdlr vc_conn;
2172
2173 f_init(1, true);
2174 f_sleep(1.0);
2175
2176 vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
2177 vc_conn.done;
2178
2179 f_shutdown_helper();
2180}
2181
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002182function f_expect_chan_rel(RslChannelNr rsl_chan_nr,
2183 BtsTrxIdx idx := {0, 0},
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002184 boolean expect_deact_sacch := true,
2185 boolean expect_rr_chan_rel := true,
2186 boolean expect_rll_rel_req := true,
Harald Welte99787102019-02-04 10:41:36 +01002187 boolean handle_rll_rel := true,
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002188 template CellSelIndValue expect_cells := omit,
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002189 template (present) RR_Cause expect_rr_cause := ?
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002190 ) runs on test_CT {
Harald Welte91d54a52018-01-28 15:35:07 +01002191
2192 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002193 var boolean got_deact_sacch := false;
2194 var boolean got_rr_chan_rel := false;
2195 var boolean got_rll_rel_req := false;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002196 var ASP_RSL_Unitdata ud;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002197 var RSL_IE_Body l3_ie;
2198 var PDU_ML3_NW_MS l3;
2199 var RR_Cause got_cause;
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002200 log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
2201 " expect_rll_rel_req=", expect_rll_rel_req);
Harald Welte91d54a52018-01-28 15:35:07 +01002202 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002203 [] 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 +01002204 got_deact_sacch := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002205 repeat;
2206 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002207 [] 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 +01002208 got_rr_chan_rel := true;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002209
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002210 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2211 setverdict(fail, "cannot find L3");
2212 mtc.stop;
2213 }
2214 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2215
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002216 if (not istemplatekind(expect_cells, "omit")) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002217 var CellSelIndValue cells := dec_CellSelIndValue(
2218 l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
2219
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002220 log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
2221 if (match(cells, expect_cells)) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002222 setverdict(pass);
2223 } else {
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002224 log("EXPECTED CELLS: ", expect_cells);
2225 setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002226 }
2227 }
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002228
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002229 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2230 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2231 if (match(got_cause, expect_rr_cause)) {
2232 setverdict(pass);
2233 } else {
2234 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2235 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002236 }
Harald Welte99787102019-02-04 10:41:36 +01002237 repeat;
2238 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002239 [] 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 +01002240 got_rll_rel_req := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002241 /* FIXME: Why are we getting this for LinkID SACCH? */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002242 if (handle_rll_rel) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002243 f_ipa_tx(ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002244 }
Harald Welte91d54a52018-01-28 15:35:07 +01002245 repeat;
2246 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002247 [] 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 +01002248 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002249 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
Harald Welte91d54a52018-01-28 15:35:07 +01002250 }
2251 /* ignore any user data */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002252 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002253 repeat;
2254 }
2255 }
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002256
2257 log("f_expect_chan_rel() summary: got_deact_sacch=", got_deact_sacch, " got_rr_chan_rel=", got_rr_chan_rel,
2258 " got_rll_rel_req=", got_rll_rel_req);
2259
2260 if (expect_deact_sacch != got_deact_sacch) {
2261 setverdict(fail, "f_expect_chan_rel(): expect_deact_sacch=", expect_deact_sacch, " got_deact_sacch=", got_deact_sacch);
2262 }
2263 if (expect_rr_chan_rel != got_rr_chan_rel) {
2264 setverdict(fail, "f_expect_chan_rel(): expect_rr_chan_rel=", expect_rr_chan_rel, " got_rr_chan_rel=", got_rr_chan_rel);
2265 }
2266 if (expect_rll_rel_req != got_rll_rel_req) {
2267 setverdict(fail, "f_expect_chan_rel(): expect_rll_rel_req=", expect_rll_rel_req, " got_rll_rel_req=", got_rll_rel_req);
2268 }
Harald Welte91d54a52018-01-28 15:35:07 +01002269}
2270
Harald Welte4003d112017-12-09 22:35:39 +01002271/* Test behavior of channel release after hard Clear Command from MSC */
2272testcase TC_chan_rel_hard_clear() runs on test_CT {
2273 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002274 var DchanTuple dt;
Harald Welte4003d112017-12-09 22:35:39 +01002275
Harald Welte89d42e82017-12-17 16:42:41 +01002276 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002277
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002278 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002279
2280 /* Instruct BSC to clear channel */
2281 var BssmapCause cause := 0;
2282 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2283
2284 /* expect Clear Complete from BSC on A */
2285 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2286 /* release the SCCP connection */
2287 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2288 }
2289
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002290 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002291 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002292}
2293
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002294function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
2295 var BSSAP_N_DATA_ind rx_di;
2296 var DchanTuple dt;
2297
2298 f_init(1);
2299
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002300 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002301 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2302 /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
2303 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
2304
2305 /* Instruct BSC to clear channel */
2306 var BssmapCause cause := 0;
2307 if (tx_csfb_ind) {
2308 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2309 } else {
2310 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2311 }
2312
2313 /* expect Clear Complete from BSC on A */
2314 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2315 /* release the SCCP connection */
2316 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2317 }
2318
2319 /* 1 neighbor is added by default in osmo-bts.cfg and
2320 SystemInformationConfig_default, use that: */
2321 var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
2322
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002323 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 +02002324 f_shutdown_helper();
2325}
2326
2327/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
2328 from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
2329 PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2330 EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
2331 Indicator or not shouldn't matter at all. */
2332testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
2333 f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
2334}
2335
2336/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
2337 MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
2338 Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2339 EUTRAN neighbor list sent later on by BSC in RR Channel. */
2340testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
2341 f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
2342}
2343
2344/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
2345 MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
2346 Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
2347 CSFB Indicator should not be used anymore, and hence, there should be no
2348 EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
2349 Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
Harald Welte99787102019-02-04 10:41:36 +01002350testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
2351 var BSSAP_N_DATA_ind rx_di;
2352 var DchanTuple dt;
2353
2354 f_init(1);
2355
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002356 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99787102019-02-04 10:41:36 +01002357
2358 /* Instruct BSC to clear channel */
2359 var BssmapCause cause := 0;
2360 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2361
2362 /* expect Clear Complete from BSC on A */
2363 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2364 /* release the SCCP connection */
2365 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2366 }
2367
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002368 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002369 f_shutdown_helper();
Harald Welte99787102019-02-04 10:41:36 +01002370}
2371
Harald Welted8c36cd2017-12-09 23:05:31 +01002372/* Test behavior of channel release after hard RLSD from MSC */
2373testcase TC_chan_rel_hard_rlsd() runs on test_CT {
Harald Welted8c36cd2017-12-09 23:05:31 +01002374 var DchanTuple dt;
Harald Welted8c36cd2017-12-09 23:05:31 +01002375
Harald Welte89d42e82017-12-17 16:42:41 +01002376 f_init(1);
Harald Welted8c36cd2017-12-09 23:05:31 +01002377
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002378 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welted8c36cd2017-12-09 23:05:31 +01002379
2380 /* release the SCCP connection */
2381 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2382
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002383 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002384 f_shutdown_helper();
Harald Welted8c36cd2017-12-09 23:05:31 +01002385}
2386
Harald Welte550daf92018-06-11 19:22:13 +02002387/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
2388testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
2389 var DchanTuple dt;
2390
2391 f_init(1);
2392
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002393 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte550daf92018-06-11 19:22:13 +02002394
2395 /* release the SCCP connection */
2396 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2397
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002398 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002399 f_shutdown_helper();
Harald Welte550daf92018-06-11 19:22:13 +02002400}
2401
Harald Welte85804d42017-12-10 14:11:58 +01002402/* Test behavior of channel release after BSSMAP RESET from MSC */
2403testcase TC_chan_rel_a_reset() runs on test_CT {
Harald Welte85804d42017-12-10 14:11:58 +01002404 var DchanTuple dt;
Harald Welte85804d42017-12-10 14:11:58 +01002405
Harald Welte89d42e82017-12-17 16:42:41 +01002406 f_init(1);
Harald Welte85804d42017-12-10 14:11:58 +01002407
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002408 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte85804d42017-12-10 14:11:58 +01002409
2410 /* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002411 IPA_RSL[0][0].clear;
Harald Welte85804d42017-12-10 14:11:58 +01002412
2413 /* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002414 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 +01002415 interleave {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002416 [] 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 +01002417 [] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
2418 }
2419
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002420 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002421 f_shutdown_helper();
Harald Welte85804d42017-12-10 14:11:58 +01002422}
2423
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002424/* Verify T(iar) triggers and releases the channel */
2425testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
2426 var DchanTuple dt;
2427
2428 /* Set T(iar) in BSC low enough that it will trigger before other side
2429 has time to keep alive with a T(ias). Keep recommended ratio of
2430 T(iar) >= T(ias)*2 */
2431 g_bsc_sccp_timer_ias := 2;
2432 g_bsc_sccp_timer_iar := 5;
2433
2434 f_init(1);
2435
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002436 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002437 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002438 f_shutdown_helper();
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002439}
2440
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002441private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause,
2442 template (present) RR_Cause expect_rr_cause)
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002443runs on test_CT
2444{
2445 var DchanTuple dt;
2446
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002447 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002448 var BssmapCause cause := 0;
2449 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
2450 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2451 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2452 }
2453
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002454 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 +02002455}
2456
2457/* Test that Clear Command cause codes affect the RR Channel Release cause code */
2458testcase TC_chan_rel_rr_cause() runs on test_CT {
2459 f_init(1);
2460
2461 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
2462 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
2463 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
2464 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
2465 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
2466 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
Vadim Yanitskiye18aebb2021-01-03 13:10:43 +01002467
2468 f_shutdown_helper();
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002469}
2470
Harald Welte5cd20ed2017-12-13 21:03:20 +01002471/* Test behavior if RSL EST IND for non-active channel */
2472testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
2473 timer T := 2.0;
2474
Harald Welte89d42e82017-12-17 16:42:41 +01002475 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002476
Harald Welte5cd20ed2017-12-13 21:03:20 +01002477 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002478 var octetstring l3_payload := gen_l3_valid_payload();
2479 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002480
2481 T.start;
2482 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002483 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002484 setverdict(fail, "MSC received COMPL L3 for non-active lchan");
2485 }
2486 [] BSSAP.receive {}
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002487 [] IPA_RSL[0][0].receive {}
Harald Welte5cd20ed2017-12-13 21:03:20 +01002488 [] T.timeout {}
2489 }
2490
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002491 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002492}
2493
2494/* Test behavior if RSL EST IND for invalid SAPI */
2495testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
2496 var RslChannelNr chan_nr;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002497 var octetstring l3_payload;
Harald Welte5cd20ed2017-12-13 21:03:20 +01002498
Harald Welte89d42e82017-12-17 16:42:41 +01002499 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002500
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002501 chan_nr := f_chreq_act_ack();
2502 l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002503
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002504 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002505
2506 timer T := 2.0;
2507 T.start;
2508 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002509 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002510 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
2511 }
2512 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002513 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002514 [] T.timeout {}
2515 }
2516
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002517 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002518}
2519
2520/* Test behavior if RSL EST IND for invalid SAPI */
2521testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
2522 timer T := 2.0;
2523
Harald Welte89d42e82017-12-17 16:42:41 +01002524 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002525
2526 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002527 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002528
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002529 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002530
2531 T.start;
2532 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002533 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002534 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
2535 }
2536 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002537 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002538 [] T.timeout {}
2539 }
2540
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002541 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002542}
2543
2544/* Test behavior if RSL EST IND for invalid SACCH */
2545testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
2546 timer T := 2.0;
2547
Harald Welte89d42e82017-12-17 16:42:41 +01002548 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002549
2550 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002551 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002552
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002553 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002554
2555 T.start;
2556 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002557 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002558 setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
2559 }
2560 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002561 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002562 [] T.timeout {}
2563 }
2564
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002565 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002566}
2567
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002568/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
2569private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
2570 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
2571 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2572
2573 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
2574 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
2575
2576 f_establish_fully(ass_cmd, exp_compl);
2577
2578 /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
2579 RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
2580 /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
2581 BSSAP.receive(PDU_BSSAP:{
2582 discriminator := '1'B,
2583 spare := '0000000'B,
2584 dlci := 'C3'O,
2585 lengthIndicator := ?,
2586 pdu := { dtap := '0904'O }
2587 });
2588
2589 /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
2590 for (var integer i := 0; i < 32; i := i + 1) {
2591 var octetstring l3 := '09'O & f_rnd_octstring(14);
2592 var template (value) RslLinkId link_id;
2593 var template (value) OCT1 dlci;
2594
2595 if (i mod 2 == 0) {
2596 /* SAPI0 on FACCH or SDCCH */
2597 link_id := ts_RslLinkID_DCCH(0);
2598 dlci := '80'O;
2599 } else {
2600 /* SAPI3 on SACCH */
2601 link_id := ts_RslLinkID_SACCH(3);
2602 dlci := 'C3'O;
2603 }
2604
2605 /* Send MO message: RSL -> BSSAP */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002606 f_mo_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002607 /* Send MT message: BSSAP -> RSL */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002608 f_mt_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002609 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002610 f_perform_clear();
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002611}
2612testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
2613 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2614 var MSC_ConnHdlr vc_conn;
2615
2616 f_init(1, true);
2617 f_sleep(1.0);
2618
2619 vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
2620 vc_conn.done;
2621
2622 f_shutdown_helper();
2623}
2624
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002625private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002626 template (present) myBSSMAP_Cause cause := ?,
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002627 template (present) BIT2 cc := ?,
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002628 float T_val := 2.0)
2629runs on test_CT {
2630 var BSSAP_N_DATA_ind rx_di;
2631 timer T;
2632
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002633 var template (present) BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
2634 var template (present) PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002635
2636 T.start(T_val);
2637 alt {
2638 [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
2639 var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
2640 if (not match(rx_cause, tr_cause)) {
2641 setverdict(fail, "Rx unexpected Cause IE: ",
2642 rx_cause, " vs expected ", tr_cause);
2643 }
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002644
2645 /* Who ever on the earth decided to define this field as two separate bits?!? */
2646 var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
2647 & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
2648 if (not match(rx_cc, cc)) {
2649 setverdict(fail, "Rx unexpected Control Channel type: ",
2650 rx_cc, " vs expected ", cc);
2651 }
2652
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002653 setverdict(pass);
2654 }
2655 [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
2656 setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
2657 }
2658 [] T.timeout {
2659 setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
2660 }
2661 }
2662}
2663
2664/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
2665testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002666 var RSL_Message rx_rsl;
2667 var DchanTuple dt;
2668
2669 f_init(1);
2670
2671 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002672 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002673
2674 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002675 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 +07002676 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002677 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 +07002678
2679 /* MS sends unexpected RELease INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002680 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002681 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2682 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
2683
2684 /* Clean up the connection */
2685 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002686 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002687
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002688 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002689}
2690
2691/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
2692testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002693 var RSL_Message rx_rsl;
2694 var DchanTuple dt;
2695
2696 f_init(1);
2697
2698 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002699 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002700
2701 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002702 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 +07002703 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002704 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 +07002705
2706 /* BTS sends unexpected ERROR INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002707 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002708 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2709 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
2710
2711 /* Clean up the connection */
2712 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002713 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002714
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002715 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002716}
2717
2718/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
2719testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002720 var RSL_Message rx_rsl;
2721 var DchanTuple dt;
2722
2723 f_init(1);
2724
2725 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002726 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002727
2728 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002729 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 +07002730 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002731 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 +07002732
2733 /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
2734 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
2735
2736 /* Clean up the connection */
2737 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002738 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002739
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002740 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002741}
2742
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002743/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
2744testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002745 var RSL_Message rx_rsl;
2746 var DchanTuple dt;
2747
2748 f_init(1);
2749
2750 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002751 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002752
2753 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002754 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 +07002755 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002756 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 +07002757
2758 /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002759 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Pau Espin Pedrol121f27f2022-01-12 12:02:10 +01002760 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, '10'B);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002761
2762 /* Clean up the connection */
2763 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002764 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002765
2766 f_shutdown_helper();
2767}
2768
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002769testcase TC_si_default() runs on test_CT {
2770 f_init(0);
2771 f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002772 f_shutdown_helper();
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002773}
Harald Welte4003d112017-12-09 22:35:39 +01002774
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002775/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
2776 * the entire value range. This function provides the same EARFCN numbers for the same earfcn_index */
2777private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uint16_t
2778{
2779 select (earfcn_index) {
2780 case (0) {
2781 /* E-ARFCN 111 is already added in the osmo-bsc.cfg */
2782 return 111;
2783 }
2784 case (1) {
2785 return 1;
2786 }
2787 case (2) {
2788 return 0;
2789 }
2790 case (3) {
2791 return 65535;
2792 }
2793 case else {
2794 return 23 * (earfcn_index - 3);
2795 }
2796 }
2797}
2798
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002799function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
2800 template CellSelIndValue expect_cells := omit) runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002801
2802 f_init(0);
2803
2804 /* E-ARFCN 111 is already added in the osmo-bsc.cfg, so only add more arfcns if total_earfcns > 1 */
2805 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002806 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2807 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002808 }
2809
2810 f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
2811
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002812 if (not istemplatekind(expect_cells, "omit")) {
2813 /* Also check that RR Channel Release contains these EARFCNs.
2814 * (copied code from TC_chan_rel_hard_clear_csfb) */
2815 var BSSAP_N_DATA_ind rx_di;
2816 var DchanTuple dt;
2817
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002818 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrold0046312021-04-19 16:35:58 +02002819 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2820 * yet when generating the EUTRAN neigh list in RR CHannel Release) */
2821 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002822
2823 /* Instruct BSC to clear channel */
2824 var BssmapCause cause := 0;
2825 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2826
2827 /* expect Clear Complete from BSC on A */
2828 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2829 /* release the SCCP connection */
2830 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2831 }
2832
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002833 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := expect_cells);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002834 }
2835
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002836 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002837 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 +02002838 }
2839}
2840
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002841private function f_tr_si2quater_earfcns(integer count) return template SI2quaterRestOctetsList
2842{
2843 var template SI2quaterRestOctetsList si2quater := {};
2844 var integer si2quater_count := (count + 2) / 3;
2845
2846 for (var integer i := 0; i < count; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002847 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002848 var integer index := i / 3;
2849 var integer earfcn_index := i mod 3;
2850 if (index >= lengthof(si2quater)) {
2851 si2quater[index] := tr_SI2quaterRestOctets_EUTRAN(index := index, count := si2quater_count - 1);
2852 }
2853 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);
2854 }
2855
2856 return si2quater;
2857}
2858
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002859private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
2860{
2861 var template CellSelIndValue_EUTRAN_Descrs cells := {};
2862
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002863 /* the lte neighbors must match the config & vty to pass this test */
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002864 for (var integer i := 0; i < count; i := i + 1) {
2865 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002866 cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002867 }
2868
2869 return tr_CellSelIndValue_EUTRAN(cells);
2870}
2871
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002872private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
2873{
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002874 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrol8ab62e42020-12-18 16:19:11 +01002875 sic.si2quater := f_tr_si2quater_earfcns(n);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002876 var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
2877 f_test_si2quater(n, sic, cells);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002878}
2879
2880testcase TC_si2quater_2_earfcns() runs on test_CT {
2881 f_tc_si2quater_n_earfcns(2);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002882 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002883}
2884
2885testcase TC_si2quater_3_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002886 f_tc_si2quater_n_earfcns(3);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002887 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002888}
2889
2890testcase TC_si2quater_4_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002891 f_tc_si2quater_n_earfcns(4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002892 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002893}
2894
2895testcase TC_si2quater_5_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002896 f_tc_si2quater_n_earfcns(5);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002897 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002898}
2899
2900testcase TC_si2quater_6_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002901 f_tc_si2quater_n_earfcns(6);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002902 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002903}
2904
2905testcase TC_si2quater_12_earfcns() runs on test_CT {
2906 f_tc_si2quater_n_earfcns(12);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002907 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002908}
2909
2910testcase TC_si2quater_23_earfcns() runs on test_CT {
2911 f_tc_si2quater_n_earfcns(23);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002912 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002913}
2914
2915testcase TC_si2quater_32_earfcns() runs on test_CT {
2916 f_tc_si2quater_n_earfcns(32);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002917 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002918}
2919
2920testcase TC_si2quater_33_earfcns() runs on test_CT {
2921 f_tc_si2quater_n_earfcns(33);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002922 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002923}
2924
2925testcase TC_si2quater_42_earfcns() runs on test_CT {
2926 f_tc_si2quater_n_earfcns(42);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002927 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002928}
2929
2930testcase TC_si2quater_48_earfcns() runs on test_CT {
2931 f_tc_si2quater_n_earfcns(48);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002932 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002933}
2934
2935/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
2936 * 48 EARFCNs. */
2937testcase TC_si2quater_49_earfcns() runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002938 var template SystemInformationConfig sic := SystemInformationConfig_default;
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002939 sic.si2quater := f_tr_si2quater_earfcns(48); /* 48, not 49! */
2940 f_init(0);
2941
2942 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002943 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2944 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002945 }
2946
2947 /* The 49th EARFCN no longer fits, expect VTY error */
2948 f_vty_enter_cfg_bts(BSCVTY, 0);
2949 var charstring vty_error;
2950 vty_error := f_vty_transceive_ret(BSCVTY,
2951 "si2quater neighbor-list add earfcn 70 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3")
2952 f_vty_transceive(BSCVTY, "end");
2953
2954 if (f_strstr(vty_error, "Unable to add ARFCN 70") >= 0) {
2955 log("Got expected VTY error: ", vty_error);
2956 setverdict(pass);
2957 } else {
2958 setverdict(fail, "Expected the 49th EUTRAN ARFCN to be rejected by vty config, got: ", vty_error);
2959 }
2960
2961 f_init_bts_and_check_sysinfo(0, expect_si := sic);
2962
2963 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002964 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 +02002965 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002966 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002967}
2968
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002969private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
2970{
2971 var uint8_t count := 0;
2972 for (var integer i := 5; i < 16; i := i + 1) {
2973 if (acc[i] == '0'B) { /* the list marks barred, we count allowed */
2974 count := count + 1;
2975 }
2976 }
2977 return count;
2978}
2979
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002980private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return SystemInformationType1
2981{
2982 var ASP_RSL_Unitdata rx_rsl_ud;
2983 var SystemInformationType1 last_si1;
2984
2985 timer T := 30.0;
2986 T.start;
2987 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002988 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
2989 tr_RSL_BCCH_INFO,
2990 tr_RSL_NO_SACCH_FILL,
2991 tr_RSL_SACCH_FILL))) -> value rx_rsl_ud {
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002992 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
2993 if (g_system_information[rsl_idx].si1 == omit) {
2994 repeat;
2995 }
2996 last_si1 := g_system_information[rsl_idx].si1;
2997 g_system_information[rsl_idx].si1 := omit;
2998 T.stop;
2999 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003000 [] IPA_RSL[rsl_idx][0].receive { repeat; }
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003001 [] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
3002 }
3003 return last_si1;
3004}
3005
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003006/* verify ACC rotate feature */
3007testcase TC_si_acc_rotate() runs on test_CT {
3008 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003009 var SystemInformationType1 last_si1;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003010 var AccessControlClass acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003011 var uint8_t count;
3012 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3013
3014 f_init(0, guard_timeout := 60.0);
3015
3016 f_bts_0_cfg(BSCVTY, {"rach access-control-class 5 barred",
3017 "access-control-class-rotate 3",
3018 "access-control-class-rotate-quantum 1"});
3019
3020 /* Init and get first sysinfo */
3021 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3022
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003023 for (var integer i:= 0; i < 20; i := i + 1) {
3024 last_si1 := f_recv_next_si1(0);
3025 acc := last_si1.rach_control.acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003026 count := f_acc09_count_allowed(acc);
3027 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3028
3029 if (count != 3) {
3030 log("RSL: EXPECTED SI ACC len=3");
3031 setverdict(fail, "received SI does not match expectations");
3032 break;
3033 }
3034
3035 for (var integer j := 0; j < 10; j := j + 1) {
3036 if (acc[16 - 1 - j] == '0'B) { /* the list marks barred, we count allowed */
3037 times_allowed[j] := times_allowed[j] + 1;
3038 }
3039 }
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003040 }
3041
3042 for (var integer j := 0; j < 10; j := j + 1) {
3043 log("ACC", j, " allowed ", times_allowed[j], " times" );
3044 if (j != 5 and times_allowed[j] < 3) {
3045 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " < 1 times");
3046 } else if (j == 5 and times_allowed[j] > 0) {
3047 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " > 0 times");
3048 }
3049 }
3050
3051 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3052 "rach access-control-class 5 allowed"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003053 f_shutdown_helper();
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02003054}
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02003055
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003056/* verify ACC startup ramp+rotate feature */
3057testcase TC_si_acc_ramp_rotate() runs on test_CT {
3058 var template SystemInformationConfig sic := SystemInformationConfig_default;
3059 var SystemInformationType1 last_si1;
3060 var AccessControlClass acc;
3061 var ASP_RSL_Unitdata rx_rsl_ud;
3062 var uint8_t count;
3063 var uint8_t prev_count;
3064 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3065
3066 f_init(0, guard_timeout := 80.0);
3067
3068 f_bts_0_cfg(BSCVTY, {"rach access-control-class 4 barred",
3069 "access-control-class-rotate 0",
3070 "access-control-class-rotate-quantum 1",
3071 "access-control-class-ramping",
3072 "access-control-class-ramping-step-interval 5",
3073 "access-control-class-ramping-step-size 5"});
3074
3075 /* Init and get first sysinfo */
3076 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3077 last_si1 := g_system_information[0].si1;
3078 acc := last_si1.rach_control.acc;
3079 count := f_acc09_count_allowed(acc);
3080 /* Adm subset size was set to 0 above, so wait until all ACC are barred */
3081 while (count > 0) {
3082 last_si1 := f_recv_next_si1(0);
3083 acc := last_si1.rach_control.acc;
3084 count := f_acc09_count_allowed(acc);
3085 log("RSL: wait len()=0: GOT SI1 ACC len=", count, ": ", acc);
3086 }
3087
3088 /* Increase adm subset size, we should see ramping start up */
3089 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10"});
3090 prev_count := 0;
3091 while (true) {
3092 last_si1 := f_recv_next_si1(0);
3093 acc := last_si1.rach_control.acc;
3094 count := f_acc09_count_allowed(acc);
3095 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3096
3097 if (prev_count > count) {
3098 setverdict(fail, "ACC allowed count dropped while expecting grow: ", prev_count, " -> ", count);
3099 break;
3100 }
3101
3102 if (count == 9) {
3103 break; /* Maximum reached (10 - 1 perm barred), done here */
3104 }
3105
3106 prev_count := count;
3107 }
3108
3109 setverdict(pass);
3110
3111 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3112 "rach access-control-class 4 allowed",
3113 "no access-control-class-ramping"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003114 f_shutdown_helper();
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003115}
3116
Harald Welte4003d112017-12-09 22:35:39 +01003117testcase TC_ctrl_msc_connection_status() runs on test_CT {
3118 var charstring ctrl_resp;
3119
Harald Welte89d42e82017-12-17 16:42:41 +01003120 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003121
3122 /* See https://osmocom.org/issues/2729 */
3123 f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003124 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01003125}
3126
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003127testcase TC_ctrl_msc0_connection_status() runs on test_CT {
3128 var charstring ctrl_resp;
3129
3130 f_init(1);
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003131
3132 f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003133 f_shutdown_helper();
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003134}
3135
Neels Hofmeyr0bc470d2021-08-21 13:37:13 +02003136/* Verify correct stats on the number of configured and connected MSCs */
3137private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
3138 g_pars := f_gen_test_hdlr_pars();
3139 var StatsDExpects expect := {
3140 { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
3141 { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
3142 };
3143 f_statsd_expect(expect);
3144}
3145
3146private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
3147{
3148 var MSC_ConnHdlr vc_conn;
3149
3150 f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
3151 f_sleep(1.0);
3152 vc_conn := f_start_handler(tc_fn);
3153 vc_conn.done;
3154
3155 /* Also verify stat exposed on CTRL interface */
3156 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
3157 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
3158
3159 f_shutdown_helper();
3160}
3161
3162/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
3163private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
3164 f_tc_stat_num_msc_connected_msc_connhdlr(1);
3165}
3166testcase TC_stat_num_msc_connected_1() runs on test_CT {
3167 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
3168}
3169
3170/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
3171private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
3172 f_tc_stat_num_msc_connected_msc_connhdlr(2);
3173}
3174testcase TC_stat_num_msc_connected_2() runs on test_CT {
3175 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
3176}
3177
3178/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
3179private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
3180 f_tc_stat_num_msc_connected_msc_connhdlr(3);
3181}
3182testcase TC_stat_num_msc_connected_3() runs on test_CT {
3183 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
3184}
3185
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003186/* Verify correct stats on the number of configured and connected MSCs */
3187private 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 +06003188 var integer num_trx_connected := 0;
3189 var integer num_trx_total := 0;
3190
3191 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3192 var integer trx_num := c_BtsParams[i].trx_num;
3193 num_trx_total := num_trx_total + trx_num;
3194 if (i < expect_num_bts_connected) {
3195 num_trx_connected := num_trx_connected + trx_num;
3196 }
3197 }
3198
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003199 var StatsDExpects expect := {
3200 { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
3201 { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3202 { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003203 { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := num_trx_connected, max := num_trx_connected },
3204 { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := num_trx_total, max := num_trx_total }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003205 };
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003206
3207 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003208 f_statsd_expect(expect);
3209}
3210
3211private 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 +06003212 var integer num_trx_connected := 0;
3213 var integer num_trx_total := 0;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003214 var MSC_ConnHdlr vc_conn;
3215
3216 f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
3217 f_sleep(1.0);
3218 vc_conn := f_start_handler(tc_fn);
3219 vc_conn.done;
3220
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003221 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3222 var integer trx_num := c_BtsParams[i].trx_num;
3223 num_trx_total := num_trx_total + trx_num;
3224 if (i < nr_bts) {
3225 num_trx_connected := num_trx_connected + trx_num;
3226 }
3227 }
3228
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003229 /* Also verify stat exposed on CTRL interface */
3230 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
3231 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 +06003232 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(num_trx_connected));
3233 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 +02003234
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003235 /* Verify rf_states exposed on CTRL interface */
3236 var charstring expect_net_rf_states := "";
3237 for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003238 var charstring expect_bts_rf_states := "";
3239
3240 for (var integer j := 0; j < c_BtsParams[i].trx_num; j := j + 1) {
3241 expect_bts_rf_states := expect_bts_rf_states &
3242 int2str(i) & "," & int2str(j) & ",";
3243 if (i < NUM_BTS) {
3244 /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
3245 expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
3246 } else {
3247 /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
3248 expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
3249 }
3250 /* The RF policy is still global in osmo-bsc, i.e. always "on" */
3251 expect_bts_rf_states := expect_bts_rf_states & "on,";
3252 if (i < nr_bts) {
3253 /* For BTS where RSL is connected, the RSL state will be "up" */
3254 expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
3255 } else {
3256 expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
3257 }
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003258 }
3259
3260 f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
3261 expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
3262 }
3263 f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
3264
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003265 f_shutdown_helper();
3266}
3267
3268/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
3269private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
3270 f_tc_stat_num_bts_connected_msc_connhdlr(1);
3271}
3272testcase TC_stat_num_bts_connected_1() runs on test_CT {
3273 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
3274}
3275
3276/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
3277private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
3278 f_tc_stat_num_bts_connected_msc_connhdlr(2);
3279}
3280testcase TC_stat_num_bts_connected_2() runs on test_CT {
3281 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
3282}
3283
3284/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
3285private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
3286 f_tc_stat_num_bts_connected_msc_connhdlr(3);
3287}
3288testcase TC_stat_num_bts_connected_3() runs on test_CT {
3289 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
3290}
3291
Harald Welte4003d112017-12-09 22:35:39 +01003292testcase TC_ctrl() runs on test_CT {
3293 var charstring ctrl_resp;
3294
Harald Welte89d42e82017-12-17 16:42:41 +01003295 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003296
3297 /* all below values must match the osmo-bsc.cfg config file used */
3298
Harald Welte6a129692018-03-17 17:30:14 +01003299 f_ctrl_get_exp(IPA_CTRL, "mcc", "001");
3300 f_ctrl_get_exp(IPA_CTRL, "mnc", "01");
Oliver Smith75aa0202019-08-19 14:17:50 +02003301 f_ctrl_get_exp(IPA_CTRL, "number-of-bts", "4");
Harald Welte4003d112017-12-09 22:35:39 +01003302
3303 var integer bts_nr := 0;
3304 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "location-area-code", "1");
3305 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "cell-identity", "0");
3306 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "oml-connection-state", "connected");
3307 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "gprs-mode", "gprs");
3308 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "rf_state", "operational,unlocked,on");
3309 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "arfcn", "871");
3310 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "max-power-reduction", "20");
3311
3312 var integer uptime := str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime"));
3313 f_sleep(2.0);
3314 if (str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime")) < uptime+1) {
3315 setverdict(fail, "oml-uptime not incrementing as expected");
3316 }
3317 /* TODO: Disconnect RSL, imply that OML is disconnected and check for uptime zero? */
3318
3319 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
3320
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003321 f_shutdown_helper();
Harald Welte96c94412017-12-09 03:12:45 +01003322}
3323
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003324/* Verify that Upon receival of SET "location", BSC forwards a TRAP
3325 "location-state" over the SCCPlite IPA conn */
3326testcase TC_ctrl_location() runs on test_CT {
3327 var MSC_ConnHdlr vc_conn;
3328 var integer bts_nr := 0;
3329
3330 f_init(1, true);
3331 f_sleep(1.0);
3332
3333 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234567,fix3d,0.340000,0.560000,0.780000");
3334 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3335 "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
3336
3337 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "1");
3338 f_sleep(2.0);
3339
3340 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234888,fix3d,0.350000,0.570000,0.790000");
3341 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3342 "1234888,fix3d,0.350000,0.570000,0.790000,operational,locked,off,001,01");
3343
3344 /* should match the one from config */
3345 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
3346
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003347 f_shutdown_helper();
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003348}
3349
Harald Welte6f521d82017-12-11 19:52:02 +01003350
3351/***********************************************************************
3352 * Paging Testing
3353 ***********************************************************************/
3354
3355type record Cell_Identity {
3356 GsmMcc mcc,
3357 GsmMnc mnc,
3358 GsmLac lac,
3359 GsmCellId ci
3360};
Harald Welte24135bd2018-03-17 19:27:53 +01003361private const Cell_Identity cid := { '001'H, '01'H, 1, 0 };
Stefan Sperling049a86e2018-03-20 15:51:00 +01003362private const Cell_Identity unknown_cid := { '678'H, 'f90'H, 1, 0 };
Harald Welte6f521d82017-12-11 19:52:02 +01003363
Harald Welte5d1a2202017-12-13 19:51:29 +01003364type set of integer BtsIdList;
3365
3366private function f_bts_in_list(integer bts_id, BtsIdList bts_ids) return boolean {
3367 for (var integer j := 0; j < sizeof(bts_ids); j := j + 1) {
3368 if (bts_id == bts_ids[j]) {
3369 return true;
3370 }
3371 }
3372 return false;
3373}
Harald Welte6f521d82017-12-11 19:52:02 +01003374
3375/* core paging test helper function; used by most paging test cases */
3376private function f_pageing_helper(hexstring imsi,
3377 template BSSMAP_FIELD_CellIdentificationList cid_list,
Harald Welte5d1a2202017-12-13 19:51:29 +01003378 BtsIdList bts_ids := { 0 },
Harald Welte6f521d82017-12-11 19:52:02 +01003379 template RSL_ChanNeeded rsl_chneed := omit,
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003380 template (omit) OCT4 tmsi := omit) runs on test_CT
Harald Welte6f521d82017-12-11 19:52:02 +01003381{
3382 var template BSSMAP_IE_ChannelNeeded bssmap_chneed;
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003383 var template MobileIdentityV mi;
Harald Welte6f521d82017-12-11 19:52:02 +01003384 var RSL_Message rx_rsl;
3385 var integer paging_group := hex2int(imsi[lengthof(imsi)-1]);
Harald Welte5d1a2202017-12-13 19:51:29 +01003386 var integer i;
Harald Welte6f521d82017-12-11 19:52:02 +01003387
3388 f_init();
Harald Welte6f521d82017-12-11 19:52:02 +01003389
3390 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Harald Weltec3068592018-03-17 19:55:31 +01003391 for (i := 0; i < NUM_BTS; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003392 IPA_RSL[i][0].clear;
Harald Welte5d1a2202017-12-13 19:51:29 +01003393 }
Harald Welte6f521d82017-12-11 19:52:02 +01003394
3395 if (isvalue(rsl_chneed)) {
3396 /* The values of 08.08 3.2.2.36 and 08.58 9.3.40 are luckily identical */
3397 bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
3398 } else {
3399 bssmap_chneed := omit;
3400 }
3401
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003402 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
3403 ts_BSSMAP_Paging(imsi, cid_list, tmsi, bssmap_chneed)));
Harald Welte6f521d82017-12-11 19:52:02 +01003404
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003405 if (not istemplatekind(tmsi, "omit")) {
3406 mi := t_MI_TMSI(tmsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003407 } else {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003408 mi := tr_MI_IMSI(imsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003409 }
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003410
Harald Welte5d1a2202017-12-13 19:51:29 +01003411 for (i := 0; i < sizeof(bts_ids); i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003412 rx_rsl := f_exp_ipa_rx(tr_RSL_PAGING_CMD(mi), idx := {bts_ids[i], 0});
Harald Welte5d1a2202017-12-13 19:51:29 +01003413 /* check channel type, paging group */
3414 if (rx_rsl.ies[1].body.paging_group != paging_group) {
3415 setverdict(fail, "Paging for wrong paging group");
3416 }
3417 if (ispresent(rsl_chneed) and
3418 rx_rsl.ies[3].body.chan_needed.chan_needed != valueof(rsl_chneed)) {
3419 setverdict(fail, "RSL Channel Needed != BSSMAP Channel Needed");
3420 }
Harald Welte6f521d82017-12-11 19:52:02 +01003421 }
Harald Welte2fccd982018-01-31 15:48:19 +01003422 f_sleep(2.0);
Harald Welte5d1a2202017-12-13 19:51:29 +01003423 /* do a quick check on all not-included BTSs if they received paging */
3424 for (i := 0; i < NUM_BTS; i := i + 1) {
3425 timer T := 0.1;
3426 if (f_bts_in_list(i, bts_ids)) {
3427 continue;
3428 }
3429 T.start;
3430 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003431 [] IPA_RSL[i][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003432 setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
3433 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003434 [] IPA_RSL[i][0].receive { repeat; }
Harald Welte5d1a2202017-12-13 19:51:29 +01003435 [] T.timeout { }
3436 }
Harald Welte6f521d82017-12-11 19:52:02 +01003437 }
3438
3439 setverdict(pass);
3440}
3441
Harald Welte5d1a2202017-12-13 19:51:29 +01003442const BtsIdList c_BtsId_all := { 0, 1, 2 };
Harald Welte751d3eb2018-01-31 15:51:06 +01003443const BtsIdList c_BtsId_none := { };
Harald Welte5d1a2202017-12-13 19:51:29 +01003444const BtsIdList c_BtsId_LAC1 := { 0, 1 };
3445const BtsIdList c_BtsId_LAC2 := { 2 };
3446
Harald Welte6f521d82017-12-11 19:52:02 +01003447/* PAGING by IMSI + TMSI */
3448testcase TC_paging_imsi_nochan() runs on test_CT {
3449 var BSSMAP_FIELD_CellIdentificationList cid_list;
3450 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Philipp Maier8c04b0a2018-02-23 13:48:48 +01003451 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, omit);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003452 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003453}
3454
3455/* PAGING by IMSI + TMSI */
3456testcase TC_paging_tmsi_nochan() runs on test_CT {
3457 var BSSMAP_FIELD_CellIdentificationList cid_list;
3458 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003459 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, 'A1B2C301'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003460 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003461}
3462
3463/* Paging with different "channel needed' values */
3464testcase TC_paging_tmsi_any() runs on test_CT {
3465 var BSSMAP_FIELD_CellIdentificationList cid_list;
3466 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003467 f_pageing_helper('001010100000002'H, cid_list, c_BtsId_all, RSL_CHANNEED_ANY, 'A1B2C302'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003468 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003469}
3470testcase TC_paging_tmsi_sdcch() runs on test_CT {
3471 var BSSMAP_FIELD_CellIdentificationList cid_list;
3472 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003473 f_pageing_helper('001010100000003'H, cid_list, c_BtsId_all, RSL_CHANNEED_SDCCH, 'A1B2C303'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003474 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003475}
3476testcase TC_paging_tmsi_tch_f() runs on test_CT {
3477 var BSSMAP_FIELD_CellIdentificationList cid_list;
3478 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003479 f_pageing_helper('001010000000004'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_F, 'A1B2C304'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003480 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003481}
3482testcase TC_paging_tmsi_tch_hf() runs on test_CT {
3483 var BSSMAP_FIELD_CellIdentificationList cid_list;
3484 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003485 f_pageing_helper('001010000000005'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_ForH, 'A1B2C305'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003486 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003487}
3488
3489/* Paging by CGI */
3490testcase TC_paging_imsi_nochan_cgi() runs on test_CT {
3491 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3492 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(cid.mcc, cid.mnc, cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003493 f_pageing_helper('001010000000006'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003494 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003495}
3496
3497/* Paging by LAC+CI */
3498testcase TC_paging_imsi_nochan_lac_ci() runs on test_CT {
3499 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3500 cid_list := { cIl_LAC_CI := { ts_BSSMAP_CI_LAC_CI(cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003501 f_pageing_helper('001010000000007'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003502 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003503}
3504
3505/* Paging by CI */
3506testcase TC_paging_imsi_nochan_ci() runs on test_CT {
3507 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3508 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003509 f_pageing_helper('001010000000008'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003510 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003511}
3512
3513/* Paging by LAI */
3514testcase TC_paging_imsi_nochan_lai() runs on test_CT {
3515 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3516 cid_list := { cIl_LAI := { ts_BSSMAP_CI_LAI(cid.mcc, cid.mnc, cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003517 f_pageing_helper('001010000000009'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003518 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003519}
3520
3521/* Paging by LAC */
3522testcase TC_paging_imsi_nochan_lac() runs on test_CT {
3523 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3524 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003525 f_pageing_helper('001010000000010'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003526 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003527}
3528
3529/* Paging by "all in BSS" */
3530testcase TC_paging_imsi_nochan_all() runs on test_CT {
3531 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3532 cid_list := { cIl_allInBSS := ''O };
Harald Welte5d1a2202017-12-13 19:51:29 +01003533 f_pageing_helper('001010000000011'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003534 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003535}
3536
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003537/* Paging by PLMN+LAC+RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003538testcase TC_paging_imsi_nochan_plmn_lac_rnc() runs on test_CT {
3539 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3540 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 +01003541 f_pageing_helper('001010000000012'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003542 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003543}
Harald Welte6f521d82017-12-11 19:52:02 +01003544
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003545/* Paging by RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003546testcase TC_paging_imsi_nochan_rnc() runs on test_CT {
3547 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3548 cid_list := { cIl_RNC := { int2oct(13, 2) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003549 f_pageing_helper('001010000000013'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003550 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003551}
3552
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003553/* Paging by LAC+RNC; We do not implement; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003554testcase TC_paging_imsi_nochan_lac_rnc() runs on test_CT {
3555 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3556 cid_list := { cIl_LAC_RNC := { ts_BSSMAP_CI_LAC_RNC(cid.lac, 14) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003557 f_pageing_helper('001010000000014'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003558 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003559}
3560
Harald Welte6f521d82017-12-11 19:52:02 +01003561/* Paging on multiple cells (multiple entries in list): Verify all of them page */
Harald Welte751d3eb2018-01-31 15:51:06 +01003562testcase TC_paging_imsi_nochan_lacs() runs on test_CT {
3563 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3564 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(1), ts_BSSMAP_CI_LAC(2) } };
3565 f_pageing_helper('001010000000015'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003566 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003567}
3568
3569/* Paging on empty list: Verify none of them page */
3570testcase TC_paging_imsi_nochan_lacs_empty() runs on test_CT {
3571 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3572 cid_list := { cIl_LAC := { } };
3573 f_pageing_helper('001010000000016'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003574 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003575}
3576
Stefan Sperling049a86e2018-03-20 15:51:00 +01003577/* Paging by CGI with unknown MCC/MNC: Verify nothing is paged. */
3578testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
3579 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3580 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(unknown_cid.mcc, unknown_cid.mnc, unknown_cid.lac, unknown_cid.ci) } };
3581 f_pageing_helper('001010000000006'H, cid_list, c_BtsId_none);
3582 f_shutdown_helper();
3583}
3584
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +01003585/* Send paging response containing invalid (wrongly formatted) MobileIdentity IE. */
3586testcase TC_paging_imsi_nochan_ci_resp_invalid_mi() runs on test_CT {
3587 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3588 var BSSAP_N_CONNECT_ind rx_c_ind;
3589 var DchanTuple dt;
3590 var octetstring rr_pag_resp := '06270003535992617965720000'O;
3591 /* { 06 27 } is { GSM48_PDISC_RR, GSM48_MT_RR_PAG_RESP }
3592 * see 3GPP TS 44.018, table 9.1.25.1
3593 * { 00 } or { 01 } is CKSN + Spare Half Octet, not important
3594 * { 03 53 59 92 } is Mobile Station Classmark
3595 * { 61 79 65 72 00 00 } is the invalid Mobile Identity IE (3GPP TS 24.008, 10.5.1.4),
3596 * Length is 0x61 (97 in decimal).
3597 */
3598
3599 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
3600 f_pageing_helper('001010000000008'H, cid_list, { 0 });
3601
3602 /* Send CHAN RQD and wait for allocation; acknowledge it */
3603 dt.rsl_chan_nr := f_chreq_act_ack();
3604 dt.idx := {0, 0};
3605
3606 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
3607 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), rr_pag_resp));
3608
3609 /* Expevct a CR with a matching Paging response on the A-Interface */
3610 timer T := 5.0;
3611 T.start;
3612 alt {
3613 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
3614 setverdict(pass);
3615 dt.sccp_conn_id := rx_c_ind.connectionId;
3616 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
3617 }
3618 [] BSSAP.receive {
3619 setverdict(fail, "Received unexpected message on A-Interface!");
3620 }
3621 [] T.timeout {
3622 setverdict(fail, "Received nothing on A-Interface!");
3623 }
3624 }
3625
3626 f_perform_clear_test_ct(dt);
3627 f_shutdown_helper();
3628}
3629
Harald Welte6f521d82017-12-11 19:52:02 +01003630/* Verify paging retransmission interval + count */
3631/* Verify paging stops after channel establishment */
Harald Welte6f521d82017-12-11 19:52:02 +01003632/* Test behavior under paging overload */
Harald Welteae026692017-12-09 01:03:01 +01003633
Harald Weltee65d40e2017-12-13 00:09:06 +01003634/* Verify PCH load */
3635testcase TC_paging_imsi_load() runs on test_CT {
3636 var BSSMAP_FIELD_CellIdentificationList cid_list;
3637 timer T := 4.0;
Harald Welte2caa1062018-03-17 18:19:05 +01003638 timer T_retrans := 1.0;
Harald Weltee65d40e2017-12-13 00:09:06 +01003639 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003640 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Weltee65d40e2017-12-13 00:09:06 +01003641
3642 /* tell BSC there is no paging space anymore */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003643 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte3b57ab52018-03-17 18:01:10 +01003644 f_sleep(0.2);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003645 IPA_RSL[0][0].clear;
Harald Weltee65d40e2017-12-13 00:09:06 +01003646
3647 /* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
3648 * there would be 8 retransmissions during 4 seconds */
3649 T.start;
Harald Welte2caa1062018-03-17 18:19:05 +01003650 T_retrans.start;
Harald Weltee65d40e2017-12-13 00:09:06 +01003651 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003652 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Weltee65d40e2017-12-13 00:09:06 +01003653 setverdict(fail, "Received PAGING after LOAD_IND(0)");
Daniel Willmannafce8662018-07-06 23:11:32 +02003654 mtc.stop;
Harald Weltee65d40e2017-12-13 00:09:06 +01003655 }
Harald Welte2caa1062018-03-17 18:19:05 +01003656 [] T_retrans.timeout {
3657 /* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003658 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte2caa1062018-03-17 18:19:05 +01003659 T_retrans.start;
3660 repeat;
3661 }
Harald Weltee65d40e2017-12-13 00:09:06 +01003662 [] T.timeout {
3663 setverdict(pass);
3664 }
3665 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003666
3667 f_shutdown_helper();
Harald Weltee65d40e2017-12-13 00:09:06 +01003668}
3669
Harald Welte235ebf12017-12-15 14:18:16 +01003670/* Verify Paging Counter */
Harald Welte1ff69992017-12-14 12:31:17 +01003671testcase TC_paging_counter() runs on test_CT {
3672 var BSSMAP_FIELD_CellIdentificationList cid_list;
3673 timer T := 4.0;
3674 var integer i;
3675 var integer paging_attempted_bsc;
3676 var integer paging_attempted_bts[NUM_BTS];
Oliver Smith8b343d32021-11-26 13:01:42 +01003677 var integer paging_expired_bsc;
Harald Welte1ff69992017-12-14 12:31:17 +01003678 var integer paging_expired_bts[NUM_BTS];
3679 cid_list := valueof(ts_BSSMAP_CIL_noCell);
3680
3681 f_init();
3682
3683 /* read counters before paging */
3684 paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003685 paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
Harald Welte1ff69992017-12-14 12:31:17 +01003686 for (i := 0; i < NUM_BTS; i := i+1) {
3687 paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
3688 paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
3689 }
3690
3691 f_pageing_helper('001230000000001'H, cid_list, c_BtsId_all);
3692
3693 /* expect the attempted pages on BSC and each BTSs to have incremented by one */
3694 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", paging_attempted_bsc+1);
3695 for (i := 0; i < NUM_BTS; i := i+1) {
3696 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted",
3697 paging_attempted_bts[i]+1);
3698 }
3699
3700 /* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
3701 f_sleep(12.0);
Pau Espin Pedrol4e431832023-02-08 12:43:47 +01003702 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
Harald Welte1ff69992017-12-14 12:31:17 +01003703 for (i := 0; i < NUM_BTS; i := i+1) {
3704 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
3705 paging_expired_bts[i]+1);
3706 }
Harald Welte1ff69992017-12-14 12:31:17 +01003707
Philipp Maier282ca4b2018-02-27 17:17:00 +01003708 f_shutdown_helper();
Harald Welte1ff69992017-12-14 12:31:17 +01003709}
3710
3711
Harald Welte10985002017-12-12 09:29:15 +01003712/* Verify paging stops after A-RESET */
3713testcase TC_paging_imsi_a_reset() runs on test_CT {
3714 var BSSMAP_FIELD_CellIdentificationList cid_list;
3715 timer T := 3.0;
3716 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003717 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Welte10985002017-12-12 09:29:15 +01003718
3719 /* Perform a BSSMAP Reset and wait for ACK */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003720 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 +01003721 alt {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003722 [] 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 +01003723 [] BSSAP.receive { repeat; }
3724 }
3725
Daniel Willmanncbef3982018-07-30 09:22:40 +02003726 /* Wait to avoid a possible race condition if a paging message is
3727 * received right before the reset ACK. */
3728 f_sleep(0.2);
3729
Harald Welte10985002017-12-12 09:29:15 +01003730 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Philipp Maier1e6b4422018-02-23 14:02:13 +01003731 for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003732 IPA_RSL[i][0].clear;
Philipp Maier1e6b4422018-02-23 14:02:13 +01003733 }
Harald Welte10985002017-12-12 09:29:15 +01003734
3735 /* Wait for 3 seconds if any more PAGING CMD are received on RSL */
3736 T.start;
3737 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003738 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte10985002017-12-12 09:29:15 +01003739 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003740 mtc.stop;
Harald Welte10985002017-12-12 09:29:15 +01003741 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003742 [] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003743 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003744 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003745 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003746 [] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003747 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003748 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003749 }
Harald Welte10985002017-12-12 09:29:15 +01003750 [] T.timeout {
3751 setverdict(pass);
3752 }
3753 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003754
3755 f_shutdown_helper();
Harald Welte10985002017-12-12 09:29:15 +01003756}
Harald Welteae026692017-12-09 01:03:01 +01003757
Philipp Maierf45824a2019-08-14 14:44:10 +02003758/* Verify how we handle unsolicited Paging Response. In case of an unsolicit
3759 * paging response we can not know which MSC is in charge, so we will blindly
3760 * pick the first configured MSC. This behavior is required in order to make
3761 * MT-CSFB calls working because in those cases the BSC can not know that the
3762 * MSC has already paged the subscriver via SGs. So any MT-CSFB call will look
3763 * like an unsolicited Paging Response to the MSC.
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003764 */
3765testcase TC_paging_resp_unsol() runs on test_CT {
3766
3767 f_init(1);
Philipp Maierf45824a2019-08-14 14:44:10 +02003768 timer T := 5.0;
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003769
3770 var BSSAP_N_CONNECT_ind rx_c_ind;
3771 var DchanTuple dt;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02003772 var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010008880018'H)));
Philipp Maierf45824a2019-08-14 14:44:10 +02003773 var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003774
3775 /* Send CHAN RQD and wait for allocation; acknowledge it */
3776 dt.rsl_chan_nr := f_chreq_act_ack();
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003777 dt.idx := {0, 0};
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003778
3779 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
Pau Espin Pedrole8a51012023-01-03 11:59:59 +01003780 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 +01003781
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003782
Philipp Maierf45824a2019-08-14 14:44:10 +02003783 /* Expevct a CR with a matching Paging response on the A-Interface */
3784 T.start;
3785 alt {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003786 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
Philipp Maierf45824a2019-08-14 14:44:10 +02003787 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003788 dt.sccp_conn_id := rx_c_ind.connectionId;
3789 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
Philipp Maierf45824a2019-08-14 14:44:10 +02003790 }
3791 [] BSSAP.receive {
3792 setverdict(fail, "Received unexpected message on A-Interface!");
3793 }
3794 [] T.timeout {
3795 setverdict(fail, "Received nothing on A-Interface!");
3796 }
3797 }
3798
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003799 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003800 f_shutdown_helper();
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003801}
3802
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003803/* Verify BSC can schedule N paging requests under one minute if BTS buffer is good enough */
3804function f_TC_paging_Nreq(integer num_subscribers, boolean send_pag_load_ind) runs on test_CT {
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003805 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003806 var Hexstrings imsis := {};
3807 var Booleans rx_paging_done := {};
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003808 var integer rx_paging_num := 0;
3809 var integer i;
3810 timer T_rx := 60.0;
3811 timer T_load_ind := 1.0;
3812
3813 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003814 imsis := imsis & {f_gen_imsi(i)};
3815 rx_paging_done := rx_paging_done & { false };
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003816 }
3817
3818 f_init(1, guard_timeout := 100.0);
3819
3820 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003821 IPA_RSL[0][0].clear;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003822 if (send_pag_load_ind) {
3823 /* Tell there's plenty of space at the BTS (UINT16_MAX): */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003824 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(65535));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003825 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003826
3827 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003828 /* Page on LAC-CI of BTS0: */
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003829 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 +02003830 ts_BSSMAP_Paging(imsis[i], valueof(ts_BSSMAP_CIL_LAC_CI({ts_BSSMAP_CI_LAC_CI(1, 0)})),
3831 omit, omit)));
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003832 }
3833
3834 T_rx.start;
3835 T_load_ind.start;
3836 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003837 [] 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 +02003838 var hexstring imsi := rx_rsl_ud.rsl.ies[2].body.ms_identity.mobileIdentityV.oddEvenInd_identity.imsi.digits;
3839 var hexstring imsi_suffix := substr(imsi, lengthof(imsi)-6, 6);
3840 var charstring imsi_str := hex2str(imsi_suffix);
3841 var integer imsi_idx := str2int(imsi_str);
3842 if (rx_paging_done[imsi_idx] == false) {
3843 rx_paging_done[imsi_idx] := true;
3844 rx_paging_num := rx_paging_num + 1;
Pau Espin Pedrolef7ef632022-04-25 13:34:57 +02003845 } else {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003846 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 +02003847 mtc.stop;
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003848 }
3849 if (rx_paging_num < num_subscribers) {
3850 repeat;
3851 }
3852 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003853 [] IPA_RSL[0][0].receive { repeat; }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003854 [] T_load_ind.timeout {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003855 log("[CCH Load Ind timer] received paging requests so far: ", rx_paging_num);
3856 if (send_pag_load_ind) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003857 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(40));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003858 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003859 T_load_ind.start;
3860 repeat;
3861 }
3862 [] T_rx.timeout {
3863 setverdict(fail, "Timeout expecting paging requests, so far ", rx_paging_num);
3864 mtc.stop;
3865 }
3866 }
3867
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003868 /* Drop OML connection to have all paging requests flushed: */
3869 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
3870
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003871 f_shutdown_helper();
3872}
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003873/* Verify BSC can schedule 500 paging requests under one minute if BTS buffer is good enough */
3874testcase TC_paging_500req() runs on test_CT {
3875 f_TC_paging_Nreq(500, true);
3876}
3877/* Same as TC_paging_500req, but without sending CCCH Load Indication, which
3878 * means BTS is always under CCH Load Threshold, aka capable of sending tons of requests.
3879 * Since No CCCH Load Ind, BSC uses a conservative estimation of BTS load, which
3880 * for current config yields ~8req/sec, so 480req/min maximum. */
3881testcase TC_paging_450req_no_paging_load_ind() runs on test_CT {
3882 f_TC_paging_Nreq(450, false);
3883}
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003884
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003885/* Test RSL link drop causes counter increment */
3886testcase TC_rsl_drop_counter() runs on test_CT {
3887 var integer rsl_fail;
3888
Harald Welte89d42e82017-12-17 16:42:41 +01003889 f_init(1);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003890
3891 rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
3892
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003893 f_ipa_rsl_stop(bts[0][0].rsl);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003894
3895 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
3896
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003897 f_shutdown_helper();
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003898}
3899
3900/* TODO: Test OML link drop causes counter increment */
3901
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003902/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
3903function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003904 var IPA_Client client;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003905 timer T := 10.0;
3906
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003907 client.id := "IPA-BTS0-TRX0-RSL";
3908 client.vc_IPA := IPA_Emulation_CT.create(client.id & "-IPA") alive;
3909 client.ccm_pars := c_IPA_default_ccm_pars;
3910 client.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
3911 client.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003912
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01003913 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003914
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003915 f_init_mgcp(0, "VirtMGW");
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003916
3917 /* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003918 map(client.vc_IPA:IPA_PORT, system:IPA);
3919 connect(client.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0][0]);
3920 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 +01003921
3922 /* wait for IPA OML link to connect and then disconnect */
3923 T.start;
3924 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003925 [] IPA_RSL[0][0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003926 T.stop;
3927 return true;
3928 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003929 [] IPA_RSL[0][0].receive { repeat }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003930 [] T.timeout {
Daniel Willmannafce8662018-07-06 23:11:32 +02003931 return false;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003932 }
3933 }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003934 return false;
3935}
3936
3937/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3938testcase TC_rsl_unknown_unit_id() runs on test_CT {
3939 if (f_ipa_unknown_unit_id(mp_bsc_rsl_port)) {
3940 setverdict(pass);
3941 } else {
3942 setverdict(fail, "Timeout RSL 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
3948/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3949testcase TC_oml_unknown_unit_id() runs on test_CT {
3950 if (f_ipa_unknown_unit_id(mp_bsc_oml_port)) {
3951 setverdict(pass);
3952 } else {
3953 setverdict(fail, "Timeout OML waiting for connection to close");
3954 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003955 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003956}
3957
3958
Harald Weltec1a2fff2017-12-17 11:06:19 +01003959/***********************************************************************
Harald Welte6811d102019-04-14 22:23:14 +02003960 * "New world" test cases using RSL_Emulation + RAN_Emulation
Harald Weltec1a2fff2017-12-17 11:06:19 +01003961 ***********************************************************************/
3962
Harald Welte6811d102019-04-14 22:23:14 +02003963import from RAN_Emulation all;
Harald Welte47cd0e32020-08-21 12:39:11 +02003964import from BSSAP_LE_Emulation all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01003965import from RSL_Emulation all;
3966import from MSC_ConnectionHandler all;
3967
3968type function void_fn(charstring id) runs on MSC_ConnHdlr;
3969
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003970/* helper function to create and connect a MSC_ConnHdlr component
3971 * TODO: allow connecting to TRX1..N, not only TRX0 */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003972private 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 +02003973 connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003974 connect(vc_conn:RSL, bts[0][0].rsl.vc_RSL:CLIENT_PT);
3975 connect(vc_conn:RSL_PROC, bts[0][0].rsl.vc_RSL:RSL_PROC);
3976 if (isvalue(bts[1][0])) {
3977 connect(vc_conn:RSL1, bts[1][0].rsl.vc_RSL:CLIENT_PT);
3978 connect(vc_conn:RSL1_PROC, bts[1][0].rsl.vc_RSL:RSL_PROC);
Philipp Maier956a92f2018-02-16 10:58:07 +01003979 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003980 if (isvalue(bts[2][0])) {
3981 connect(vc_conn:RSL2, bts[2][0].rsl.vc_RSL:CLIENT_PT);
3982 connect(vc_conn:RSL2_PROC, bts[2][0].rsl.vc_RSL:RSL_PROC);
Neels Hofmeyr91401012019-07-11 00:42:35 +02003983 }
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003984 connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02003985 if (mp_enable_lcs_tests) {
3986 connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
3987 connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
3988 }
Daniel Willmannebdecc02020-08-12 15:30:17 +02003989 connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003990 connect(vc_conn:MGCP_PROC, vc_MGCP[mgwpool_idx]:MGCP_PROC);
3991 connect(vc_conn:MGCP, vc_MGCP[mgwpool_idx]:MGCP_CLIENT);
3992 connect(vc_conn:MGCP_MULTI, vc_MGCP[mgwpool_idx]:MGCP_CLIENT_MULTI);
Harald Welte336820c2018-05-31 20:34:52 +02003993}
3994
Neels Hofmeyrda436782021-07-20 22:09:06 +02003995function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
Harald Welte336820c2018-05-31 20:34:52 +02003996runs on test_CT return MSC_ConnHdlr {
3997 var charstring id := testcasename();
3998 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003999 var integer bssap_idx := 0;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004000 var integer mgwpool_idx := 0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004001 if (isvalue(pars)) {
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004002 var TestHdlrParams pars_val := valueof(pars);
4003 bssap_idx := pars_val.mscpool.bssap_idx;
4004 mgwpool_idx := pars_val.mgwpool_idx;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004005 }
Harald Welte336820c2018-05-31 20:34:52 +02004006 vc_conn := MSC_ConnHdlr.create(id);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02004007 f_connect_handler(vc_conn, bssap_idx, mgwpool_idx);
Neels Hofmeyrda436782021-07-20 22:09:06 +02004008 return vc_conn;
4009}
4010
4011function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
4012runs on test_CT return MSC_ConnHdlr {
4013 var charstring id := testcasename();
Harald Weltea0630032018-03-20 21:09:55 +01004014 vc_conn.start(f_handler_init(fn, id, pars));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004015 return vc_conn;
4016}
4017
Neels Hofmeyrda436782021-07-20 22:09:06 +02004018function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
4019runs on test_CT return MSC_ConnHdlr {
4020 return f_start_handler_run(f_start_handler_create(pars), fn, pars);
4021}
4022
Harald Weltea0630032018-03-20 21:09:55 +01004023/* first function inside ConnHdlr component; sets g_pars + starts function */
4024private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
4025runs on MSC_ConnHdlr {
4026 if (isvalue(pars)) {
4027 g_pars := valueof(pars);
4028 }
4029 fn.apply(id);
4030}
4031
Oliver Smith26a3db72021-07-09 13:51:29 +02004032private function f_vty_encryption_a5(charstring options) runs on test_CT {
4033 f_vty_transceive(BSCVTY, "configure terminal");
4034 f_vty_transceive(BSCVTY, "network");
4035 f_vty_transceive(BSCVTY, "encryption a5 " & options);
4036 f_vty_transceive(BSCVTY, "exit");
4037 f_vty_transceive(BSCVTY, "exit");
4038}
4039
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004040const charstring VTY_A5_DEFAULT := "0 1 3";
4041
Oliver Smith26a3db72021-07-09 13:51:29 +02004042private function f_vty_encryption_a5_reset() runs on test_CT {
4043 /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01004044 f_vty_encryption_a5(VTY_A5_DEFAULT);
Oliver Smith26a3db72021-07-09 13:51:29 +02004045}
4046
Harald Welte3c86ea02018-05-10 22:28:05 +02004047/* Establish signalling channel (non-assignment case) followed by cipher mode */
4048private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004049 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4050 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte3c86ea02018-05-10 22:28:05 +02004051 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Philipp Maier23000732018-05-18 11:25:37 +02004052 ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode := omit;
4053 ass_cmd.pdu.bssmap.assignmentRequest.aoIPTransportLayer := omit;
4054 exp_compl.pdu.bssmap.assignmentComplete.circuitIdentityCode := omit;
4055 exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
Harald Welte3c86ea02018-05-10 22:28:05 +02004056
Philipp Maier23000732018-05-18 11:25:37 +02004057 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004058 f_perform_clear();
Harald Welte3c86ea02018-05-10 22:28:05 +02004059}
4060testcase TC_ciph_mode_a5_0() 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('01'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}
4071testcase TC_ciph_mode_a5_1() runs on test_CT {
4072 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004073 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004074 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
4075
4076 f_init(1, true);
4077 f_sleep(1.0);
4078 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4079 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004080 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004081}
Oliver Smith50b98122021-07-09 15:00:28 +02004082/* OS#4975: verify that A5/2 is preferred over A5/0 */
4083testcase TC_ciph_mode_a5_2_0() runs on test_CT {
4084 var MSC_ConnHdlr vc_conn;
4085 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4086
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004087 pars.encr := f_encr_params('05'O, '04'O); /* A5/0 and A5/2 (0x01|0x04)*/
Oliver Smith50b98122021-07-09 15:00:28 +02004088
4089 f_init(1, true);
4090 f_vty_encryption_a5("0 1 2 3");
4091 f_sleep(1.0);
4092 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4093 vc_conn.done;
4094 f_vty_encryption_a5_reset();
4095 f_shutdown_helper();
4096}
Oliver Smith1dff88d2021-07-09 08:45:51 +02004097/* OS#4975: verify that A5/1 is preferred over A5/2 */
4098testcase TC_ciph_mode_a5_2_1() runs on test_CT {
4099 var MSC_ConnHdlr vc_conn;
4100 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4101
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004102 pars.encr := f_encr_params('06'O, '02'O); /* A5/1 and A5/2 (0x02|0x04)*/
Oliver Smith1dff88d2021-07-09 08:45:51 +02004103
4104 f_init(1, true);
4105 f_vty_encryption_a5("1 2");
4106 f_sleep(1.0);
4107 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4108 vc_conn.done;
4109 f_vty_encryption_a5_reset();
4110 f_shutdown_helper();
4111}
Harald Welte3c86ea02018-05-10 22:28:05 +02004112testcase TC_ciph_mode_a5_3() runs on test_CT {
4113 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004114 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004115 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
4116
4117 f_init(1, true);
4118 f_sleep(1.0);
4119 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4120 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004121 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004122}
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004123/* Establish a Signalling channel with A5/4 encryption. */
4124testcase TC_ciph_mode_a5_4() runs on test_CT {
4125 var MSC_ConnHdlr vc_conn;
4126 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4127 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Harald Welte3c86ea02018-05-10 22:28:05 +02004128
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004129 f_init(1, true);
Oliver Smith26a3db72021-07-09 13:51:29 +02004130 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004131 f_sleep(1.0);
4132 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4133 vc_conn.done;
Oliver Smith26a3db72021-07-09 13:51:29 +02004134 f_vty_encryption_a5_reset();
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004135 f_shutdown_helper();
4136}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004137/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
4138private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
4139 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4140 var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
4141 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4142 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4143
4144 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004145 f_perform_clear();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004146}
4147testcase TC_assignment_aoip_tla_v6() runs on test_CT {
4148 var MSC_ConnHdlr vc_conn;
4149 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4150
4151 f_init(1, true);
4152 f_sleep(1.0);
4153 vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
4154 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004155 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004156}
4157
Harald Welte3c86ea02018-05-10 22:28:05 +02004158
4159/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
Harald Welte651fcdc2018-05-10 20:23:16 +02004160private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004161 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4162 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004163
Harald Welte552620d2017-12-16 23:21:36 +01004164 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4165 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte73cd2712017-12-17 00:44:52 +01004166
Harald Weltea0630032018-03-20 21:09:55 +01004167 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004168 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004169}
Harald Welte552620d2017-12-16 23:21:36 +01004170testcase TC_assignment_fr_a5_0() runs on test_CT {
4171 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('01'O, f_rnd_octstring(8)));
Harald Welte552620d2017-12-16 23:21:36 +01004174
Harald Welte89d42e82017-12-17 16:42:41 +01004175 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +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);
Harald Welte552620d2017-12-16 23:21:36 +01004178 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004179 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004180}
Harald Welte552620d2017-12-16 23:21:36 +01004181testcase TC_assignment_fr_a5_1() runs on test_CT {
Harald Weltec1a2fff2017-12-17 11:06:19 +01004182 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('02'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004185
Harald Welte89d42e82017-12-17 16:42:41 +01004186 f_init(1, true);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004187 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004188 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4189 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004190 f_shutdown_helper();
Harald Welte651fcdc2018-05-10 20:23:16 +02004191}
4192testcase TC_assignment_fr_a5_3() runs on test_CT {
4193 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004194 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004195 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004196
Harald Welte651fcdc2018-05-10 20:23:16 +02004197 f_init(1, true);
4198 f_sleep(1.0);
4199 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004200 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004201 f_shutdown_helper();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004202}
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004203/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
4204testcase TC_assignment_fr_a5_4() runs on test_CT {
4205 var MSC_ConnHdlr vc_conn;
4206 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4207 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
4208
4209 f_init(1, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02004210 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004211 f_sleep(1.0);
4212 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4213 vc_conn.done;
Oliver Smith7eabd312021-07-12 14:18:56 +02004214 f_vty_encryption_a5_reset();
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004215 f_shutdown_helper();
4216}
Harald Weltec1a2fff2017-12-17 11:06:19 +01004217
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +02004218/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
4219testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
4220 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4221 var MSC_ConnHdlr vc_conn;
4222
4223 f_init(1, true);
4224 f_sleep(1.0);
4225
4226 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
4227 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
4228 vc_conn.done;
4229 f_shutdown_helper();
4230}
4231
Harald Welte552620d2017-12-16 23:21:36 +01004232/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
4233private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004234 g_pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004235 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02004236 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004237
4238 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02004239 /* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
4240
Harald Weltea0630032018-03-20 21:09:55 +01004241 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004242 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004243}
Harald Welte552620d2017-12-16 23:21:36 +01004244testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
4245 var MSC_ConnHdlr vc_conn;
4246
Harald Welte89d42e82017-12-17 16:42:41 +01004247 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004248 f_sleep(1.0);
4249
Harald Welte8863fa12018-05-10 20:15:27 +02004250 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
Harald Welte552620d2017-12-16 23:21:36 +01004251 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004252 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004253}
4254
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004255private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
4256 var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
4257 var PDU_BSSAP exp_ass_req := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004258
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004259 exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4260 exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4261
4262 /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
4263
4264 var BSSMAP_FIELD_CodecType codecType;
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004265
4266 codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
4267 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
4268
4269 f_create_chan_and_exp();
4270 /* we should now have a COMPL_L3 at the MSC */
4271
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004272 /* Start ciphering, expect Cipher Mode Reject */
Neels Hofmeyr6c388f22021-06-11 02:36:56 +02004273 f_cipher_mode(g_pars.encr, exp_fail := true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004274 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004275}
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004276testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
4277 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004278 var MSC_ConnHdlr vc_conn;
4279
Harald Welte89d42e82017-12-17 16:42:41 +01004280 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004281 f_sleep(1.0);
4282
Neels Hofmeyr0588cad2021-06-11 01:38:18 +02004283 pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004284 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004285 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004286 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004287}
4288
4289
Harald Welte4532e0a2017-12-23 02:05:44 +01004290private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004291 g_pars := f_gen_test_hdlr_pars();
Harald Welte4532e0a2017-12-23 02:05:44 +01004292 var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
Philipp Maier48604732018-10-09 15:00:37 +02004293 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte4532e0a2017-12-23 02:05:44 +01004294 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004295
4296 f_statsd_reset();
Harald Weltea0630032018-03-20 21:09:55 +01004297 f_establish_fully(ass_cmd, exp_compl);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004298
4299 var StatsDExpects expect := {
Daniel Willmannc5398f72020-09-21 10:41:35 +02004300 { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
4301 { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
Daniel Willmannebdecc02020-08-12 15:30:17 +02004302 { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
4303 { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
4304 };
4305 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004306 f_perform_clear();
Harald Welte4532e0a2017-12-23 02:05:44 +01004307}
4308
4309testcase TC_assignment_sign() runs on test_CT {
4310 var MSC_ConnHdlr vc_conn;
4311
4312 f_init(1, true);
4313 f_sleep(1.0);
4314
Harald Welte8863fa12018-05-10 20:15:27 +02004315 vc_conn := f_start_handler(refers(f_tc_assignment_sign));
Harald Welte4532e0a2017-12-23 02:05:44 +01004316 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004317 f_shutdown_helper();
Harald Welte4532e0a2017-12-23 02:05:44 +01004318}
4319
Harald Welte60aa5762018-03-21 19:33:13 +01004320/***********************************************************************
4321 * Codec (list) testing
4322 ***********************************************************************/
4323
4324/* check if the given rsl_mode is compatible with the a_elem */
4325private function f_match_codec(BSSMAP_FIELD_CodecElement a_elem, RSL_IE_ChannelMode rsl_mode)
4326return boolean {
4327 select (a_elem.codecType) {
4328 case (GSM_FR) {
4329 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1))) {
4330 return true;
4331 }
4332 }
4333 case (GSM_HR) {
4334 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1))) {
4335 return true;
4336 }
4337 }
4338 case (GSM_EFR) {
4339 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2))) {
4340 return true;
4341 }
4342 }
4343 case (FR_AMR) {
4344 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3))) {
4345 return true;
4346 }
4347 }
4348 case (HR_AMR) {
4349 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3))) {
4350 return true;
4351 }
4352 }
4353 case else { }
4354 }
4355 return false;
4356}
4357
4358/* check if the given rsl_mode is compatible with the a_list */
4359private function f_match_codecs(BSSMAP_IE_SpeechCodecList a_list, RSL_IE_ChannelMode rsl_mode)
4360return boolean {
4361 for (var integer i := 0; i < sizeof(a_list); i := i+1) {
4362 if (f_match_codec(a_list.codecElements[i], rsl_mode)) {
4363 return true;
4364 }
4365 }
4366 return false;
4367}
4368
4369/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
Philipp Maier61f6b572018-07-06 14:03:38 +02004370function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
Harald Welte60aa5762018-03-21 19:33:13 +01004371return BSSMAP_IE_ChannelType {
4372 /* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
4373 var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
4374 select (a_elem.codecType) {
4375 case (GSM_FR) {
4376 ret.channelRateAndType := ChRate_TCHF;
4377 ret.speechId_DataIndicator := Spdi_TCHF_FR;
4378 }
4379 case (GSM_HR) {
4380 ret.channelRateAndType := ChRate_TCHH;
4381 ret.speechId_DataIndicator := Spdi_TCHH_HR;
4382 }
4383 case (GSM_EFR) {
4384 ret.channelRateAndType := ChRate_TCHF;
4385 ret.speechId_DataIndicator := Spdi_TCHF_EFR;
4386 }
4387 case (FR_AMR) {
4388 ret.channelRateAndType := ChRate_TCHF;
4389 ret.speechId_DataIndicator := Spdi_TCHF_AMR;
4390 }
4391 case (HR_AMR) {
4392 ret.channelRateAndType := ChRate_TCHH;
4393 ret.speechId_DataIndicator := Spdi_TCHH_AMR;
4394 }
4395 case else {
4396 setverdict(fail, "Unsupported codec ", a_elem);
Daniel Willmannafce8662018-07-06 23:11:32 +02004397 mtc.stop;
Harald Welte60aa5762018-03-21 19:33:13 +01004398 }
4399 }
4400 return ret;
4401}
4402
Harald Weltea63b9102018-03-22 20:36:16 +01004403private function f_rsl_chmod_tmpl_from_codec(BSSMAP_FIELD_CodecElement a_elem)
4404return template RSL_IE_Body {
4405 var template RSL_IE_Body mode_ie := {
4406 chan_mode := {
4407 len := ?,
4408 reserved := ?,
4409 dtx_d := ?,
4410 dtx_u := ?,
4411 spd_ind := RSL_SPDI_SPEECH,
4412 ch_rate_type := -,
Oliver Smith0033b122023-02-28 13:30:53 +01004413 u := { speech := - }
Harald Weltea63b9102018-03-22 20:36:16 +01004414 }
4415 }
4416
4417 select (a_elem.codecType) {
4418 case (GSM_FR) {
4419 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004420 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004421 }
4422 case (GSM_HR) {
4423 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004424 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
Harald Weltea63b9102018-03-22 20:36:16 +01004425 }
4426 case (GSM_EFR) {
4427 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004428 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM2;
Harald Weltea63b9102018-03-22 20:36:16 +01004429 }
4430 case (FR_AMR) {
4431 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
Oliver Smith0033b122023-02-28 13:30:53 +01004432 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004433 }
4434 case (HR_AMR) {
4435 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
Oliver Smith0033b122023-02-28 13:30:53 +01004436 mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
Harald Weltea63b9102018-03-22 20:36:16 +01004437 }
4438 }
4439 return mode_ie;
4440}
4441
Harald Welte60aa5762018-03-21 19:33:13 +01004442type record CodecListTest {
4443 BSSMAP_IE_SpeechCodecList codec_list,
4444 charstring id
4445}
4446type record of CodecListTest CodecListTests
4447
4448private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004449 f_assignment_codec(id);
4450}
4451
4452private function f_assignment_codec(charstring id, boolean do_perform_clear := true) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02004453 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02004454 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welte60aa5762018-03-21 19:33:13 +01004455
4456 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004457 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte79f3f542018-05-25 20:02:37 +02004458 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4459 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
4460 g_pars.ass_codec_list.codecElements[0];
Philipp Maierd0e64b02019-03-13 14:15:23 +01004461 if (isvalue(g_pars.expect_mr_s0_s7)) {
4462 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
4463 g_pars.expect_mr_s0_s7;
4464 }
Harald Welte79f3f542018-05-25 20:02:37 +02004465 }
Harald Welte60aa5762018-03-21 19:33:13 +01004466 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4467 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
Harald Welte60aa5762018-03-21 19:33:13 +01004468 log("expecting ASS COMPL like this: ", exp_compl);
4469
4470 f_establish_fully(ass_cmd, exp_compl);
Harald Weltea63b9102018-03-22 20:36:16 +01004471
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004472 if (not g_pars.expect_channel_mode_modify) {
4473 /* Verify that the RSL-side activation actually matches our expectations */
4474 var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
Harald Weltea63b9102018-03-22 20:36:16 +01004475
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004476 var RSL_IE_Body mode_ie;
4477 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
4478 setverdict(fail, "Couldn't find CHAN_MODE IE");
Daniel Willmannafce8662018-07-06 23:11:32 +02004479 mtc.stop;
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004480 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004481 var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
4482 if (not match(mode_ie, t_mode_ie)) {
4483 log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
4484 setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004485 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004486
4487 var RSL_IE_Body mr_conf;
4488 if (g_pars.expect_mr_conf_ie != omit) {
4489 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
4490 setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
4491 mtc.stop;
4492 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004493 log("found RSL MR CONFIG IE: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004494
4495 if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
Vadim Yanitskiy8b189372022-09-14 17:31:17 +07004496 setverdict(fail, "RSL MR CONFIG IE does not match expectation. ",
4497 "Expected: ", g_pars.expect_mr_conf_ie, ", got: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004498 }
4499 } else {
4500 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
4501 log("found RSL MR CONFIG IE: ", mr_conf);
4502 setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
4503 mtc.stop;
4504 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004505 }
4506 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004507
4508 if (do_perform_clear) {
4509 f_perform_clear();
4510 }
Harald Welte60aa5762018-03-21 19:33:13 +01004511}
4512
Philipp Maierd0e64b02019-03-13 14:15:23 +01004513private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
4514
4515 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4516 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4517
4518 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004519 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maierd0e64b02019-03-13 14:15:23 +01004520 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4521 }
4522 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4523 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
4524 log("expecting ASS FAIL like this: ", exp_fail);
4525
4526 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004527 f_perform_clear();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004528}
4529
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004530const CounterNameVals counternames_bsc_bts_assignment := {
4531 { "assignment:attempted", 0 },
4532 { "assignment:completed", 0 },
4533 { "assignment:stopped", 0 },
4534 { "assignment:no_channel", 0 },
4535 { "assignment:timeout", 0 },
4536 { "assignment:failed", 0 },
4537 { "assignment:error", 0 }
4538};
4539
4540const CounterNameVals counternames_bts_assignment := {
4541 { "assignment:attempted_sign", 0 },
4542 { "assignment:attempted_speech", 0 },
4543 { "assignment:completed_sign", 0 },
4544 { "assignment:completed_speech", 0 },
4545 { "assignment:stopped_sign", 0 },
4546 { "assignment:stopped_speech", 0 },
4547 { "assignment:no_channel_sign", 0 },
4548 { "assignment:no_channel_speech", 0 },
4549 { "assignment:timeout_sign", 0 },
4550 { "assignment:timeout_speech", 0 },
4551 { "assignment:failed_sign", 0 },
4552 { "assignment:failed_speech", 0 },
4553 { "assignment:error_sign", 0 },
4554 { "assignment:error_speech", 0 }
4555};
4556
4557function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
4558 var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
4559 f_ctrs_bts_init(bts_count, bts_names);
4560 f_ctrs_bsc_init(counternames_bsc_bts_assignment);
4561}
4562
Harald Welte60aa5762018-03-21 19:33:13 +01004563testcase TC_assignment_codec_fr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004564 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004565 var MSC_ConnHdlr vc_conn;
4566
4567 f_init(1, true);
4568 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004569 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004570
4571 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004572 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004573 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004574
4575 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4576 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4577 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4578 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4579 f_ctrs_bts_verify();
4580
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004581 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004582}
4583
4584testcase TC_assignment_codec_hr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004585 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004586 var MSC_ConnHdlr vc_conn;
4587
4588 f_init(1, true);
4589 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004590 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004591
4592 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004593 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004594 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004595
4596 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4597 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4598 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4599 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4600 f_ctrs_bts_verify();
4601
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004602 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004603}
4604
4605testcase TC_assignment_codec_efr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004606 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004607 var MSC_ConnHdlr vc_conn;
4608
4609 f_init(1, true);
4610 f_sleep(1.0);
4611
4612 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004613 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004614 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004615 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004616}
4617
Philipp Maierd0e64b02019-03-13 14:15:23 +01004618/* Allow 5,90k only (current default config) */
4619private function f_allow_amr_rate_5_90k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004620 f_vty_cfg_msc(BSCVTY, 0, {
4621 "amr-config 12_2k forbidden",
4622 "amr-config 10_2k forbidden",
4623 "amr-config 7_95k forbidden",
4624 "amr-config 7_40k forbidden",
4625 "amr-config 6_70k forbidden",
4626 "amr-config 5_90k allowed",
4627 "amr-config 5_15k forbidden",
4628 "amr-config 4_75k forbidden"
4629 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004630}
4631
4632/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
4633 * ("Config-NB-Code = 1") */
4634private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004635 f_vty_cfg_msc(BSCVTY, 0, {
4636 "amr-config 12_2k allowed",
4637 "amr-config 10_2k forbidden",
4638 "amr-config 7_95k forbidden",
4639 "amr-config 7_40k allowed",
4640 "amr-config 6_70k forbidden",
4641 "amr-config 5_90k allowed",
4642 "amr-config 5_15k forbidden",
4643 "amr-config 4_75k allowed"
4644 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004645}
4646
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004647private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
4648 var charstring tch;
4649 if (fr) {
4650 tch := "tch-f";
4651 } else {
4652 tch := "tch-h";
4653 }
4654 f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
4655}
4656
4657/* Set the AMR start-mode for this TCH back to the default configuration. */
4658private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
4659 f_vty_amr_start_mode_set(fr, "auto");
4660}
4661
Harald Welte60aa5762018-03-21 19:33:13 +01004662testcase TC_assignment_codec_amr_f() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004663 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004664 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004665
4666 /* Note: This setups the codec configuration. The parameter payload in
4667 * mr_conf must be consistant with the parameter codecElements in pars
4668 * and also must match the amr-config in osmo-bsc.cfg! */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004669 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004670 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004671 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004672 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004673
Harald Welte60aa5762018-03-21 19:33:13 +01004674 f_init(1, true);
4675 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004676 f_vty_amr_start_mode_set(true, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004677 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004678
Harald Welte8863fa12018-05-10 20:15:27 +02004679 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004680 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004681
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004682 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4683 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4684 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4685 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4686 f_ctrs_bts_verify();
4687
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004688 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004689 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004690}
4691
4692testcase TC_assignment_codec_amr_h() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004693 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004694 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004695
4696 /* See note above */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004697 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004698 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004699 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004700 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004701
Harald Welte60aa5762018-03-21 19:33:13 +01004702 f_init(1, true);
4703 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004704 f_vty_amr_start_mode_set(false, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004705 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004706
Harald Welte8863fa12018-05-10 20:15:27 +02004707 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004708 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004709
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004710 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4711 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4712 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4713 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4714 f_ctrs_bts_verify();
4715
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004716 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004717 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004718}
4719
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004720/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
4721testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
4722 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4723 var MSC_ConnHdlr vc_conn;
4724
4725 f_init(1, true);
4726 f_sleep(1.0);
4727
4728 /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
4729 * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
4730 * expecting a Channel Mode Modify if the channel type is compatible. */
4731 f_disable_all_sdcch();
4732 f_disable_all_tch_h();
4733
4734 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4735 pars.expect_channel_mode_modify := true;
4736 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4737 vc_conn.done;
4738
4739 f_enable_all_sdcch();
4740 f_enable_all_tch();
4741 f_shutdown_helper();
4742}
4743
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004744/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
4745testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
4746 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4747 var MSC_ConnHdlr vc_conn;
4748
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004749 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4750 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
4751 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy36fe9582022-09-14 15:25:04 +07004752 pars.expect_mr_conf_ie := c_mr_conf_5_90;
4753 pars.expect_mr_conf_ie.multirate_cfg.icmi := false; /* expect ICMI=0, smod=00: */
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004754
4755 f_init(1, true);
4756 f_sleep(1.0);
4757
4758 /* First set nonzero start mode bits */
4759 f_vty_amr_start_mode_set(true, "4");
4760 /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
4761 * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
4762 * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
4763 f_vty_amr_start_mode_set(true, "auto");
4764
4765 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4766 vc_conn.done;
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004767
4768 /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
4769 f_vty_amr_start_mode_set(true, "1");
4770 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004771 f_shutdown_helper();
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004772}
4773
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004774function f_TC_assignment_codec_amr(boolean fr, RSL_IE_MultirateCfg mr_cfg,
4775 bitstring s8_s0, bitstring exp_s8_s0,
4776 charstring start_mode := "1")
Philipp Maierd0e64b02019-03-13 14:15:23 +01004777runs on test_CT {
4778
4779 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4780 var MSC_ConnHdlr vc_conn;
4781
Philipp Maierd0e64b02019-03-13 14:15:23 +01004782 if (fr) {
4783 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4784 } else {
4785 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4786 }
4787 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4788 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004789 pars.expect_mr_conf_ie := { multirate_cfg := mr_cfg };
Philipp Maierd0e64b02019-03-13 14:15:23 +01004790 pars.expect_mr_s0_s7 := exp_s8_s0;
4791
4792 f_init(1, true);
4793 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004794 f_vty_amr_start_mode_set(fr, start_mode);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004795 f_sleep(1.0);
4796
4797 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4798 vc_conn.done;
4799 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004800 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004801}
4802
4803function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
4804runs on test_CT {
4805
4806 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4807 var MSC_ConnHdlr vc_conn;
4808
4809 if (fr) {
4810 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4811 } else {
4812 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4813 }
4814 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4815 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4816
4817 f_init(1, true);
4818 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004819 f_vty_amr_start_mode_set(fr, "1");
Philipp Maierd0e64b02019-03-13 14:15:23 +01004820 f_sleep(1.0);
4821
4822 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
4823 vc_conn.done;
4824 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004825 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004826}
4827
Philipp Maierd0e64b02019-03-13 14:15:23 +01004828/* Set S1, we expect an AMR multirate configuration IE with all four rates
4829 * set. */
4830testcase TC_assignment_codec_amr_f_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004831 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4832 params := '20882208'O));
4833 f_TC_assignment_codec_amr(true, mr_cfg, '00000011'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004834 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004835}
4836
4837/* Set S1, we expect an AMR multirate configuration IE with the lower three
4838 * rates set. */
4839testcase TC_assignment_codec_amr_h_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004840 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4841 params := '208820'O));
4842 f_TC_assignment_codec_amr(false, mr_cfg, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004843 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004844}
4845
4846/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4847 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4848testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004849 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4850 params := '20882208'O));
4851 f_TC_assignment_codec_amr(true, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004852 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004853}
4854
4855/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4856 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4857testcase TC_assignment_codec_amr_h_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004858 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4859 params := '208820'O));
4860 f_TC_assignment_codec_amr(false, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004861 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004862}
4863
4864/* The following block of tests selects more and more rates until all four
4865 * possible rates are in the active set (full rate) */
4866testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004867 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4868 f_TC_assignment_codec_amr(true, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004869 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004870}
4871
4872testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004873 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4874 params := '2080'O));
4875 f_TC_assignment_codec_amr(true, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004876 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004877}
4878
4879testcase TC_assignment_codec_amr_f_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004880 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4881 params := '208820'O));
4882 f_TC_assignment_codec_amr(true, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004883 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004884}
4885
4886testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004887 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4888 params := '20882208'O));
4889 f_TC_assignment_codec_amr(true, mr_cfg, '10010101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004890 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004891}
4892
4893/* The following block of tests selects more and more rates until all three
4894 * possible rates are in the active set (half rate) */
4895testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004896 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4897 f_TC_assignment_codec_amr(false, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004898 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004899}
4900
4901testcase TC_assignment_codec_amr_h_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004902 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4903 params := '2080'O));
4904 f_TC_assignment_codec_amr(false, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004905 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004906}
4907
4908testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004909 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4910 params := '208820'O));
4911 f_TC_assignment_codec_amr(false, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004912 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004913}
4914
4915/* The following block tests what happens when the MSC does offer rate
4916 * configurations that are not supported by the BSC. Normally such situations
4917 * should not happen because the MSC gets informed by the BSC in advance via
4918 * the L3 COMPLETE message which rates are applicable. The MSC should not try
4919 * to offer rates that are not applicable anyway. */
4920
4921testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004922 /* Try to include 12,2k in into the active set even though the channel
4923 * is half rate only. The BSC is expected to remove the 12,0k */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004924 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4925 params := '208820'O));
4926 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004927 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004928}
4929
4930testcase TC_assignment_codec_amr_f_S01234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004931 /* See what happens when all rates are selected at once. Since then
4932 * Also S1 is selected, this setting will be prefered and we should
4933 * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004934 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4935 params := '20882208'O));
4936 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004937 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004938}
4939
4940testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004941 /* Same as above, but with S1 missing, the MSC is then expected to
4942 * select the currently supported rates, which are also 12.2k, 7,40k,
4943 * 5,90k, and 4,75k, into the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004944 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4945 params := '20882208'O));
4946 f_TC_assignment_codec_amr(true, mr_cfg, '11111101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004947 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004948}
4949
4950testcase TC_assignment_codec_amr_f_zero() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004951 /* Try to select no rates at all */
4952 f_TC_assignment_codec_amr_fail(true, '00000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004953 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004954}
4955
4956testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004957 /* Try to select only unsupported rates */
4958 f_TC_assignment_codec_amr_fail(true, '01101000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004959 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004960}
4961
4962testcase TC_assignment_codec_amr_h_S7() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004963 /* Try to select 12,2k for half rate */
4964 f_TC_assignment_codec_amr_fail(false, '10000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004965 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004966}
4967
Neels Hofmeyr21863562020-11-26 00:34:33 +00004968testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004969 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4970 codec_modes := '10010101'B,
4971 params := '20882208'O));
4972 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004973 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004974}
4975
4976testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004977 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4978 codec_modes := '00010101'B,
4979 params := '208820'O));
4980 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B,
Neels Hofmeyr21863562020-11-26 00:34:33 +00004981 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004982 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004983}
4984
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004985testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004986 /* "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 +07004987 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 3,
4988 codec_modes := '10010101'B,
4989 params := '20882208'O));
4990 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004991 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004992}
4993
4994testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004995 /* "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 +07004996 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 2,
4997 codec_modes := '00010101'B,
4998 params := '208820'O));
4999 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01005000 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00005001}
5002
Philipp Maierac09bfc2019-01-08 13:41:39 +01005003private function f_disable_all_tch_f() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005004 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 borken");
5005 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 borken");
5006 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 borken");
5007 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005008}
5009
5010private function f_disable_all_tch_h() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005011 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 borken");
5012 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005013}
5014
5015private function f_enable_all_tch() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01005016 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 unused");
5017 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 unused");
5018 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 unused");
5019 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 unused");
5020 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 unused");
5021 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
Philipp Maierac09bfc2019-01-08 13:41:39 +01005022}
5023
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02005024private function f_disable_all_sdcch() runs on test_CT {
5025 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
5026 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
5027 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
5028 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
5029}
5030
5031private function f_enable_all_sdcch() runs on test_CT {
5032 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
5033 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
5034 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
5035 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
5036}
5037
Philipp Maierac09bfc2019-01-08 13:41:39 +01005038/* Allow HR only */
5039private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs on MSC_ConnHdlr {
5040 g_pars := f_gen_test_hdlr_pars();
5041 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5042 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5043 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5044 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5045 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5046 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5047 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005048 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005049}
5050
5051/* Allow FR only */
5052private function f_TC_assignment_codec_xr_exhausted_req_fr(charstring id) runs on MSC_ConnHdlr {
5053 g_pars := f_gen_test_hdlr_pars();
5054 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5055 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5056 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5057 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5058 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5059 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5060 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005061 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005062}
5063
5064/* Allow HR only (expect assignment failure) */
5065private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) runs on MSC_ConnHdlr {
5066 g_pars := f_gen_test_hdlr_pars();
5067 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5068 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5069 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5070 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5071 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5072 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5073 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005074 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005075}
5076
5077/* Allow FR only (expect assignment failure) */
5078private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) runs on MSC_ConnHdlr {
5079 g_pars := f_gen_test_hdlr_pars();
5080 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5081 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5082 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5083 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5084 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5085 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5086 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005087 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005088}
5089
5090/* Allow FR and HR, but prefer FR */
5091private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5092 g_pars := f_gen_test_hdlr_pars();
5093 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5094 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5095 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5096 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5097 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5098 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5099 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5100 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005101 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005102}
5103
5104/* Allow FR and HR, but prefer HR */
5105private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5106 g_pars := f_gen_test_hdlr_pars();
5107 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5108 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5109 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5110 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5111 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5112 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5113 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5114 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005115 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005116}
5117
5118/* Allow FR and HR, but prefer FR */
5119private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5120 g_pars := f_gen_test_hdlr_pars();
5121 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5122 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5123 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5124 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5125 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5126 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5127 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5128 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005129 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005130}
5131
5132/* Allow FR and HR, but prefer HR */
5133private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5134 g_pars := f_gen_test_hdlr_pars();
5135 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5136 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5137 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5138 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5139 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5140 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5141 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5142 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005143 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005144}
5145
5146/* Request a HR channel while all FR channels are exhausted, this is expected
5147 * to work without conflicts */
5148testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
5149 var MSC_ConnHdlr vc_conn;
5150 f_init(1, true);
5151 f_sleep(1.0);
5152 f_enable_all_tch();
5153 f_disable_all_tch_f();
5154 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
5155 vc_conn.done;
5156 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005157 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005158}
5159
5160/* Request a FR channel while all FR channels are exhausted, this is expected
5161 * to fail. */
5162testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
5163 var MSC_ConnHdlr vc_conn;
5164 f_init(1, true);
5165 f_sleep(1.0);
5166 f_enable_all_tch();
5167 f_disable_all_tch_f();
5168 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
5169 vc_conn.done;
5170 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005171 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005172}
5173
5174/* Request a FR (prefered) or alternatively a HR channel while all FR channels
5175 * are exhausted, this is expected to be resolved by selecting a HR channel. */
5176testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
5177 var MSC_ConnHdlr vc_conn;
5178 f_init(1, true);
5179 f_sleep(1.0);
5180 f_enable_all_tch();
5181 f_disable_all_tch_f();
5182 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
5183 vc_conn.done;
5184 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005185 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005186}
5187
5188/* Request a HR (prefered) or alternatively a FR channel while all FR channels
5189 * are exhausted, this is expected to work without conflicts. */
5190testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
5191 var MSC_ConnHdlr vc_conn;
5192 f_init(1, true);
5193 f_sleep(1.0);
5194 f_enable_all_tch();
5195 f_disable_all_tch_f();
5196 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
5197 vc_conn.done;
5198 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005199 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005200}
5201
5202/* Request a FR channel while all HR channels are exhausted, this is expected
5203 * to work without conflicts */
5204testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
5205 var MSC_ConnHdlr vc_conn;
5206 f_init(1, true);
5207 f_sleep(1.0);
5208 f_enable_all_tch();
5209 f_disable_all_tch_h();
5210 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
5211 vc_conn.done;
5212 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005213 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005214}
5215
5216/* Request a HR channel while all HR channels are exhausted, this is expected
5217 * to fail. */
5218testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
5219 var MSC_ConnHdlr vc_conn;
5220 f_init(1, true);
5221 f_sleep(1.0);
5222 f_enable_all_tch();
5223 f_disable_all_tch_h();
5224 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
5225 vc_conn.done;
5226 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005227 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005228}
5229
5230/* Request a HR (prefered) or alternatively a FR channel while all HR channels
5231 * are exhausted, this is expected to be resolved by selecting a FR channel. */
5232testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
5233 var MSC_ConnHdlr vc_conn;
5234 f_init(1, true);
5235 f_sleep(1.0);
5236 f_enable_all_tch();
5237 f_disable_all_tch_h();
5238 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
5239 vc_conn.done;
5240 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005241 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005242}
5243
5244/* Request a FR (prefered) or alternatively a HR channel while all HR channels
5245 * are exhausted, this is expected to work without conflicts. */
5246testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
5247 var MSC_ConnHdlr vc_conn;
5248 f_init(1, true);
5249 f_sleep(1.0);
5250 f_enable_all_tch();
5251 f_disable_all_tch_h();
5252 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
5253 vc_conn.done;
5254 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005255 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005256}
5257
5258/* Allow FR and HR, but prefer HR */
5259private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5260 g_pars := f_gen_test_hdlr_pars();
5261 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5262 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5263 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5264 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5265 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5266 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5267 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5268 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005269 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005270}
5271
5272/* Allow FR and HR, but prefer FR */
5273private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5274 g_pars := f_gen_test_hdlr_pars();
5275 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5276 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5277 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5278 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5279 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5280 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5281 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5282 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005283 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005284}
5285
5286/* Request a HR (prefered) or alternatively a FR channel, it is expected that
5287 * HR, which is the prefered type, is selected. */
5288testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
5289 var MSC_ConnHdlr vc_conn;
5290 f_init(1, true);
5291 f_sleep(1.0);
5292 f_enable_all_tch();
5293 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
5294 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005295 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005296}
5297
5298/* Request a FR (prefered) or alternatively a HR channel, it is expected that
5299 * FR, which is the prefered type, is selected. */
5300testcase TC_assignment_codec_req_fr_hr() runs on test_CT {
5301 var MSC_ConnHdlr vc_conn;
5302 f_init(1, true);
5303 f_sleep(1.0);
5304 f_enable_all_tch();
5305 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_fr_hr));
5306 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005307 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005308}
5309
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005310/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
5311private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
5312 g_pars := f_gen_test_hdlr_pars();
5313 g_pars.ra := '02'O; /* RA containing reason=LU */
5314
5315 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5316 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5317 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5318 var template uint3_t tsc := ?;
5319
5320 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5321 f_create_bssmap_exp(l3_enc);
5322 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5323 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5324
5325 /* we should now have a COMPL_L3 at the MSC */
5326 timer T := 10.0;
5327 T.start;
5328 alt {
5329 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5330 [] T.timeout {
5331 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5332 }
5333 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005334
5335 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005336}
5337testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
5338 var MSC_ConnHdlr vc_conn;
5339 f_init(1, true);
5340 f_sleep(1.0);
5341 f_disable_all_sdcch();
5342 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
5343 vc_conn.done;
5344 f_enable_all_sdcch();
5345 f_shutdown_helper();
5346}
5347
5348/* Request a signalling channel with all SDCCH exhausted, it is
5349 expected that no TCH will be selected for signalling and assigment will fail
5350 because it's dictated by VTY config */
5351testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
5352 var RSL_Message rsl_unused, rsl_msg;
5353 var GsmRrMessage rr;
5354 f_init(1, false);
5355 f_sleep(1.0);
5356 f_vty_allow_tch_for_signalling(false, 0);
5357 f_disable_all_sdcch();
5358
5359 /* RA containing reason=LU */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005360 f_ipa_tx(ts_RSL_CHAN_RQD('02'O, 2342));
5361 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005362 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
5363 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
5364 setverdict(fail, "Expected reject");
5365 }
5366
5367 f_vty_allow_tch_for_signalling(true, 0);
5368 f_enable_all_sdcch();
5369 f_shutdown_helper();
5370}
5371
5372/* Request a voice channel with all SDCCH exhausted, it is
5373 * expected that TCH channel will be allocated since the VTY option is only
5374 * aimed at signalling requests */
5375private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
5376 g_pars := f_gen_test_hdlr_pars();
5377 g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
5378
5379 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5380 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5381 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5382 var template uint3_t tsc := ?;
5383
5384 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5385 f_create_bssmap_exp(l3_enc);
5386 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5387 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5388
5389 /* we should now have a COMPL_L3 at the MSC */
5390 timer T := 10.0;
5391 T.start;
5392 alt {
5393 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5394 [] T.timeout {
5395 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5396 }
5397 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005398 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005399}
5400testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
5401 var MSC_ConnHdlr vc_conn;
5402 f_init(1, true);
5403 f_sleep(1.0);
5404 f_vty_allow_tch_for_signalling(false, 0);
5405 f_disable_all_sdcch();
5406
5407 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
5408 vc_conn.done;
5409
5410 f_vty_allow_tch_for_signalling(true, 0);
5411 f_enable_all_sdcch();
5412 f_shutdown_helper();
5413}
5414
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005415/* Test Osmux setup BSC<->MSC */
5416testcase TC_assignment_osmux_cn() runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005417 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5418 var MSC_ConnHdlr vc_conn;
5419
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005420 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5421 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5422 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiyb9bf00f2022-09-14 15:35:37 +07005423 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02005424 pars.use_osmux_cn := true;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005425
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02005426 g_osmux_enabled_cn := true;
5427 f_init(1, true);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005428 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005429 f_vty_amr_start_mode_set(false, "1");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005430
5431 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5432 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005433
5434 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01005435 f_shutdown_helper();
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005436}
5437
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005438/* Test Osmux setup BTS<->BSC */
5439testcase TC_assignment_osmux_bts() runs on test_CT {
5440 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5441 var MSC_ConnHdlr vc_conn;
5442
5443 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5444 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5445 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005446 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005447 pars.use_osmux_bts := true;
5448
5449 g_osmux_enabled_bts := true;
5450 f_init(1, true);
5451 f_sleep(1.0);
5452 f_vty_amr_start_mode_set(false, "1");
5453
5454 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5455 vc_conn.done;
5456
5457 f_vty_amr_start_mode_restore(false);
5458 f_shutdown_helper();
5459}
5460
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +02005461/* Test non-AMR codecs still work fine as RTP when Osmux is enabled BTS<->BSC<->MSC */
5462testcase TC_assignment_codec_hr_osmux_on() runs on test_CT {
5463 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5464 var MSC_ConnHdlr vc_conn;
5465
5466 g_osmux_enabled_cn := true;
5467 g_osmux_enabled_bts := true;
5468 f_init(1, true);
5469 f_sleep(1.0);
5470 f_ctrs_bsc_and_bts_assignment_init(1);
5471
5472 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5473 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5474 vc_conn.done;
5475
5476 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
5477 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
5478 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
5479 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
5480 f_ctrs_bts_verify();
5481
5482 f_shutdown_helper();
5483}
5484
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005485/* Test Osmux setup BTS<->BSC<->MSC */
5486testcase TC_assignment_osmux() runs on test_CT {
5487 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5488 var MSC_ConnHdlr vc_conn;
5489
5490 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5491 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5492 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005493 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005494 pars.use_osmux_cn := true;
5495 pars.use_osmux_bts := true;
5496
5497 g_osmux_enabled_cn := true;
5498 g_osmux_enabled_bts := true;
5499 f_init(1, true);
5500 f_sleep(1.0);
5501 f_vty_amr_start_mode_set(false, "1");
5502
5503 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5504 vc_conn.done;
5505
5506 f_vty_amr_start_mode_restore(false);
5507 f_shutdown_helper();
5508}
5509
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005510/* test the procedure of the MSC requesting a Classmark Update:
5511 * a) BSSMAP Classmark Request should result in RR CLASSMARK ENQUIRY,
5512 * b) L3 RR CLASSMARK CHANGE should result in BSSMAP CLASSMARK UPDATE */
Harald Welte898113b2018-01-31 18:32:21 +01005513private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005514 g_pars := f_gen_test_hdlr_pars();
5515
Harald Weltea0630032018-03-20 21:09:55 +01005516 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005517 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005518
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005519 BSSAP.send(ts_BSSMAP_ClassmarkRequest);
5520 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
5521
Harald Welte898113b2018-01-31 18:32:21 +01005522 f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
5523 BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
5524 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005525
5526 f_perform_clear();
Harald Welte898113b2018-01-31 18:32:21 +01005527}
5528testcase TC_classmark() runs on test_CT {
5529 var MSC_ConnHdlr vc_conn;
5530 f_init(1, true);
5531 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005532 vc_conn := f_start_handler(refers(f_tc_classmark));
Harald Welte898113b2018-01-31 18:32:21 +01005533 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005534 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005535}
5536
Harald Welteeddf0e92020-06-21 19:42:15 +02005537/* Send a CommonID from the simulated MSC and verify that the information is used to
5538 * fill BSC-internal data structures (specifically, bsc_subscr associated with subscr_conn) */
5539private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
5540 g_pars := f_gen_test_hdlr_pars();
5541 f_MscConnHdlr_init_vty();
5542
5543 f_create_chan_and_exp();
5544 /* we should now have a COMPL_L3 at the MSC */
Harald Welteeddf0e92020-06-21 19:42:15 +02005545
5546 /* Send CommonID */
5547 BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
5548
5549 /* Use VTY to verify that the IMSI of the subscr_conn is set */
5550 var charstring regex := "*(IMSI: " & hex2str(g_pars.imsi) & ")*";
5551 f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
5552
5553 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005554
5555 f_perform_clear();
Harald Welteeddf0e92020-06-21 19:42:15 +02005556}
5557testcase TC_common_id() runs on test_CT {
5558 var MSC_ConnHdlr vc_conn;
5559 f_init(1, true);
5560 f_sleep(1.0);
5561 vc_conn := f_start_handler(refers(f_tc_common_id));
5562 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005563 f_shutdown_helper();
Harald Welteeddf0e92020-06-21 19:42:15 +02005564}
5565
Harald Weltee3bd6582018-01-31 22:51:25 +01005566private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005567 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005568 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005569 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005570
Harald Weltee3bd6582018-01-31 22:51:25 +01005571 /* send the single message we want to send */
5572 f_rsl_send_l3(l3);
5573}
5574
5575private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr {
5576 timer T := sec;
5577 var PDU_BSSAP bssap;
Harald Welte898113b2018-01-31 18:32:21 +01005578 T.start;
5579 alt {
Harald Weltee3bd6582018-01-31 22:51:25 +01005580 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap {
5581 setverdict(fail, "Unexpected BSSMAP ", bssap);
Daniel Willmannafce8662018-07-06 23:11:32 +02005582 mtc.stop;
Harald Welte898113b2018-01-31 18:32:21 +01005583 }
5584 [] T.timeout {
5585 setverdict(pass);
5586 }
5587 }
5588}
5589
Harald Weltee3bd6582018-01-31 22:51:25 +01005590/* unsolicited ASSIGNMENT FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5591private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
5592 f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
5593 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005594 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005595}
Harald Welte898113b2018-01-31 18:32:21 +01005596testcase TC_unsol_ass_fail() runs on test_CT {
5597 var MSC_ConnHdlr vc_conn;
5598 f_init(1, true);
5599 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005600 vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
Harald Welte898113b2018-01-31 18:32:21 +01005601 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005602 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005603}
Harald Welte552620d2017-12-16 23:21:36 +01005604
Harald Welteea99a002018-01-31 20:46:43 +01005605
5606/* unsolicited ASSIGNMENT COMPLETE (without ASSIGN) from MS shouldn't bring BSC down */
5607private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005608 f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
5609 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005610 f_perform_clear();
Harald Welteea99a002018-01-31 20:46:43 +01005611}
5612testcase TC_unsol_ass_compl() runs on test_CT {
5613 var MSC_ConnHdlr vc_conn;
5614 f_init(1, true);
5615 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005616 vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
Harald Welteea99a002018-01-31 20:46:43 +01005617 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005618 f_shutdown_helper();
Harald Welteea99a002018-01-31 20:46:43 +01005619}
5620
5621
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005622/* unsolicited HANDOVER FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5623private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005624 f_est_single_l3(ts_RRM_HandoverFailure('00'O));
5625 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005626 f_perform_clear();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005627}
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005628testcase TC_unsol_ho_fail() runs on test_CT {
5629 var MSC_ConnHdlr vc_conn;
5630 f_init(1, true);
5631 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005632 vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005633 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005634 f_shutdown_helper();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005635}
5636
5637
Harald Weltee3bd6582018-01-31 22:51:25 +01005638/* short message from MS should be ignored */
5639private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005640 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005641 f_create_chan_and_exp();
Harald Weltee3bd6582018-01-31 22:51:25 +01005642 /* we should now have a COMPL_L3 at the MSC */
Harald Weltee3bd6582018-01-31 22:51:25 +01005643
5644 /* send short message */
5645 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
5646 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005647 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005648}
5649testcase TC_err_82_short_msg() runs on test_CT {
5650 var MSC_ConnHdlr vc_conn;
5651 f_init(1, true);
5652 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005653 vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
Harald Weltee3bd6582018-01-31 22:51:25 +01005654 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005655 f_shutdown_helper();
Harald Weltee3bd6582018-01-31 22:51:25 +01005656}
5657
5658
Harald Weltee9e02e42018-01-31 23:36:25 +01005659/* 24.008 8.4 Unknown message must trigger RR STATUS */
5660private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
5661 f_est_single_l3(ts_RRM_UL_REL('00'O));
5662 timer T := 3.0
5663 alt {
5664 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
5665 setverdict(pass);
5666 }
5667 [] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
Harald Welte458fd372018-03-21 11:26:23 +01005668 [] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
Harald Weltee9e02e42018-01-31 23:36:25 +01005669 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005670 f_perform_clear();
Harald Weltee9e02e42018-01-31 23:36:25 +01005671}
5672testcase TC_err_84_unknown_msg() runs on test_CT {
5673 var MSC_ConnHdlr vc_conn;
5674 f_init(1, true);
5675 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005676 vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
Harald Weltee9e02e42018-01-31 23:36:25 +01005677 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005678 f_shutdown_helper();
Harald Weltee9e02e42018-01-31 23:36:25 +01005679}
5680
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005681/***********************************************************************
5682 * Handover
5683 ***********************************************************************/
5684
Harald Welte94e0c342018-04-07 11:33:23 +02005685/* execute a "bts <0-255> trx <0-255> timeslot <0-7> " command on given Dchan */
5686private function f_vty_ts_action(charstring suffix, integer bts_nr, integer trx_nr, integer ts_nr)
5687runs on test_CT {
5688 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5689 " timeslot "&int2str(ts_nr)&" ";
5690 f_vty_transceive(BSCVTY, cmd & suffix);
5691}
5692
Harald Welte261af4b2018-02-12 21:20:39 +01005693/* 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 +07005694private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
5695 uint8_t bts_nr, uint8_t trx_nr,
5696 in RslChannelNr chan_nr)
5697{
Harald Welte261af4b2018-02-12 21:20:39 +01005698 /* FIXME: resolve those from component-global state */
5699 var integer ts_nr := chan_nr.tn;
5700 var integer ss_nr;
5701 if (ischosen(chan_nr.u.ch0)) {
5702 ss_nr := 0;
5703 } else if (ischosen(chan_nr.u.lm)) {
5704 ss_nr := chan_nr.u.lm.sub_chan;
5705 } else if (ischosen(chan_nr.u.sdcch4)) {
5706 ss_nr := chan_nr.u.sdcch4.sub_chan;
5707 } else if (ischosen(chan_nr.u.sdcch8)) {
5708 ss_nr := chan_nr.u.sdcch8.sub_chan;
5709 } else {
5710 setverdict(fail, "Invalid ChanNr ", chan_nr);
Daniel Willmannafce8662018-07-06 23:11:32 +02005711 mtc.stop;
Harald Welte261af4b2018-02-12 21:20:39 +01005712 }
5713
5714 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5715 " timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005716 f_vty_transceive(pt, cmd & suffix);
Harald Welte261af4b2018-02-12 21:20:39 +01005717}
5718
Neels Hofmeyr91401012019-07-11 00:42:35 +02005719/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
5720 * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor
5721 * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
5722 * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
5723 * pair, not really to a specific BTS number. */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005724private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
5725 in RslChannelNr chan_nr, uint8_t new_bts_nr)
5726{
5727 f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
Harald Welte261af4b2018-02-12 21:20:39 +01005728}
5729
5730/* intra-BSC hand-over between BTS0 and BTS1 */
5731private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02005732 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5733 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte261af4b2018-02-12 21:20:39 +01005734
5735 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5736 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5737
Harald Weltea0630032018-03-20 21:09:55 +01005738 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005739 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Harald Welte261af4b2018-02-12 21:20:39 +01005740
5741 var HandoverState hs := {
5742 rr_ho_cmpl_seen := false,
5743 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005744 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005745 expect_target_tsc := c_BtsParams[1].tsc
Harald Welte261af4b2018-02-12 21:20:39 +01005746 };
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005747 /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005748 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
Harald Welte261af4b2018-02-12 21:20:39 +01005749 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5750 f_rslem_suspend(RSL1_PROC);
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005751
5752 /* From the MGW perspective, a handover is is characterized by
5753 * performing one MDCX operation with the MGW. So we expect to see
5754 * one more MDCX during handover. */
5755 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5756
Harald Welte261af4b2018-02-12 21:20:39 +01005757 alt {
5758 [] as_handover(hs);
Harald Welte261af4b2018-02-12 21:20:39 +01005759 }
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005760
Philipp Maier4dae0652018-11-12 12:03:26 +01005761 /* Since this is an internal handover we expect the BSC to inform the
5762 * MSC about the event */
5763 BSSAP.receive(tr_BSSMAP_HandoverPerformed);
5764
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005765 /* Check the amount of MGCP transactions is still consistant with the
5766 * test expectation */
5767 f_check_mgcp_expectations()
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005768
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005769 var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
5770
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005771 /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
5772 * 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 +02005773 f_verify_encr_info(chan_act);
5774
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005775 f_chan_act_verify_tsc(chan_act, c_BtsParams[1].tsc);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005776
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005777 f_perform_clear(RSL1, RSL1_PROC);
5778
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005779 f_sleep(0.5);
Harald Welte261af4b2018-02-12 21:20:39 +01005780}
5781
5782testcase TC_ho_int() runs on test_CT {
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005783 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte261af4b2018-02-12 21:20:39 +01005784 var MSC_ConnHdlr vc_conn;
5785 f_init(2, true);
5786 f_sleep(1.0);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005787
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005788 pars.expect_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005789
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005790 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005791
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005792 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
Harald Welte261af4b2018-02-12 21:20:39 +01005793 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005794
5795 /* from f_establish_fully() */
5796 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5797 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5798 /* from handover */
5799 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5800 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5801 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5802 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005803 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5804 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005805 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005806 f_shutdown_helper(ho := true);
Harald Welte261af4b2018-02-12 21:20:39 +01005807}
Harald Weltee9e02e42018-01-31 23:36:25 +01005808
Oliver Smith7eabd312021-07-12 14:18:56 +02005809function 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 +02005810 var MSC_ConnHdlr vc_conn;
5811 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5812 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
5813
5814 f_init(2, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02005815 f_vty_encryption_a5(enc_a5);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005816 f_sleep(1.0);
5817
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005818 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005819
5820 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
5821 vc_conn.done;
5822
5823 /* from f_establish_fully() */
5824 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5825 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5826 /* from handover */
5827 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5828 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5829 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5830 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005831 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5832 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005833 f_ctrs_bsc_and_bts_verify();
Oliver Smith7eabd312021-07-12 14:18:56 +02005834 f_vty_encryption_a5_reset();
Oliver Smith39f53072022-10-27 14:44:04 +02005835 f_shutdown_helper(ho := true);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005836}
5837
5838testcase TC_ho_int_a5_0() runs on test_CT {
5839 f_tc_ho_int_a5('01'O);
5840}
5841
5842testcase TC_ho_int_a5_1() runs on test_CT {
5843 f_tc_ho_int_a5('02'O);
5844}
5845
5846testcase TC_ho_int_a5_3() runs on test_CT {
5847 f_tc_ho_int_a5('08'O);
5848}
5849
5850testcase TC_ho_int_a5_4() runs on test_CT {
Oliver Smith7eabd312021-07-12 14:18:56 +02005851 f_tc_ho_int_a5('10'O, "0 1 3 4");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005852}
5853
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005854/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
5855private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
5856 g_pars := f_gen_test_hdlr_pars();
5857 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5858 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005859
5860 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5861 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5862
5863 f_establish_fully(ass_cmd, exp_compl);
5864 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
5865
5866 var HandoverState hs := {
5867 rr_ho_cmpl_seen := false,
5868 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005869 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005870 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005871 };
5872 /* issue hand-over command on VTY */
5873 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
5874 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5875 f_rslem_suspend(RSL1_PROC);
5876
5877 /* From the MGW perspective, a handover is is characterized by
5878 * performing one MDCX operation with the MGW. So we expect to see
5879 * one more MDCX during handover. */
5880 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5881
5882 var RSL_Message rsl;
5883 var PDU_ML3_NW_MS l3;
5884 var RslChannelNr new_chan_nr;
5885 var GsmArfcn arfcn;
5886 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
5887 l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
5888 if (not ischosen(l3.msgs.rrm.handoverCommand)) {
5889 setverdict(fail, "Expected handoverCommand");
5890 mtc.stop;
5891 }
5892 }
5893 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
5894 new_chan_nr, arfcn);
5895
5896 f_rslem_register(0, new_chan_nr, RSL1_PROC);
5897
5898 /* resume processing of RSL DChan messages, which was temporarily suspended
5899 * before performing a hand-over */
5900 f_rslem_resume(RSL1_PROC);
5901 RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
5902
5903 f_sleep(1.0);
5904
5905 /* Handover fails because no HANDO DET appears on the new lchan,
5906 * and the old lchan reports a Radio Link Failure. */
5907 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
5908
5909 var PDU_BSSAP rx_clear_request;
5910 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5911 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5912 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5913
5914 var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
5915
5916 var MgcpCommand mgcp;
5917 interleave {
5918 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
5919 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005920 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005921 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005922 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005923 }
5924 [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005925 [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005926 RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005927 f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005928 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005929 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5930 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5931 }
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005932 }
5933
5934 f_sleep(0.5);
5935 setverdict(pass);
5936}
5937testcase TC_ho_int_radio_link_failure() runs on test_CT {
5938 var MSC_ConnHdlr vc_conn;
5939 f_init(2, true);
5940 f_sleep(1.0);
5941
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005942 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005943
5944 vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
5945 vc_conn.done;
5946
5947 /* from f_establish_fully() */
5948 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5949 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5950 /* from handover */
5951 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5952 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
5953 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5954 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005955 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5956 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005957 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005958 f_shutdown_helper(ho := true);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005959}
5960
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005961/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005962private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005963 var MgcpCommand mgcp;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005964 var template MgcpResponse mgcp_resp;
5965 var MGCP_RecvFrom mrf;
5966 var template MgcpMessage msg_resp;
5967 var template MgcpMessage msg_dlcx := {
5968 command := tr_DLCX()
5969 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005970
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005971 if (g_pars.aoip) {
5972 MGCP.receive(tr_DLCX()) -> value mgcp {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005973 log("Got first DLCX: ", mgcp);
5974 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005975 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005976
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005977 MGCP.receive(tr_DLCX()) -> value mgcp {
5978 log("Got second DLCX: ", mgcp);
5979 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
5980 };
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005981 } else {
5982 /* For SCCPLite, BSC doesn't handle the MSC-side */
5983 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
5984 log("Got first DLCX: ", mrf.msg.command);
5985 msg_resp := {
5986 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
5987 }
5988 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
5989 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005990 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005991}
5992
Oliver Smithc9a5f532022-10-21 11:32:23 +02005993private function f_ho_out_of_this_bsc(template (omit) BSSMAP_oldToNewBSSIEs exp_oldToNewBSSIEs := omit,
5994 boolean skip_meas_rep := false) runs on MSC_ConnHdlr {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005995
Oliver Smithc9a5f532022-10-21 11:32:23 +02005996 if (not skip_meas_rep) {
5997 var NcellReports neighbor_rep := {
5998 { rxlev := 20, bcch_freq := 0, bsic := 11 }
5999 };
6000 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
6001 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
6002 l3_mr, 0));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006003
Oliver Smithc9a5f532022-10-21 11:32:23 +02006004 BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
6005 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006006
6007 f_sleep(0.5);
6008 /* The MSC negotiates Handover Request and Handover Request Ack with
6009 * the other BSS and comes back with a BSSMAP Handover Command
6010 * containing an RR Handover Command coming from the target BSS... */
6011
6012 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6013 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6014 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6015 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6016 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6017
6018 /* expect the Handover Command to go out on RR */
6019 var RSL_Message rsl_ho_cmd
6020 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6021 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6022 var RSL_IE_Body rsl_ho_cmd_l3;
6023 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6024 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6025 setverdict(fail);
6026 } else {
6027 log("Found L3 Info: ", rsl_ho_cmd_l3);
6028 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6029 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6030 setverdict(fail);
6031 } else {
6032 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6033 setverdict(pass);
6034 }
6035 }
6036
6037 /* When the other BSS has reported a completed handover, this side is
6038 * torn down. */
6039
6040 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_HANDOVER_SUCCESSFUL;
6041 var BssmapCause cause := enum2int(cause_val);
6042 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6043
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006044 f_expect_dlcx_conns();
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006045
6046 interleave {
6047 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
6048 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
6049 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006050 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
6051 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
6052 }
Pau Espin Pedrol06199952021-06-15 11:30:00 +02006053 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006054 setverdict(pass);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006055}
6056
6057private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
6058 g_pars := f_gen_test_hdlr_pars();
6059 var PDU_BSSAP ass_req := f_gen_ass_req();
6060 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6061 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6062 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6063 f_establish_fully(ass_req, exp_compl);
6064
6065 f_ho_out_of_this_bsc();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006066}
6067testcase TC_ho_out_of_this_bsc() runs on test_CT {
6068 var MSC_ConnHdlr vc_conn;
6069
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006070 f_init_vty();
6071 f_bts_0_cfg(BSCVTY,
6072 {"neighbor-list mode automatic",
6073 "handover 1",
6074 "handover algorithm 2",
6075 "handover2 window rxlev averaging 1",
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006076 "no neighbors",
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006077 "neighbor lac 99 arfcn 123 bsic any"});
6078 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6079
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006080 f_init(1, true);
6081 f_sleep(1.0);
6082
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006083 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006084
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006085 vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
6086 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006087
6088 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6089 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6090 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6091 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6092 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6093 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
6094 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006095 f_shutdown_helper(ho := true);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006096}
6097
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006098private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6099 template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
Vadim Yanitskiy2ef6a2f2020-10-08 23:17:32 +07006100 template (present) OCT1 dlci := ?,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006101 octetstring l3 := '0123456789'O)
6102runs on MSC_ConnHdlr {
Neels Hofmeyr43654812020-09-25 01:35:35 +02006103 /* The old lchan and conn should still be active. See that arbitrary L3
6104 * is still going through. */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006105 rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
Neels Hofmeyr43654812020-09-25 01:35:35 +02006106 var template PDU_BSSAP exp_data := {
6107 discriminator := '1'B,
6108 spare := '0000000'B,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006109 dlci := dlci,
6110 lengthIndicator := lengthof(l3),
Neels Hofmeyr43654812020-09-25 01:35:35 +02006111 pdu := {
6112 dtap := l3
6113 }
6114 };
6115 BSSAP.receive(exp_data);
6116 setverdict(pass);
6117}
6118
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006119private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6120 template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006121 template (value) OCT1 dlci := '00'O,
6122 octetstring l3 := '0123456789'O)
6123runs on MSC_ConnHdlr {
6124 BSSAP.send(PDU_BSSAP:{
6125 discriminator := '1'B,
6126 spare := '0000000'B,
6127 dlci := dlci,
6128 lengthIndicator := lengthof(l3),
6129 pdu := {
6130 dtap := l3
6131 }
6132 });
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006133 rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006134 setverdict(pass);
6135}
6136
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006137/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
6138 * simply never sends a BSSMAP Handover Command. */
6139private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006140 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006141
6142 var PDU_BSSAP ass_req := f_gen_ass_req();
6143 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6144 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6145 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6146 f_establish_fully(ass_req, exp_compl);
6147
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006148 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006149 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6150
6151 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6152
6153 /* osmo-bsc should time out 10 seconds after the handover started.
6154 * Let's give it a bit extra. */
6155 f_sleep(15.0);
6156
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006157 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006158 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006159 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006160}
6161testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
6162 var MSC_ConnHdlr vc_conn;
6163
6164 f_init(1, true);
6165 f_sleep(1.0);
6166
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006167 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006168
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006169 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
6170 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006171
6172 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6173 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6174 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6175 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6176 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6177 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6178 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006179 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006180}
6181
6182/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
6183 * RR Handover Failure. */
6184private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006185 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006186
6187 var PDU_BSSAP ass_req := f_gen_ass_req();
6188 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6189 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6190 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6191 f_establish_fully(ass_req, exp_compl);
6192
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006193 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006194 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6195
6196 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6197
6198 f_sleep(0.5);
6199 /* The MSC negotiates Handover Request and Handover Request Ack with
6200 * the other BSS and comes back with a BSSMAP Handover Command
6201 * containing an RR Handover Command coming from the target BSS... */
6202
6203 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6204 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6205 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6206 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6207 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6208
6209 /* expect the Handover Command to go out on RR */
6210 var RSL_Message rsl_ho_cmd
6211 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6212 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6213 var RSL_IE_Body rsl_ho_cmd_l3;
6214 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6215 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6216 setverdict(fail);
6217 } else {
6218 log("Found L3 Info: ", rsl_ho_cmd_l3);
6219 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6220 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6221 setverdict(fail);
6222 } else {
6223 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6224 setverdict(pass);
6225 }
6226 }
6227
6228 f_sleep(0.2);
6229 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
6230
6231 /* Should tell the MSC about the failure */
6232 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6233
6234 f_sleep(1.0);
6235
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006236 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006237 f_sleep(1.0);
6238
6239 setverdict(pass);
6240 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006241 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006242}
6243testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
6244 var MSC_ConnHdlr vc_conn;
6245
6246 f_init(1, true);
6247 f_sleep(1.0);
6248
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006249 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006250
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006251 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
6252 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006253
6254 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6255 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6256 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6257 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6258 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6259 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
6260 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006261 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006262}
6263
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006264/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
6265 * (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 +02006266 * and the lchan is released. */
6267private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006268 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006269
6270 var PDU_BSSAP ass_req := f_gen_ass_req();
6271 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6272 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6273 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6274 f_establish_fully(ass_req, exp_compl);
6275
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006276 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006277 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6278
6279 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6280
6281 f_sleep(0.5);
6282 /* The MSC negotiates Handover Request and Handover Request Ack with
6283 * the other BSS and comes back with a BSSMAP Handover Command
6284 * containing an RR Handover Command coming from the target BSS... */
6285
6286 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6287 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6288 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6289 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6290 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6291
6292 /* expect the Handover Command to go out on RR */
6293 var RSL_Message rsl_ho_cmd
6294 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6295 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6296 var RSL_IE_Body rsl_ho_cmd_l3;
6297 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6298 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6299 setverdict(fail);
6300 } else {
6301 log("Found L3 Info: ", rsl_ho_cmd_l3);
6302 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6303 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6304 setverdict(fail);
6305 } else {
6306 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6307 setverdict(pass);
6308 }
6309 }
6310
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006311 /* We get neither success nor failure report from the remote BSS. Eventually T8 times out and we run into 3GPP
6312 * TS 48.008 3.1.5.3.3 "Abnormal Conditions": Clear Request should go to the MSC, and RR should be released
6313 * after Clear Command */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006314
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006315 var PDU_BSSAP rx_clear_request;
Neels Hofmeyre1797aa2019-07-09 19:34:04 +02006316 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
6317 log("Got BSSMAP Clear Request");
6318 /* Instruct BSC to clear channel */
6319 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6320 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6321
6322 var MgcpCommand mgcp;
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006323 interleave {
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01006324 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
6325 log("Got Deact SACCH");
6326 }
Harald Welte924b6ea2019-02-04 01:05:34 +01006327 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
Neels Hofmeyr211169d2018-11-07 00:37:29 +01006328 log("Got RR Release");
6329 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02006330 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006331 log("Got RF Chan Rel");
6332 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02006333 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006334 }
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006335 }
6336
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006337 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006338 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006339 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006340
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006341 setverdict(pass);
6342 f_sleep(1.0);
6343}
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006344testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006345 var MSC_ConnHdlr vc_conn;
6346
6347 f_init(1, true);
6348 f_sleep(1.0);
6349
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006350 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006351
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006352 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006353 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006354
6355 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6356 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6357 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6358 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6359 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6360 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6361 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006362 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006363}
6364
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006365private 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 +01006366 var PDU_BSSAP rx_bssap;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006367 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6368 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6369 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6370 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6371 * before we get started. */
6372 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6373 f_rslem_register(0, new_chan_nr);
6374 g_chan_nr := new_chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06006375 var uint3_t expect_target_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006376 f_sleep(1.0);
6377
6378 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6379 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006380 var default as_media := activate(as_Media());
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006381
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01006382 var PDU_BSSAP ho_req := f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
6383 cell_id_source := g_pars.cell_id_source,
6384 oldToNewBSSIEs := oldToNewBSSIEs,
6385 enc := g_pars.encr);
6386 if (g_pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr) {
6387 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, ho_req));
6388 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6389 } else {
6390 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, omit));
6391 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6392 BSSAP.send(ho_req);
6393 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006394
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006395 alt {
6396 [] BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap {
6397 if (g_pars.expect_ho_fail) {
6398 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6399 "Expected Handover Request to fail, but got Handover Request Ack")
6400 }
6401 }
6402 [] BSSAP.receive(tr_BSSMAP_HandoverFailure) -> value rx_bssap {
6403 if (not g_pars.expect_ho_fail) {
6404 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6405 "Expected Handover Request to succeed, but got Handover Failure")
6406 }
6407 // TODO: evaluate correct cause value. But osmo-bsc doesn't seem to send meaningful causes yet!
6408 // For now just accept any cause.
6409 BSSAP.receive(tr_BSSMAP_ClearRequest);
6410 setverdict(pass);
6411 return;
6412 }
6413 }
6414
Oliver Smith7a8594a2023-02-13 14:30:49 +01006415 if (g_pars.expect_ho_fail_lchan_est) {
6416 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6417 setverdict(pass);
Oliver Smitha1cbec52023-02-21 12:44:12 +01006418
6419 /* When we let MGCP MDCX run into a timeout, it's still in the
6420 * queue and additionally after BSSAP HandoverFailure, two DLCX
Oliver Smith30eb8822023-03-06 12:31:53 +01006421 * get sent (for AoIP, for SCCPlite one DLCX). */
Oliver Smitha1cbec52023-02-21 12:44:12 +01006422 if (g_pars.ignore_mgw_mdcx) {
Oliver Smith30eb8822023-03-06 12:31:53 +01006423 if (g_pars.aoip) {
6424 MGCP.receive(tr_MDCX);
6425 MGCP.receive(tr_DLCX);
6426 MGCP.receive(tr_DLCX);
6427 } else {
6428 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_MDCX}));
6429 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_DLCX}));
6430 }
Oliver Smitha1cbec52023-02-21 12:44:12 +01006431 }
Oliver Smith7a8594a2023-02-13 14:30:49 +01006432 return;
6433 }
6434
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006435 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6436
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006437 /* we're sure that the channel activation is done now, verify the parameters in it */
6438 var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
6439 f_verify_encr_info(chan_act);
6440 f_chan_act_verify_tsc(chan_act, expect_target_tsc);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006441
Neels Hofmeyr46e16e52022-02-23 17:04:00 +01006442 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.codecList)) {
6443 if (not g_pars.aoip) {
6444 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6445 "handoverRequestAck: Expected no Speech Codec List (BSS Supported), because this is not AoIP");
6446 }
6447 /* TODO: check actual codecs? */
6448 } else {
6449 if (g_pars.aoip) {
6450 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6451 "handoverRequestAck: Expected Speech Codec List (BSS Supported), but none found");
6452 }
6453 }
6454
6455 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.speechCodec)) {
6456 if (not g_pars.aoip) {
6457 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6458 "handoverRequestAck: Expected no Speech Codec (Chosen), because this is not AoIP");
6459 }
6460 /* TODO: check actual codec? */
6461 } else {
6462 if (g_pars.aoip) {
6463 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6464 "handoverRequestAck: Expected Speech Codec (Chosen), but none found");
6465 }
6466 }
6467
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006468 var octetstring ho_command_str;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006469 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6470 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6471 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6472 log("L3 Info in HO Request Ack is ", ho_command);
6473
6474 var GsmArfcn arfcn;
6475 var RslChannelNr actual_new_chan_nr;
6476 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6477 actual_new_chan_nr, arfcn);
6478
6479 if (actual_new_chan_nr != new_chan_nr) {
6480 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6481 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6482 setverdict(fail);
6483 return;
6484 }
6485 log("Handover Command chan_nr is", actual_new_chan_nr);
6486
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006487 var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
6488 if (not match(got_tsc, expect_target_tsc)) {
6489 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6490 expect_target_tsc, " got ", got_tsc);
6491 mtc.stop;
6492 } else {
6493 log("handoverCommand: verified TSC = ", got_tsc);
6494 }
6495
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006496 /* Check the Cipher Mode Setting IE (shall be present during inter-RAT handover) */
6497 if (ispresent(ho_command.msgs.rrm.handoverCommand.cipherModeSetting)) {
6498 var CipherModeSetting_TV cms := ho_command.msgs.rrm.handoverCommand.cipherModeSetting;
6499 var template (present) CipherModeSetting_TV tr_cms := {
6500 sC := '0'B, /* no ciphering by default */
6501 algorithmIdentifier := '000'B,
6502 elementIdentifier := ?
6503 };
6504 if (ispresent(g_pars.encr) and g_pars.encr.enc_alg_expect != '01'O) { /* A5/N */
6505 tr_cms.algorithmIdentifier := f_cipher_mode_bssmap_to_rr(g_pars.encr.enc_alg_expect);
6506 tr_cms.sC := '1'B;
6507 }
6508 if (not match(cms, tr_cms)) {
6509 setverdict(fail, "RR Handover Command: unexpected Cipher Mode Setting IE: ",
6510 cms, ", expected: ", tr_cms);
6511 }
6512 } else {
6513 setverdict(fail, "RR Handover Command: Cipher Mode Setting IE is not present");
6514 }
6515
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006516 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6517 * tells the MS to handover to the new lchan. Here comes the new MS on
6518 * the new lchan with a Handover RACH: */
6519
6520 /* send handover detect */
6521
6522 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6523
6524 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6525
6526 /* send handover complete over the new channel */
6527
6528 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_HandoverComplete('00'O));
6529 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
6530 enc_PDU_ML3_MS_NW(l3_tx)));
6531
6532 BSSAP.receive(tr_BSSMAP_HandoverComplete);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006533 deactivate(as_media);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006534 setverdict(pass);
6535}
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006536
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006537private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006538 var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006539 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
6540 if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
6541 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006542 }
6543 if (g_pars.exp_fast_return) {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006544 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006545 } else {
6546 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006547 }
6548 f_ho_into_this_bsc(id, oldToNewBSSIEs);
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006549 if (g_pars.expect_ho_fail) {
6550 f_perform_clear_no_lchan();
Oliver Smith7a8594a2023-02-13 14:30:49 +01006551 } else if (g_pars.expect_ho_fail_lchan_est) {
6552 BSSAP.receive(tr_BSSMAP_ClearRequest);
6553 f_perform_clear_no_lchan();
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006554 } else {
6555 f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
6556 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006557 setverdict(pass);
6558}
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006559function 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 +01006560 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006561
6562 f_init(1, true);
6563 f_sleep(1.0);
6564
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006565 f_vty_encryption_a5(vty_a5_cfg);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006566 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006567
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006568 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6569 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006570
6571 vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
6572 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006573
6574 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006575 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006576 if (pars.expect_ho_fail) {
6577 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6578 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:failed");
Oliver Smith7a8594a2023-02-13 14:30:49 +01006579 } else if (pars.expect_ho_fail_lchan_est) {
6580 f_ctrs_bsc_and_bts_add(0, "handover:error");
6581 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006582 } else {
6583 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6584 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
6585 }
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006586 f_ctrs_bsc_and_bts_verify();
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006587
6588 f_vty_encryption_a5_reset();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006589}
6590
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006591testcase TC_ho_into_this_bsc() runs on test_CT {
6592 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6593 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006594 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006595}
6596
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006597function f_tc_ho_into_this_bsc_a5(TestHdlrEncrParams encr, charstring vty_a5_cfg := VTY_A5_DEFAULT,
6598 boolean expect_fail := false) runs on test_CT {
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006599 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006600 pars.encr := encr;
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006601 pars.expect_ho_fail := expect_fail;
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006602 f_tc_ho_into_this_bsc_main(pars, vty_a5_cfg);
Oliver Smith39f53072022-10-27 14:44:04 +02006603 f_shutdown_helper(ho := true);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006604}
6605
6606testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006607 f_tc_ho_into_this_bsc_a5(f_encr_params('01'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006608}
6609
6610testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006611 f_tc_ho_into_this_bsc_a5(f_encr_params('02'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006612}
6613
6614testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006615 f_tc_ho_into_this_bsc_a5(f_encr_params('08'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006616}
6617
6618testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006619 f_tc_ho_into_this_bsc_a5(f_encr_params('10'O, kc128 := true), "3 4");
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006620}
6621
Neels Hofmeyr1951be22022-02-16 16:21:07 +01006622/* Report: in inter-BSC incoming handover, when the MSC omits the Chosen Encryption Algorithm IE in the Handover Request
6623 * message, then osmo-bsc starts an unencrypted lchan even if A5/0 is not permitted.
6624 *
6625 * This test verifies that the Encryption Information is present in the Channel Activation when the Chosen Enc Alg is
6626 * omitted.
6627 *
6628 * Related: SYS#5839
6629 */
6630testcase TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() runs on test_CT {
6631 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O, alg_chosen := omit));
6632}
6633
6634testcase TC_ho_into_this_bsc_a5_1_3() runs on test_CT {
6635 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O));
6636}
6637
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006638/* Send a permitted algo mask that does not intersect with osmo-bsc.cfg */
6639testcase TC_ho_into_this_bsc_a5_mismatch() runs on test_CT {
6640 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '18'O, alg_expect := '10'O), "0 1",
6641 expect_fail := true); // 0x18 = A5/3 and A5/4
6642}
6643
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006644testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
6645 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6646 pars.host_aoip_tla := "::6";
6647 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006648 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006649}
6650
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006651/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006652 to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006653 channel is later released (RR CHannel Release), should trigger inclusion of
6654 IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
6655 neighbors. */
6656testcase TC_srvcc_eutran_to_geran() runs on test_CT {
6657 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6658 pars.last_used_eutran_plmn := '323454'O;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006659 pars.exp_fast_return := true;
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006660 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006661
6662 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6663 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6664 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006665 f_shutdown_helper(ho := true);
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006666}
6667
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006668/* Same as TC_srvcc_eutran_to_geran, but enables ciphering on the target channel. */
6669testcase TC_srvcc_eutran_to_geran_a5_3() runs on test_CT {
6670 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6671 pars.encr := f_encr_params('08'O); /* only A5/3 */
6672 pars.last_used_eutran_plmn := '323454'O;
6673 pars.exp_fast_return := true;
6674 f_tc_ho_into_this_bsc_main(pars);
6675
6676 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6677 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6678 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006679 f_shutdown_helper(ho := true);
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006680}
6681
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006682/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
6683 on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
6684 list when the channel is released. */
6685testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
6686 f_init_vty();
6687 f_vty_allow_srvcc_fast_return(true, 0)
6688
6689 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6690 pars.last_used_eutran_plmn := '323454'O;
6691 pars.exp_fast_return := false;
6692 f_tc_ho_into_this_bsc_main(pars);
6693 f_vty_allow_srvcc_fast_return(false, 0);
6694 f_shutdown_helper();
6695}
6696
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01006697/* Same as TC_srvcc_eutran_to_geran, but using SAI as serving Cell Identifier. SYS#5838 */
6698testcase TC_srvcc_eutran_to_geran_src_sai() runs on test_CT {
6699 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6700 pars.last_used_eutran_plmn := '323454'O;
6701 pars.cell_id_source := valueof(ts_CellID_SAI('123456'O, 300, 444));
6702 f_tc_ho_into_this_bsc_main(pars);
6703
6704 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6705 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6706 f_ctrs_bsc_and_bts_verify();
6707 f_shutdown_helper();
6708}
6709
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006710private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
6711 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
6712 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
6713 f_ho_into_this_bsc(id, oldToNewBSSIEs);
6714 f_ho_out_of_this_bsc(oldToNewBSSIEs);
6715 setverdict(pass);
6716}
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006717
6718private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
6719 runs on test_CT {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006720 var MSC_ConnHdlr vc_conn;
6721 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6722
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006723 f_init_vty();
6724 f_bts_0_cfg(BSCVTY,
6725 {"neighbor-list mode automatic",
6726 "handover 1",
6727 "handover algorithm 2",
6728 "handover2 window rxlev averaging 1",
6729 "no neighbors",
6730 "neighbor lac 99 arfcn 123 bsic any"});
6731 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6732
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006733 f_init(1, true);
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006734 if (disable_fast_return) {
6735 f_vty_allow_srvcc_fast_return(true, 0);
6736 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006737 f_sleep(1.0);
6738
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006739 f_ctrs_bsc_and_bts_handover_init();
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006740
6741 pars.last_used_eutran_plmn := '323454'O;
6742 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6743 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
6744
6745 vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
6746 vc_conn.done;
6747
6748 f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
6749 f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
6750 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
6751 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
6752 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
6753 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006754
6755 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
6756 f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006757 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006758
6759 if (disable_fast_return) {
6760 f_vty_allow_srvcc_fast_return(false, 0);
6761 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006762 f_shutdown_helper();
6763}
6764
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006765/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
6766 BSS Information" IE with "Last Used E-UTRAN PLMN Id".
6767 Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
6768 IE with "Last Used E-UTRAN PLMN Id" from first step. */
6769testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
6770 f_tc_srvcc_eutran_to_geran_ho_out_main(false);
6771}
6772/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
6773 * independently of fast-reture allowed/forbidden in local BTS */
6774testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
6775 f_tc_srvcc_eutran_to_geran_ho_out_main(true);
6776}
6777
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006778private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
6779 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6780 f_rslem_register(0, new_chan_nr);
6781 g_chan_nr := new_chan_nr;
6782 f_sleep(1.0);
6783
6784 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6785 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6786 activate(as_Media());
6787
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006788 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006789 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006790 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006791
6792 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6793
6794 var PDU_BSSAP rx_bssap;
6795 var octetstring ho_command_str;
6796
6797 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6798
6799 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6800 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6801 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6802 log("L3 Info in HO Request Ack is ", ho_command);
6803
6804 var GsmArfcn arfcn;
6805 var RslChannelNr actual_new_chan_nr;
6806 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6807 actual_new_chan_nr, arfcn);
6808
6809 if (actual_new_chan_nr != new_chan_nr) {
6810 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6811 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6812 setverdict(fail);
6813 return;
6814 }
6815 log("Handover Command chan_nr is", actual_new_chan_nr);
6816
Neels Hofmeyr61ca08d2019-05-06 23:52:22 +02006817 /* For deterministic test results, give some time for the MGW endpoint to be configured */
6818 f_sleep(1.0);
6819
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006820 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6821 * tells the MS to handover to the new lchan. In this case, the MS
6822 * reports a Handover Failure to the old BSS, which forwards a BSSMAP
6823 * Handover Failure to the MSC. The procedure according to 3GPP TS
6824 * 48.008 3.1.5.3.2 "Handover Failure" is then that the MSC sends a
6825 * BSSMAP Clear Command: */
6826
6827 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6828 var BssmapCause cause := enum2int(cause_val);
6829 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6830
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006831 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006832 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006833 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006834
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006835 setverdict(pass);
6836 f_sleep(1.0);
6837
6838 setverdict(pass);
6839}
6840testcase TC_ho_in_fail_msc_clears() runs on test_CT {
6841 var MSC_ConnHdlr vc_conn;
6842 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6843
6844 f_init(1, true);
6845 f_sleep(1.0);
6846
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006847 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006848
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006849 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6850 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006851
6852 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
6853 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006854
6855 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6856 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6857 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6858 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6859 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006860 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006861}
6862
6863private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
6864 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6865 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6866 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6867 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6868 * before we get started. */
6869 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6870 f_rslem_register(0, new_chan_nr);
6871 g_chan_nr := new_chan_nr;
6872 f_sleep(1.0);
6873
6874 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6875 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6876 activate(as_Media());
6877
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006878 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006879 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006880 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006881
6882 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6883
6884 var PDU_BSSAP rx_bssap;
6885 var octetstring ho_command_str;
6886
6887 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6888
6889 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6890 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6891 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6892 log("L3 Info in HO Request Ack is ", ho_command);
6893
6894 var GsmArfcn arfcn;
6895 var RslChannelNr actual_new_chan_nr;
6896 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6897 actual_new_chan_nr, arfcn);
6898
6899 if (actual_new_chan_nr != new_chan_nr) {
6900 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6901 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6902 setverdict(fail);
6903 return;
6904 }
6905 log("Handover Command chan_nr is", actual_new_chan_nr);
6906
6907 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6908 * tells the MS to handover to the new lchan. Here comes the new MS on
6909 * the new lchan with a Handover RACH: */
6910
6911 /* send handover detect */
6912
6913 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6914
6915 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6916
6917 /* The MSC chooses to clear the connection now, maybe we got the
6918 * Handover RACH on the new cell but the MS still signaled Handover
6919 * Failure to the old BSS? */
6920
6921 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6922 var BssmapCause cause := enum2int(cause_val);
6923 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6924
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006925 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006926 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006927 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006928
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006929 f_sleep(1.0);
6930}
6931testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
6932 var MSC_ConnHdlr vc_conn;
6933 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6934
6935 f_init(1, true);
6936 f_sleep(1.0);
6937
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006938 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006939
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006940 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6941 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006942
6943 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
6944 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006945
6946 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6947 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6948 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6949 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6950 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006951 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006952}
6953
6954/* The new BSS's lchan times out before the MSC decides that handover failed. */
6955private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
6956 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6957 f_rslem_register(0, new_chan_nr);
6958 g_chan_nr := new_chan_nr;
6959 f_sleep(1.0);
6960
6961 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6962 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01006963 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006964
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006965 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006966 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006967 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006968
6969 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6970
6971 var PDU_BSSAP rx_bssap;
6972 var octetstring ho_command_str;
6973
6974 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6975
6976 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6977 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6978 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6979 log("L3 Info in HO Request Ack is ", ho_command);
6980
6981 var GsmArfcn arfcn;
6982 var RslChannelNr actual_new_chan_nr;
6983 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6984 actual_new_chan_nr, arfcn);
6985
6986 if (actual_new_chan_nr != new_chan_nr) {
6987 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6988 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6989 setverdict(fail);
6990 return;
6991 }
6992 log("Handover Command chan_nr is", actual_new_chan_nr);
6993
6994 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6995 * tells the MS to handover to the new lchan. But the MS never shows up
6996 * on the new lchan. */
6997
6998 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6999
7000 /* Did osmo-bsc also send a Clear Request? */
7001 timer T := 0.5;
7002 T.start;
7003 alt {
7004 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
7005 [] T.timeout { }
7006 }
7007
7008 /* MSC plays along with a Clear Command (no matter whether osmo-bsc
7009 * asked for it, this is a Handover Failure after all). */
7010
7011 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
7012 var BssmapCause cause := enum2int(cause_val);
7013 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7014
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007015 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007016 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007017 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007018
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007019 f_sleep(1.0);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007020}
7021testcase TC_ho_in_fail_no_detect() runs on test_CT {
7022 var MSC_ConnHdlr vc_conn;
7023 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7024
Oliver Smithd49f46d2023-03-08 12:23:13 +01007025 pars.fail_on_dlcx := false;
7026
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007027 f_init(1, true);
7028 f_sleep(1.0);
7029
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007030 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007031
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007032 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7033 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007034
7035 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect), pars);
7036 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007037
7038 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7039 f_ctrs_bsc_and_bts_add(0, "handover:error");
7040 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7041 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7042 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007043 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007044}
7045
7046/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
7047private function f_tc_ho_in_fail_no_detect2(charstring id) runs on MSC_ConnHdlr {
7048 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
7049 f_rslem_register(0, new_chan_nr);
7050 g_chan_nr := new_chan_nr;
7051 f_sleep(1.0);
7052
7053 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
7054 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Oliver Smith735b47c2023-02-15 16:03:54 +01007055 activate(as_Media());
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007056
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007057 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007058 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02007059 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007060
7061 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
7062
7063 var PDU_BSSAP rx_bssap;
7064 var octetstring ho_command_str;
7065
7066 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
7067
7068 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
7069 log("Received L3 Info in HO Request Ack: ", ho_command_str);
7070 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
7071 log("L3 Info in HO Request Ack is ", ho_command);
7072
7073 var GsmArfcn arfcn;
7074 var RslChannelNr actual_new_chan_nr;
7075 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
7076 actual_new_chan_nr, arfcn);
7077
7078 if (actual_new_chan_nr != new_chan_nr) {
7079 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
7080 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
7081 setverdict(fail);
7082 return;
7083 }
7084 log("Handover Command chan_nr is", actual_new_chan_nr);
7085
7086 /* Now the MSC forwards the RR Handover Command to the other BSC, which
7087 * tells the MS to handover to the new lchan. But the MS never shows up
7088 * on the new lchan. */
7089
7090 BSSAP.receive(tr_BSSMAP_HandoverFailure);
7091
7092 /* MSC plays dumb and sends no Clear Command */
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007093 var PDU_BSSAP rx_clear_request;
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02007094
7095 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request {
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007096 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
7097 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7098 };
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007099 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007100 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007101 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007102
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007103 f_sleep(1.0);
7104}
7105testcase TC_ho_in_fail_no_detect2() runs on test_CT {
7106 var MSC_ConnHdlr vc_conn;
7107 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7108
Oliver Smith735b47c2023-02-15 16:03:54 +01007109 pars.fail_on_dlcx := false;
7110
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007111 f_init(1, true);
7112 f_sleep(1.0);
7113
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007114 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007115
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007116 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7117 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007118
7119 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
7120 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007121
7122 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7123 f_ctrs_bsc_and_bts_add(0, "handover:error");
7124 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7125 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7126 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007127 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007128}
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01007129
Oliver Smith7a8594a2023-02-13 14:30:49 +01007130testcase TC_ho_in_fail_mgw_mdcx_timeout() runs on test_CT {
7131 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7132
7133 pars.ignore_mgw_mdcx := true;
7134 pars.expect_ho_fail_lchan_est := true;
7135
7136 f_tc_ho_into_this_bsc_main(pars);
7137 f_shutdown_helper(ho := true);
7138}
7139
Oliver Smith4eed06f2023-02-15 15:43:19 +01007140testcase TC_ho_in_fail_ipa_crcx_timeout() runs on test_CT {
7141 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7142
7143 pars.ignore_ipa_media := true;
7144 pars.expect_ho_fail_lchan_est := true;
7145 pars.fail_on_dlcx := false;
7146
7147 f_tc_ho_into_this_bsc_main(pars);
7148 f_shutdown_helper(ho := true);
7149}
7150
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007151/* An incoming inter-BSC HO can either issue the Handover Request message attached to the initial SCCP N-Connect (as in
7152 * the other tests we have so far), or the first CR can be "empty" with the BSSAP request following later. Test the
7153 * empty N-Connect case. */
7154testcase TC_ho_into_this_bsc_sccp_cr_without_bssap() runs on test_CT {
7155 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7156 pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr := false;
7157 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02007158 f_shutdown_helper(ho := true);
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007159}
7160
Neels Hofmeyr91401012019-07-11 00:42:35 +02007161type record of charstring Commands;
7162
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007163private function f_bts_0_cfg(TELNETasp_PT pt, Commands cmds := {})
Neels Hofmeyr91401012019-07-11 00:42:35 +02007164{
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007165 f_vty_enter_cfg_bts(pt, 0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007166 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007167 f_vty_transceive(pt, cmds[i]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007168 }
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007169 f_vty_transceive(pt, "end");
Neels Hofmeyr91401012019-07-11 00:42:35 +02007170}
7171
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01007172private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
7173{
7174 f_vty_enter_cfg_cs7_inst(pt, 0);
7175 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
7176 f_vty_transceive(pt, cmds[i]);
7177 }
7178 f_vty_transceive(pt, "end");
7179}
7180
Neels Hofmeyr91401012019-07-11 00:42:35 +02007181private function f_probe_for_handover(charstring log_label,
7182 charstring log_descr,
7183 charstring handover_vty_cmd,
7184 boolean expect_handover,
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007185 boolean is_inter_bsc_handover := false,
7186 template uint3_t expect_target_tsc := ?)
Neels Hofmeyr91401012019-07-11 00:42:35 +02007187runs on MSC_ConnHdlr
7188{
Neels Hofmeyrb3fc8982020-05-11 00:16:42 +02007189 /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
7190 * lchans to be established on bts 1 or bts 2. */
7191 f_rslem_suspend(RSL1_PROC);
7192 f_rslem_suspend(RSL2_PROC);
7193
Neels Hofmeyr91401012019-07-11 00:42:35 +02007194 var RSL_Message rsl;
7195
7196 var charstring log_msg := " (expecting handover)"
7197 if (not expect_handover) {
7198 log_msg := " (expecting NO handover)";
7199 }
7200 log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg);
7201 f_vty_transceive(BSCVTY, handover_vty_cmd);
7202
Neels Hofmeyr91401012019-07-11 00:42:35 +02007203 timer T := 2.0;
7204 T.start;
7205
7206 alt {
7207 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
7208 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
7209 log("Rx L3 from net: ", l3);
7210 if (ischosen(l3.msgs.rrm.handoverCommand)) {
7211 var RslChannelNr new_chan_nr;
7212 var GsmArfcn arfcn;
7213 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
7214 new_chan_nr, arfcn);
7215 log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
7216 log(l3.msgs.rrm.handoverCommand);
7217
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007218 /* Verify correct TSC in handoverCommand */
7219 var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
7220 if (not match(got_tsc, expect_target_tsc)) {
7221 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
7222 expect_target_tsc, " got ", got_tsc);
7223 mtc.stop;
7224 } else {
7225 log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
7226 expect_target_tsc, ")");
7227 }
7228
Neels Hofmeyr91401012019-07-11 00:42:35 +02007229 /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
7230 * matter on which BTS it really is, we're not going to follow through an entire handover
7231 * anyway. */
7232 f_rslem_register(0, new_chan_nr, RSL1_PROC);
7233 f_rslem_resume(RSL1_PROC);
7234 f_rslem_register(0, new_chan_nr, RSL2_PROC);
7235 f_rslem_resume(RSL2_PROC);
7236
7237 if (expect_handover and not is_inter_bsc_handover) {
7238 setverdict(pass);
7239 log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected.");
7240 } else {
7241 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. "
7242 & log_label & ": " & log_descr);
7243 }
7244
7245 log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
7246 /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with
7247 * Handover Failure. */
7248 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
7249
7250 /* target BTS is told to release lchan again; don't care which BTS nor what messages. */
7251 f_sleep(0.5);
7252 RSL1.clear;
7253 RSL2.clear;
7254 log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)");
7255 break;
7256 } else {
7257 repeat;
7258 }
7259 }
7260 [] BSSAP.receive(tr_BSSMAP_HandoverRequired) {
7261 if (expect_handover and is_inter_bsc_handover) {
7262 setverdict(pass);
7263 log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected.");
7264 } else {
7265 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. "
7266 & log_label & ": " & log_descr);
7267 }
7268
7269 log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)");
7270
7271 /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to
7272 * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required,
7273 * setting a short timeout and waiting is the only way. */
7274 log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out...");
7275 f_sleep(1.5);
7276 log("f_probe_for_handover(" & log_label & "): ...done");
7277
7278 break;
7279 }
7280 [] T.timeout {
7281 if (expect_handover) {
7282 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. "
7283 & log_label & ": " & log_descr);
7284 } else {
7285 setverdict(pass);
7286 log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected.");
7287 }
7288 log("f_probe_for_handover(" & log_label & "): done (got no Handover)");
7289 break;
7290 }
7291 }
7292
7293 f_rslem_resume(RSL1_PROC);
7294 f_rslem_resume(RSL2_PROC);
7295 f_sleep(3.0);
7296 RSL.clear;
7297
7298 log("f_probe_for_handover(" & log_label & "): done clearing");
7299}
7300
7301/* Test the effect of various neighbor configuration scenarios:
7302 *
7303 * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0.
7304 * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO.
7305 */
7306private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
7307 g_pars := f_gen_test_hdlr_pars();
7308 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
7309 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007310
7311 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
7312 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
7313
7314 /* Establish lchan at bts 0 */
7315 f_establish_fully(ass_cmd, exp_compl);
7316
7317 /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */
7318 f_vty_enter_cfg_network(BSCVTY);
7319 f_vty_transceive(BSCVTY, "timer T7 1");
7320 f_vty_transceive(BSCVTY, "end");
7321}
7322
7323private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
7324 f_tc_ho_neighbor_config_start();
7325
7326 /*
7327 * bts 0 ARFCN 871 BSIC 10
7328 * bts 1 ARFCN 871 BSIC 11
7329 * bts 2 ARFCN 871 BSIC 12
7330 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7331 */
7332
7333 log("f_tc_ho_neighbor_config: 1. No 'neighbor' config");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007334 f_bts_0_cfg(BSCVTY, {"no neighbors"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007335 f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
7336 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007337 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007338
7339 f_probe_for_handover("1.b", "HO to unknown cell does not start",
7340 "handover any to arfcn 13 bsic 39",
7341 false);
7342
7343 f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error",
7344 "handover any to arfcn 871 bsic 12",
7345 false);
7346
7347 f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
7348 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007349 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007350
7351 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007352}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007353testcase TC_ho_neighbor_config_1() runs on test_CT {
7354 var MSC_ConnHdlr vc_conn;
7355 f_init(3, true, guard_timeout := 60.0);
7356 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007357 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007358 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
7359 vc_conn.done;
7360
7361 /* f_tc_ho_neighbor_config_start() */
7362 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7363 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7364
7365 /* 1.a */
7366 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7367 * handover quickly by sending a Handover Failure message. */
7368 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7369 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7370 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7371 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007372 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7373 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007374
7375 /* 1.b */
7376 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7377 f_ctrs_bsc_and_bts_add(0, "handover:error");
7378
7379 /* 1.c */
7380 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7381 f_ctrs_bsc_and_bts_add(0, "handover:error");
7382
7383 /* 1.d */
7384 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7385 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7386 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7387 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007388 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7389 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007390
7391 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007392 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007393}
7394
Neels Hofmeyr91401012019-07-11 00:42:35 +02007395private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
7396 f_tc_ho_neighbor_config_start();
7397
7398 /*
7399 * bts 0 ARFCN 871 BSIC 10
7400 * bts 1 ARFCN 871 BSIC 11
7401 * bts 2 ARFCN 871 BSIC 12
7402 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7403 */
7404
7405 log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007406 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007407 f_sleep(0.5);
7408
7409 f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
7410 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007411 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007412
7413 f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
7414 "handover any to arfcn 871 bsic 12",
7415 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007416 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007417}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007418testcase TC_ho_neighbor_config_2() runs on test_CT {
7419 var MSC_ConnHdlr vc_conn;
7420 f_init(3, true, guard_timeout := 50.0);
7421 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007422 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007423 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
7424 vc_conn.done;
7425
7426 /* f_tc_ho_neighbor_config_start() */
7427 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7428 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7429
7430 /* 2.a */
7431 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7432 * handover quickly by sending a Handover Failure message. */
7433 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7434 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7435 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7436 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007437 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7438 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007439
7440 /* 2.b */
7441 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7442 f_ctrs_bsc_and_bts_add(0, "handover:error");
7443
7444 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007445 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007446}
7447
Neels Hofmeyr91401012019-07-11 00:42:35 +02007448private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
7449 f_tc_ho_neighbor_config_start();
7450
7451 /*
7452 * bts 0 ARFCN 871 BSIC 10
7453 * bts 1 ARFCN 871 BSIC 11
7454 * bts 2 ARFCN 871 BSIC 12
7455 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7456 */
7457
7458 log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007459 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007460 f_sleep(0.5);
7461
7462 f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor",
7463 "handover any to arfcn 871 bsic 11",
7464 false);
7465 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",
7466 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007467 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007468 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007469}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007470testcase TC_ho_neighbor_config_3() runs on test_CT {
7471 var MSC_ConnHdlr vc_conn;
7472 f_init(3, true, guard_timeout := 50.0);
7473 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007474 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007475 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
7476 vc_conn.done;
7477
7478 /* f_tc_ho_neighbor_config_start() */
7479 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7480 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7481
7482 /* 3.a */
7483 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7484 f_ctrs_bsc_and_bts_add(0, "handover:error");
7485
7486 /* 3.b */
7487 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7488 * handover quickly by sending a Handover Failure message. */
7489 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7490 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7491 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7492 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007493 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7494 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007495
7496 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007497 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007498}
7499
Neels Hofmeyr91401012019-07-11 00:42:35 +02007500private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
7501 f_tc_ho_neighbor_config_start();
7502
7503 /*
7504 * bts 0 ARFCN 871 BSIC 10
7505 * bts 1 ARFCN 871 BSIC 11
7506 * bts 2 ARFCN 871 BSIC 12
7507 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7508 */
7509
7510 log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007511 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007512 f_sleep(0.5);
7513
7514 f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor",
7515 "handover any to arfcn 871 bsic 11",
7516 false);
7517 f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor",
7518 "handover any to arfcn 871 bsic 12",
7519 false);
7520 f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
7521 "handover any to arfcn 123 bsic 45",
7522 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007523 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007524}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007525testcase TC_ho_neighbor_config_4() runs on test_CT {
7526 var MSC_ConnHdlr vc_conn;
7527 f_init(3, true, guard_timeout := 50.0);
7528 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007529 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007530 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
7531 vc_conn.done;
7532
7533 /* f_tc_ho_neighbor_config_start() */
7534 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7535 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7536
7537 /* 4.a */
7538 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7539 f_ctrs_bsc_and_bts_add(0, "handover:error");
7540
7541 /* 4.b */
7542 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7543 f_ctrs_bsc_and_bts_add(0, "handover:error");
7544
7545 /* 4.c */
7546 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7547 * handover quickly by timing out after the Handover Required message */
7548 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7549 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7550 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7551 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7552
7553 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007554 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007555}
7556
Neels Hofmeyr91401012019-07-11 00:42:35 +02007557private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
7558 f_tc_ho_neighbor_config_start();
7559
7560 /*
7561 * bts 0 ARFCN 871 BSIC 10
7562 * bts 1 ARFCN 871 BSIC 11
7563 * bts 2 ARFCN 871 BSIC 12
7564 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7565 */
7566
7567 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 +02007568 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007569 f_sleep(0.5);
7570
7571 f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
7572 "handover any to arfcn 871 bsic 12",
7573 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007574 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007575}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007576testcase TC_ho_neighbor_config_5() runs on test_CT {
7577 var MSC_ConnHdlr vc_conn;
7578 f_init(3, true);
7579 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007580 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007581 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
7582 vc_conn.done;
7583
7584 /* f_tc_ho_neighbor_config_start() */
7585 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7586 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7587
7588 /* 5 */
7589 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7590 * handover quickly by timing out after the Handover Required message */
7591 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7592 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7593 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7594 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7595
7596 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007597 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007598}
7599
Neels Hofmeyr91401012019-07-11 00:42:35 +02007600private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
7601 f_tc_ho_neighbor_config_start();
7602
7603 /*
7604 * bts 0 ARFCN 871 BSIC 10
7605 * bts 1 ARFCN 871 BSIC 11
7606 * bts 2 ARFCN 871 BSIC 12
7607 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7608 */
7609
7610 log("f_tc_ho_neighbor_config: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:"
7611 & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007612 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007613 f_sleep(0.5);
7614
7615 f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
7616 "handover any to arfcn 871 bsic 12",
7617 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007618 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007619}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007620testcase TC_ho_neighbor_config_6() runs on test_CT {
7621 var MSC_ConnHdlr vc_conn;
7622 f_init(3, true);
7623 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007624 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007625 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
7626 vc_conn.done;
7627
7628 /* f_tc_ho_neighbor_config_start() */
7629 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7630 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7631
7632 /* 6.a */
7633 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7634 * handover quickly by timing out after the Handover Required message */
7635 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7636 f_ctrs_bsc_and_bts_add(0, "handover:error");
7637
7638 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007639 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007640}
7641
Neels Hofmeyr91401012019-07-11 00:42:35 +02007642private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
7643 f_tc_ho_neighbor_config_start();
7644
7645 /*
7646 * bts 0 ARFCN 871 BSIC 10
7647 * bts 1 ARFCN 871 BSIC 11
7648 * bts 2 ARFCN 871 BSIC 12
7649 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7650 */
7651
7652 log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:"
7653 & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007654 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007655 f_sleep(0.5);
7656
7657 f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
7658 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007659 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007660 f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
7661 "handover any to arfcn 123 bsic 45",
7662 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007663 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007664}
Neels Hofmeyr91401012019-07-11 00:42:35 +02007665testcase TC_ho_neighbor_config_7() runs on test_CT {
7666 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf2b88032020-06-16 00:35:04 +02007667 f_init(3, true, guard_timeout := 50.0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007668 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007669 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007670 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
7671 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007672
7673 /* f_tc_ho_neighbor_config_start() */
7674 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7675 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7676
7677 /* 7.a */
7678 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7679 * handover quickly by sending a Handover Failure message. */
7680 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7681 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7682 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7683 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007684 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7685 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007686
7687 /* 7.b */
7688 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7689 * handover quickly by timing out after the Handover Required message */
7690 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7691 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7692 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7693 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7694
7695 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007696 f_shutdown_helper(ho := true);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007697}
7698
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007699/* OS#3041: Open and close N connections in a normal fashion, and expect no
7700 * BSSMAP Reset just because of that. */
7701testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
7702 var default d;
7703 var integer i;
7704 var DchanTuple dt;
7705
7706 f_init();
7707
7708 /* Wait for initial BSSMAP Reset to pass */
7709 f_sleep(4.0);
7710
7711 d := activate(no_bssmap_reset());
7712
7713 /* Setup up a number of connections and RLSD them again from the MSC
7714 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7715 * Let's do it some more times for good measure. */
Harald Weltec3260d92018-06-11 17:48:16 +02007716 for (i := 0; i < 4; i := i+1) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007717 /* Since we're doing a lot of runs, give each one a fresh
7718 * T_guard from the top. */
7719 T_guard.start;
7720
7721 /* Setup a BSSAP connection and clear it right away. This is
7722 * the MSC telling the BSC about a planned release, it's not an
7723 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007724 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007725
7726 /* MSC disconnects (RLSD). */
7727 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
7728 }
7729
7730 /* In the buggy behavior, a timeout of 2 seconds happens between above
7731 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7732 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7733 f_sleep(4.0);
7734
7735 deactivate(d);
7736 f_shutdown_helper();
7737}
Harald Welte552620d2017-12-16 23:21:36 +01007738
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007739/* OS#3041: Open and close N connections in a normal fashion, and expect no
7740 * BSSMAP Reset just because of that. Invoke the release by a BSSMAP Clear from
7741 * the MSC. */
7742testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
7743 var default d;
7744 var integer i;
7745 var DchanTuple dt;
7746 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007747 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
7748 var BssmapCause cause := enum2int(cause_val);
7749
7750 f_init();
7751
7752 /* Wait for initial BSSMAP Reset to pass */
7753 f_sleep(4.0);
7754
7755 d := activate(no_bssmap_reset());
7756
7757 /* Setup up a number of connections and RLSD them again from the MSC
7758 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7759 * Let's do it some more times for good measure. */
7760 for (i := 0; i < 8; i := i+1) {
7761 /* Since we're doing a lot of runs, give each one a fresh
7762 * T_guard from the top. */
7763 T_guard.start;
7764
7765 /* Setup a BSSAP connection and clear it right away. This is
7766 * the MSC telling the BSC about a planned release, it's not an
7767 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007768 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007769
7770 /* Instruct BSC to clear channel */
7771 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7772
7773 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007774 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007775 }
7776
7777 /* In the buggy behavior, a timeout of 2 seconds happens between above
7778 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7779 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7780 f_sleep(4.0);
7781
7782 deactivate(d);
7783 f_shutdown_helper();
7784}
7785
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007786/* OS#3041: Open and close N connections in a normal fashion, and expect no
7787 * BSSMAP Reset just because of that. Close connections from the MS side with a
7788 * Release Ind on RSL. */
7789testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
7790 var default d;
7791 var integer i;
7792 var DchanTuple dt;
7793 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007794 var integer j;
7795
7796 f_init();
7797
7798 /* Wait for initial BSSMAP Reset to pass */
7799 f_sleep(4.0);
7800
7801 d := activate(no_bssmap_reset());
7802
7803 /* Setup up a number of connections and RLSD them again from the MSC
7804 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7805 * Let's do it some more times for good measure. */
7806 for (i := 0; i < 8; i := i+1) {
7807 /* Since we're doing a lot of runs, give each one a fresh
7808 * T_guard from the top. */
7809 T_guard.start;
7810
7811 /* Setup a BSSAP connection and clear it right away. This is
7812 * the MSC telling the BSC about a planned release, it's not an
7813 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007814 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007815
7816 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007817 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007818
7819 /* expect Clear Request on MSC side */
7820 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
7821
7822 /* Instruct BSC to clear channel */
7823 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
7824 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7825
7826 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007827 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007828 }
7829
7830 /* In the buggy behavior, a timeout of 2 seconds happens between above
7831 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7832 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7833 f_sleep(4.0);
7834
7835 deactivate(d);
7836 f_shutdown_helper();
7837}
7838
Harald Welte94e0c342018-04-07 11:33:23 +02007839/***********************************************************************
7840 * IPA style dynamic PDCH
7841 ***********************************************************************/
7842
7843private function f_dyn_ipa_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7844 template (omit) RSL_Cause nack := omit)
7845runs on test_CT {
7846 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7847 var RSL_Message rsl_unused;
7848 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7849 f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
7850 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007851 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007852 if (istemplatekind(nack, "omit")) {
7853 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007854 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007855 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007856 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007857 }
7858}
7859
7860private function f_dyn_ipa_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7861 template (omit) RSL_Cause nack := omit)
7862runs on test_CT {
7863 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7864 var RSL_Message rsl_unused;
7865 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7866 f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
7867 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007868 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_DEACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007869 if (istemplatekind(nack, "omit")) {
7870 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007871 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007872 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007873 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007874 }
7875}
7876
7877private function f_ts_dyn_mode_get(integer bts_nr, integer trx_nr, integer ts_nr)
7878runs on test_CT return charstring {
7879 var charstring cmd, resp;
7880 cmd := "show timeslot "&int2str(bts_nr)&" "&int2str(trx_nr)&" "&int2str(ts_nr);
Stefan Sperlingcff13562018-11-13 15:24:06 +01007881 return f_vty_transceive_match_regexp_retry(BSCVTY, cmd, "*\((*)\)*", 0, 4, 1.0);
Harald Welte94e0c342018-04-07 11:33:23 +02007882}
7883
7884private function f_ts_dyn_mode_assert(integer bts_nr, integer trx_nr, integer ts_nr,
7885 template charstring exp)
7886runs on test_CT {
7887 var charstring mode := f_ts_dyn_mode_get(bts_nr, trx_nr, ts_nr);
7888 if (not match(mode, exp)) {
7889 setverdict(fail, "Unexpected TS Mode: ", mode);
Daniel Willmannafce8662018-07-06 23:11:32 +02007890 mtc.stop;
Harald Welte94e0c342018-04-07 11:33:23 +02007891 }
7892}
7893
7894private function f_ts_set_chcomb(integer bts_nr, integer trx_nr, integer ts_nr, charstring chcomb)
7895runs on test_CT {
7896 f_vty_enter_cfg_ts(BSCVTY, bts_nr, trx_nr, ts_nr);
7897 f_vty_transceive(BSCVTY, "phys_chan_config " & chcomb);
7898 f_vty_transceive(BSCVTY, "end");
7899}
7900
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007901
7902private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
7903 var integer i;
7904 for (i := 0; i < 8; i := i + 1) {
7905 f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
7906 }
7907}
7908
Harald Welte94e0c342018-04-07 11:33:23 +02007909private const charstring TCHF_MODE := "TCH/F mode";
7910private const charstring TCHH_MODE := "TCH/H mode";
7911private const charstring PDCH_MODE := "PDCH mode";
7912private const charstring NONE_MODE := "NONE mode";
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007913private const charstring SDCCH8_MODE := "SDCCH8 mode";
Harald Welte94e0c342018-04-07 11:33:23 +02007914
7915/* Test IPA PDCH activation / deactivation triggered by VTY */
7916testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
7917 var RSL_Message rsl_unused;
7918
7919 /* change Timeslot 6 before f_init() starts RSL */
7920 f_init_vty();
7921 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7922 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7923
7924 f_init(1, false);
7925 f_sleep(1.0);
7926
7927 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7928
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007929 log("TCH/F_PDCH pchan starts out in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007930 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7931 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007932 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7933 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007934 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007935 log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007936 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7937
7938 /* De-activate it via VTY */
7939 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7940 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007941 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007942 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7943
7944 /* re-activate it via VTY */
7945 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn);
7946 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007947 log("TCH/F_PDCH pchan, PDCH ACT via VTY, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007948 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7949
7950 /* and finally de-activate it again */
7951 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7952 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007953 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007954 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7955
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007956 /* clean up config */
7957 f_ts_set_chcomb(0, 0, 6, "PDCH");
7958
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007959 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007960}
7961
7962/* Test IPA PDCH activation NACK */
7963testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
7964 var RSL_Message rsl_unused;
7965
7966 /* change Timeslot 6 before f_init() starts RSL */
7967 f_init_vty();
7968 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7969 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7970
7971 f_init(1, false);
7972 f_sleep(1.0);
7973
7974 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7975
7976 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7977 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007978 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7979 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007980 f_sleep(1.0);
7981 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7982
7983 /* De-activate it via VTY */
7984 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7985 f_sleep(1.0);
7986 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7987
7988 /* re-activate it via VTY, but fail that; check BSC still assumes TCH/F mode */
7989 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn, RSL_ERR_EQUIPMENT_FAIL);
7990 f_sleep(1.0);
7991 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7992
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007993 /* clean up config */
7994 f_ts_set_chcomb(0, 0, 6, "PDCH");
7995
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007996 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007997}
7998
7999
8000/***********************************************************************
8001 * Osmocom style dynamic PDCH
8002 ***********************************************************************/
8003
8004private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
8005 template (omit) RSL_Cause nack := omit)
8006runs on test_CT {
8007 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
8008 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02008009 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02008010 /* FIXME: no VTY command to activate Osmocom PDCH !! */
8011 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008012 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT(chan_nr, ?));
Harald Welte94e0c342018-04-07 11:33:23 +02008013 if (istemplatekind(nack, "omit")) {
8014 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008015 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02008016 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008017 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02008018 }
8019}
8020
8021private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
8022 template (omit) RSL_Cause nack := omit)
8023runs on test_CT {
8024 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
8025 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02008026 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02008027 /* FIXME: no VTY command to activate Osmocom PDCH !! */
8028 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008029 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008030 if (istemplatekind(nack, "omit")) {
8031 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008032 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008033 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008034 //f_ipa_tx(ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02008035 }
8036}
8037
8038/* Test Osmocom dyn PDCH activation / deactivation triggered by VTY */
8039testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
8040 var RSL_Message rsl_unused;
8041
8042 /* change Timeslot 6 before f_init() starts RSL */
8043 f_init_vty();
8044 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8045 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8046
8047 f_init(1, false);
8048 f_sleep(1.0);
8049
8050 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8051
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008052 log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02008053 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8054 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008055 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008056
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008057 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02008058 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02008059 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 +02008060 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
8061
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008062 /* clean up config */
8063 f_ts_set_chcomb(0, 0, 6, "PDCH");
8064
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008065 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008066}
8067
8068/* Test Osmocom dyn PDCH activation NACK behavior */
8069testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
8070 var RSL_Message rsl_unused;
8071
8072 /* change Timeslot 6 before f_init() starts RSL */
8073 f_init_vty();
8074 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
8075 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8076
8077 f_init(1, false);
8078 f_sleep(1.0);
8079
8080 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
8081
8082 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8083 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008084 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02008085
8086 /* NACK this activation and expect the "show timeslot" mode still to be NONE */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008087 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte94e0c342018-04-07 11:33:23 +02008088 f_sleep(1.0);
8089 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
8090
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02008091 /* clean up config */
8092 f_ts_set_chcomb(0, 0, 6, "PDCH");
8093
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008094 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02008095}
8096
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008097/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
8098testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
8099 var RSL_Message rsl_unused, rsl_msg;
8100 var DchanTuple dt;
8101 var BSSAP_N_CONNECT_ind rx_c_ind;
8102
8103 /* change Timeslot 6 before f_init() starts RSL */
8104 f_init_vty();
8105 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8106 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8107
8108 f_init(1, false);
8109 f_sleep(1.0);
8110
8111 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8112
8113 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8114 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8115 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008116 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008117
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008118 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008119 f_sleep(1.0);
8120 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8121 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8122
8123 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8124 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008125 var DchanTuples sdcch_cleanup := {};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008126 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008127 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008128 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008129 sdcch_cleanup := sdcch_cleanup & { dt };
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008130 }
8131
8132 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008133 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8134 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8135 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008136
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008137 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008138 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008139 dt.idx := {0, 0};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008140
8141 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008142 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8143 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008144 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
8145
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008146 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 +02008147 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8148 dt.sccp_conn_id := rx_c_ind.connectionId;
8149 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8150
8151 /* Instruct BSC to clear channel */
8152 var BssmapCause cause := 0;
8153 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008154 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008155
8156 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008157 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8158 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008159 f_sleep(1.0);
8160 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8161
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008162 /* Clean up SDCCH lchans */
8163 for (i := 0; i < lengthof(sdcch_cleanup); i := i + 1) {
8164 f_perform_clear_test_ct(sdcch_cleanup[i]);
8165 }
8166
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008167 /* clean up config */
8168 f_ts_set_chcomb(0, 0, 6, "PDCH");
8169
8170 f_shutdown_helper();
8171}
8172
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008173/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
8174testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
8175 var ASP_RSL_Unitdata rsl_ud;
8176 var integer i;
8177 var integer chreq_total, chreq_nochan;
8178
8179 f_init_vty();
8180 for (i := 1; i < 8; i := i + 1) {
8181 if (i == 2) {
8182 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8183 } else {
8184 f_ts_set_chcomb(0, 0, i, "PDCH");
8185 }
8186 }
8187 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8188
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008189 f_init(1, guard_timeout := 60.0);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008190
8191 /* The dyn TS want to activate PDCH mode, ACK that. */
8192 var RslChannelNr chan_nr;
8193 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008194 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
8195 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008196
8197 f_sleep(1.0);
8198
8199 /* Exhaust all dedicated SDCCH lchans.
8200 /* GSM 44.018 Table 9.1.8.2:
8201 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
8202 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008203 var DchanTuples chan_cleanup := {};
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008204 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008205 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 +02008206 }
8207
8208 /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008209 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 +02008210 /* Also occupy the seven other SDCCH of the dyn TS */
8211 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008212 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 +01008213 }
8214
8215 /* Clean up SDCCH lchans */
8216 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8217 f_perform_clear_test_ct(chan_cleanup[i]);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008218 }
8219
8220 /* clean up config */
8221 f_ts_reset_chcomb(0);
8222
8223 f_shutdown_helper();
8224}
8225
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008226/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
8227 SDCCH8 would end up in having no free TCH, then BSC should decide to activate
8228 it as TCH directly instead. SYS#5309. */
8229testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
8230 var RSL_Message rsl_unused, rsl_msg;
8231 var DchanTuple dt;
8232 var BSSAP_N_CONNECT_ind rx_c_ind;
8233 var integer i;
8234
8235 /* change Timeslot 6 before f_init() starts RSL */
8236 f_init_vty();
8237 for (i := 1; i < 8; i := i + 1) {
8238 if (i == 6) {
8239 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8240 } else {
8241 f_ts_set_chcomb(0, 0, i, "PDCH");
8242 }
8243 }
8244 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8245
8246 f_init(1, false);
8247 f_sleep(1.0);
8248
8249 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8250
8251 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8252 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8253 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008254 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008255
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008256 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008257 f_sleep(1.0);
8258 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8259 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8260
8261 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8262 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008263 var DchanTuples chan_cleanup := {};
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02008264 var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008265 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008266 dt := f_est_dchan(ra, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008267 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008268 }
8269
8270 /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008271 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
8272 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8273 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008274
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008275 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008276 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008277 dt.idx := {0, 0};
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008278
8279 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008280 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8281 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008282 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
8283
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008284 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 +02008285 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8286 dt.sccp_conn_id := rx_c_ind.connectionId;
8287 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8288
8289 /* Instruct BSC to clear channel */
8290 var BssmapCause cause := 0;
8291 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008292 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008293
8294 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008295 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8296 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008297 f_sleep(1.0);
8298 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8299
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008300 /* Clean up SDCCH lchans */
8301 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8302 f_perform_clear_test_ct(chan_cleanup[i]);
8303 }
8304
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008305 /* clean up config */
8306 f_ts_reset_chcomb(0);
8307 /* TODO: clean up other channels? */
8308
8309 f_shutdown_helper();
8310}
8311
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008312/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
8313testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
8314 var RSL_Message rsl_unused, rsl_msg;
8315 var DchanTuple dt;
8316 var BSSAP_N_CONNECT_ind rx_c_ind;
8317 var GsmRrMessage rr;
8318
8319 /* change Timeslot 6 before f_init() starts RSL */
8320 f_init_vty();
8321 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8322 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8323
8324 f_init(1, false);
8325 f_sleep(1.0);
8326
8327 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8328
8329 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8330 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8331 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008332 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008333
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008334 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008335 f_sleep(1.0);
8336 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8337 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8338
8339 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8340 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008341 var DchanTuples chan_cleanup := {};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008342 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008343 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008344 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008345 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008346 }
8347
8348 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008349 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8350 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8351 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008352
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008353 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008354 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008355 dt.idx := {0, 0};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008356
8357 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008358 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
8359 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008360 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
8361 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
8362 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
8363 }
8364
8365 /* FIXME? Currently the TS stays in state BORKEN: */
8366
8367 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008368 /* rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8369 * f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008370 * f_sleep(1.0);
8371 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
8372 */
8373
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008374 /* Clean up SDCCH lchans */
8375 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8376 f_perform_clear_test_ct(chan_cleanup[i]);
8377 }
8378
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008379 /* clean up config */
8380 f_ts_set_chcomb(0, 0, 6, "PDCH");
8381
8382 f_shutdown_helper();
8383}
8384
Stefan Sperling0796a822018-10-05 13:01:39 +02008385testcase TC_chopped_ipa_ping() runs on test_CT {
Stefan Sperling554123f2018-10-09 14:12:30 +02008386 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port, mp_bsc_ctrl_port};
Stefan Sperling0796a822018-10-05 13:01:39 +02008387 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8388 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8389 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008390 f_shutdown_helper();
Stefan Sperling0796a822018-10-05 13:01:39 +02008391}
8392
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008393testcase TC_chopped_ipa_payload() runs on test_CT {
8394 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port
8395 /* TODO: mp_bsc_ctrl_port does not work yet */};
8396 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8397 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8398 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008399 f_shutdown_helper();
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008400}
8401
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008402/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
8403 the BTS does autonomous MS power control loop */
8404testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
8405 var MSC_ConnHdlr vc_conn;
8406 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8407 //pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
8408 pars.exp_ms_power_params := true;
8409
8410 f_init(1, true);
8411 f_sleep(1.0);
8412 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
8413 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008414 f_shutdown_helper();
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008415}
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008416
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008417/* Verify activation and deactivation of the BCCH carrier power reduction mode */
8418testcase TC_c0_power_red_mode() runs on test_CT {
8419 f_init(1);
8420
8421 for (var integer red := 6; red >= 0; red := red - 2) {
8422 /* Configure BCCH carrier power reduction mode via the VTY */
8423 f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
8424
8425 /* Expect Osmocom specific BS Power Control message on the RSL */
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03008426 var template (present) RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008427 chan_nr := t_RslChanNr_BCCH(0),
8428 bs_power := tr_RSL_IE_BS_Power(red / 2));
8429 tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008430 var RSL_Message unused := f_exp_ipa_rx(tr_rsl_pdu);
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008431
8432 /* Additionally verify the applied value over the CTRL interface */
8433 var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
8434 if (cred != int2str(red)) {
8435 setverdict(fail, "Unexpected BCCH carrier power reduction value ",
8436 cred, " (expected ", red, ")");
8437 }
8438 }
8439
8440 f_shutdown_helper();
8441}
8442
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008443/***********************************************************************
8444 * MSC Pooling
8445 ***********************************************************************/
8446
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008447template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
Harald Weltebf397612021-01-14 20:39:46 +01008448 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 +02008449
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008450private 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 +02008451runs on MSC_ConnHdlr {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008452 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008453 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008454 f_logp(BSCVTY, "Got RSL RR Release");
8455 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008456 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008457 f_logp(BSCVTY, "Got RSL Deact SACCH");
8458 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008459 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008460 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008461 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8462 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008463 break;
8464 }
8465 }
8466}
8467
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008468private altstep as_mgcp_ack_all_dlcx() runs on MSC_ConnHdlr {
8469 var MgcpCommand mgcp_cmd;
Oliver Smithab7354b2023-05-08 11:34:30 +02008470 var template MgcpMessage msg_dlcx := {
8471 command := tr_DLCX
8472 }
8473 var MGCP_RecvFrom mrf;
8474
8475 [g_pars.aoip] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008476 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
8477 repeat;
8478 }
Oliver Smithab7354b2023-05-08 11:34:30 +02008479
8480 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
8481 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
8482 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
8483 }));
8484 repeat;
8485 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008486}
8487
8488private altstep as_rsl_ack_all_rel_req() runs on MSC_ConnHdlr {
8489 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
8490 [] RSL.receive(tr_RSL_REL_REQ(g_chan_nr, ?)) {
8491 RSL.send(ts_RSL_REL_CONF(g_chan_nr, main_dcch));
8492 repeat;
8493 }
8494}
8495
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008496friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
8497 template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02008498runs on MSC_ConnHdlr {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008499 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8500 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008501 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008502 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8503 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008504 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008505 f_logp(BSCVTY, "Got RSL RR Release");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008506 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008507 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008508 f_logp(BSCVTY, "Got RSL Deact SACCH");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008509 }
8510 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008511 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008512 /* Also drop the SCCP connection */
8513 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8514 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008515 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008516 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008517 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8518 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008519 }
8520 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008521 deactivate(ack_dlcx);
8522 deactivate(ack_rel_req);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008523}
8524
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01008525friend function f_perform_clear_no_rr_rel(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC)
8526runs on MSC_ConnHdlr {
8527 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8528 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
8529 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8530 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8531 interleave {
8532 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
8533 f_logp(BSCVTY, "Got RSL Deact SACCH");
8534 }
8535 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
8536 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8537 /* Also drop the SCCP connection */
8538 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8539 }
8540 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
8541 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
8542 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8543 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
8544 }
8545 }
8546 deactivate(ack_dlcx);
8547 deactivate(ack_rel_req);
8548}
8549
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01008550friend function f_perform_clear_no_lchan()
8551runs on MSC_ConnHdlr {
8552 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8553 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8554 BSSAP.receive(tr_BSSMAP_ClearComplete);
8555 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8556 /* Also drop the SCCP connection */
8557 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8558}
8559
Vadim Yanitskiy65d879d2022-06-23 18:15:39 +07008560friend function f_perform_clear_test_ct(DchanTuple dt)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008561 runs on test_CT
8562{
8563 /* Instruct BSC to clear channel */
8564 var BssmapCause cause := 0;
8565 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008566 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008567}
8568
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008569private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
8570 template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008571runs on MSC_ConnHdlr {
8572 timer T := 10.0;
8573 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
8574
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008575 f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008576 f_create_bssmap_exp(l3_enc);
8577
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008578 /* RSL_Emulation.f_chan_est() on rsl_pt:
8579 * This is basically code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008580 * RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
8581 */
8582 var RSL_Message rx_rsl;
8583 var GsmRrMessage rr;
8584
8585 /* request a channel to be established */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008586 rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008587 /* expect immediate assignment.
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008588 * Code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008589 * rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
8590 */
8591 timer Tt := 10.0;
8592
8593 /* request a channel to be established */
8594 Tt.start;
8595 alt {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008596 [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008597 Tt.stop;
8598 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008599 [] rsl_pt.receive {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008600 setverdict(fail, "Unexpected RSL message on DCHAN");
8601 mtc.stop;
8602 }
8603 [] Tt.timeout {
8604 setverdict(fail, "Timeout waiting for RSL on DCHAN");
8605 mtc.stop;
8606 }
8607 }
8608 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
8609 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008610 rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008611
8612
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008613 if (expect_bssmap_l3) {
8614 f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
8615 var template PDU_BSSAP exp_l3_compl;
8616 exp_l3_compl := tr_BSSMAP_ComplL3()
8617 if (g_pars.aoip == false) {
8618 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
8619 } else {
8620 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
8621 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008622
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008623 var PDU_BSSAP bssap;
8624 T.start;
8625 alt {
8626 [] BSSAP.receive(exp_l3_compl) -> value bssap {
8627 f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
8628 log("rx exp_l3_compl = ", bssap);
8629 }
8630 [] BSSAP.receive(tr_BSSMAP_ComplL3) {
8631 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
8632 }
8633 [] T.timeout {
8634 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
8635 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008636 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008637
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008638 /* start ciphering, if requested */
8639 if (ispresent(g_pars.encr)) {
8640 f_logp(BSCVTY, "start ciphering");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008641 f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008642 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008643 }
8644
8645 if (do_clear) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008646 f_perform_clear(rsl_pt, rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008647 }
8648 setverdict(pass);
8649 f_sleep(1.0);
8650}
8651
8652private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
8653 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8654 if (g_pars.mscpool.rsl_idx == 0) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008655 f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008656 } else if (g_pars.mscpool.rsl_idx == 1) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008657 f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008658 } else if (g_pars.mscpool.rsl_idx == 2) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008659 f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008660 }
8661}
8662
8663/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
8664private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
8665 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008666 f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
8667 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 +02008668 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)) );
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008669 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 +02008670}
8671testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
8672
8673 f_init(1, true);
8674 f_sleep(1.0);
8675 var MSC_ConnHdlr vc_conn;
8676 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008677
8678 f_ctrs_msc_init();
8679
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008680 vc_conn := f_start_handler(refers(f_tc_mscpool_L3Compl_on_1_msc), pars);
8681 vc_conn.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008682
8683 f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008684 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008685}
8686
8687/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
8688/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8689 * just as well using only RSL. */
8690testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
8691
8692 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8693 f_sleep(1.0);
8694
8695 /* Control which MSC gets chosen next by the round-robin, otherwise
8696 * would be randomly affected by which other tests ran before this. */
8697 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8698
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008699 f_ctrs_msc_init();
8700
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008701 var MSC_ConnHdlr vc_conn1;
8702 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8703 pars1.mscpool.rsl_idx := 0;
8704 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8705 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8706 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008707 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008708
8709 var MSC_ConnHdlr vc_conn2;
8710 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8711 pars2.mscpool.rsl_idx := 1;
8712 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8713 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8714 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008715 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008716
8717 /* Test round-robin wrap to the first MSC */
8718 var MSC_ConnHdlr vc_conn3;
8719 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8720 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008721 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008722 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8723 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008724 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008725 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008726}
8727
8728/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 0
8729 * (configured in osmo-bsc.cfg). */
8730/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8731 * just as well using only RSL. */
8732testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
8733
8734 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8735 f_sleep(1.0);
8736
8737 /* Control which MSC gets chosen next by the round-robin, otherwise
8738 * would be randomly affected by which other tests ran before this. */
8739 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8740
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008741 f_ctrs_msc_init();
8742
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008743 var MSC_ConnHdlr vc_conn1;
8744 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8745 pars1.mscpool.rsl_idx := 0;
8746 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8747 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8748 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008749 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008750
8751 var MSC_ConnHdlr vc_conn2;
8752 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8753 pars2.mscpool.rsl_idx := 1;
8754 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8755 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8756 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008757 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008758
8759 /* Test round-robin wrap to the first MSC */
8760 var MSC_ConnHdlr vc_conn3;
8761 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8762 pars3.mscpool.rsl_idx := 2;
8763 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8764 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8765 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008766 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008767 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008768}
8769
8770/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
8771 * (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
8772 * NULL-NRI setting is stronger than that. */
8773/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8774 * just as well using only RSL. */
8775testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
8776
8777 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8778 f_sleep(1.0);
8779
8780 /* Control which MSC gets chosen next by the round-robin, otherwise
8781 * would be randomly affected by which other tests ran before this. */
8782 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8783
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008784 f_ctrs_msc_init();
8785
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008786 var MSC_ConnHdlr vc_conn1;
8787 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8788 pars1.mscpool.rsl_idx := 0;
8789 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8790 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8791 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008792 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008793
8794 var MSC_ConnHdlr vc_conn2;
8795 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8796 pars2.mscpool.rsl_idx := 1;
8797 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8798 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8799 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008800 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008801
8802 /* Test round-robin wrap to the first MSC */
8803 var MSC_ConnHdlr vc_conn3;
8804 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8805 pars3.mscpool.rsl_idx := 2;
8806 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8807 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8808 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008809 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008810 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008811}
8812
8813/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
8814 * assigned to any MSC (configured in osmo-bsc.cfg). */
8815/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8816 * just as well using only RSL. */
8817testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test_CT {
8818
8819 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8820 f_sleep(1.0);
8821
8822 /* Control which MSC gets chosen next by the round-robin, otherwise
8823 * would be randomly affected by which other tests ran before this. */
8824 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8825
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008826 f_ctrs_msc_init();
8827
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008828 var MSC_ConnHdlr vc_conn1;
8829 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8830 pars1.mscpool.rsl_idx := 0;
8831 /* An NRI that is not assigned to any MSC */
8832 pars1.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(1023))));
8833 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8834 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008835 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008836
8837 var MSC_ConnHdlr vc_conn2;
8838 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8839 pars2.mscpool.rsl_idx := 1;
8840 /* An NRI that is not assigned to any MSC */
8841 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(768)), '00F110'O));
8842 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8843 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008844 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008845
8846 /* Test round-robin wrap to the first MSC */
8847 var MSC_ConnHdlr vc_conn3;
8848 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8849 pars3.mscpool.rsl_idx := 2;
8850 /* An NRI that is not assigned to any MSC */
8851 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, valueof(ts_MI_TMSI_NRI_LV(819))));
8852 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8853 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008854 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008855 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008856}
8857
8858/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
8859 * assigned to an MSC that is currently not connected (configured in osmo-bsc.cfg). */
8860/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8861 * just as well using only RSL. */
8862testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
8863
8864 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8865 f_sleep(1.0);
8866
8867 /* Control which MSC gets chosen next by the round-robin, otherwise
8868 * would be randomly affected by which other tests ran before this. */
8869 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8870
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008871 f_ctrs_msc_init();
8872
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008873 var MSC_ConnHdlr vc_conn1;
8874 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8875 pars1.mscpool.rsl_idx := 0;
8876 /* An NRI that is assigned to an unconnected MSC */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008877 pars1.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(512)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008878 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8879 vc_conn1.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();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008883
8884 var MSC_ConnHdlr vc_conn2;
8885 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8886 pars2.mscpool.rsl_idx := 1;
8887 /* An NRI that is assigned to an unconnected MSC */
8888 pars2.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(767))));
8889 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8890 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008891 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8892 f_ctrs_msc_add(1, "mscpool:subscr:new");
8893 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008894
8895 /* Test round-robin wrap to the first MSC */
8896 var MSC_ConnHdlr vc_conn3;
8897 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8898 pars3.mscpool.rsl_idx := 2;
8899 /* An NRI that is assigned to an unconnected MSC */
8900 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(750)), '00F110'O));
8901 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8902 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008903 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8904 f_ctrs_msc_add(0, "mscpool:subscr:new");
8905 f_ctrs_msc_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008906 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008907}
8908
8909/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
8910 * osmo-bsc.cfg). */
8911/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8912 * just as well using only RSL. */
8913testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
8914
8915 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8916 f_sleep(1.0);
8917
8918 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
8919 * this is not using round-robin. */
8920 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8921
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008922 f_ctrs_msc_init();
8923
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008924 var MSC_ConnHdlr vc_conn1;
8925 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8926 pars1.mscpool.rsl_idx := 0;
8927 /* An NRI of the second MSC's range (256-511) */
8928 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(256))));
8929 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8930 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008931 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008932
8933 var MSC_ConnHdlr vc_conn2;
8934 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8935 pars2.mscpool.rsl_idx := 1;
8936 /* An NRI of the second MSC's range (256-511) */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008937 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(260)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008938 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8939 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008940 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008941
8942 var MSC_ConnHdlr vc_conn3;
8943 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8944 pars3.mscpool.rsl_idx := 2;
8945 /* An NRI of the second MSC's range (256-511) */
8946 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(511)), '00F110'O));
8947 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8948 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008949 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008950 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008951}
8952
8953/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
8954 * while a round-robin remains unaffected by that. */
8955/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8956 * just as well using only RSL. */
8957testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
8958
8959 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8960 f_sleep(1.0);
8961
8962 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
8963 * this is not using round-robin. */
8964 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8965
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008966 f_ctrs_msc_init();
8967
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008968 var MSC_ConnHdlr vc_conn1;
8969 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 2);
8970 pars1.mscpool.rsl_idx := 0;
8971 /* An NRI of the third MSC's range (512-767) */
8972 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(512))));
8973 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8974 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008975 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008976
8977 var MSC_ConnHdlr vc_conn2;
8978 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8979 pars2.mscpool.rsl_idx := 1;
8980 /* An NRI of the third MSC's range (512-767) */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02008981 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(678)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008982 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8983 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008984 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008985
8986 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
8987 var MSC_ConnHdlr vc_conn3;
8988 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8989 pars3.mscpool.rsl_idx := 2;
8990 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000013'H)), '00F110'O));
8991 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8992 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008993 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008994 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008995}
8996
8997/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
8998/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8999 * just as well using only RSL. */
9000testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
9001
9002 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9003 f_sleep(1.0);
9004
9005 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
9006 * instead, and hits msc 0. */
9007 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9008
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009009 f_ctrs_msc_init();
9010
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009011 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-bsc.cfg */
9012 var MSC_ConnHdlr vc_conn1;
9013 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9014 pars1.mscpool.rsl_idx := 0;
9015 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(260)), '99F999'O));
9016 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9017 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009018 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009019
9020 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
9021 var MSC_ConnHdlr vc_conn2;
9022 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9023 pars2.mscpool.rsl_idx := 1;
9024 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(555)), '00F110'O));
9025 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9026 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009027 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009028 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009029}
9030
9031/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
9032 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9033private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
9034 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9035 //cid_list := { cIl_allInBSS := ''O };
9036 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9037 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9038 var BSSAP_N_UNITDATA_req paging;
9039 var hexstring imsi := '001010000000123'H;
9040
9041 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9042
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009043 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009044 valueof(ts_BSSMAP_Paging(imsi, cid_list, omit, bssmap_chneed))));
9045 BSSAP.send(paging);
9046
9047 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9048 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9049 * channel number is picked here. */
9050 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9051 f_rslem_register(0, new_chan_nr);
9052 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(imsi)));
9053 f_rslem_unregister(0, new_chan_nr);
9054
9055 /* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
9056 * causes this Paging Response to go to the first MSC (bssap_idx := 0). */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009057 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV(imsi)) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009058 f_sleep(1.0);
9059}
9060testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
9061 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9062 f_sleep(1.0);
9063
9064 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9065 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9066 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
9067
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009068 f_ctrs_msc_init();
9069
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009070 var MSC_ConnHdlr vc_conn1;
9071 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9072 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009073 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9074 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009075 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
9076 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009077 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009078 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009079}
9080
9081/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
9082 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
9083private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
9084 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
9085 //cid_list := { cIl_allInBSS := ''O };
9086 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
9087 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
9088 var integer nri_v := 300; /* <-- second MSC's NRI */
Harald Weltebf397612021-01-14 20:39:46 +01009089 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009090 var BSSAP_N_UNITDATA_req paging;
9091
9092 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9093
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009094 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009095 valueof(ts_BSSMAP_Paging('001010000000011'H, cid_list, tmsi, bssmap_chneed))));
9096 BSSAP.send(paging);
9097
9098 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
9099 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
9100 * channel number is picked here. */
9101 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
9102 f_rslem_register(0, new_chan_nr);
9103 RSL.receive(tr_RSL_PAGING_CMD(t_MI_TMSI(tmsi)));
9104 f_rslem_unregister(0, new_chan_nr);
9105
9106 /* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
9107 * third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
9108 * the first MSC (bssap_idx := 0). */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009109 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_TMSI_NRI_LV(nri_v)) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009110 f_sleep(1.0);
9111}
9112testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
9113 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
9114 f_sleep(1.0);
9115
9116 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
9117 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
9118 f_vty_transceive(BSCVTY, "mscpool roundrobin next 2");
9119
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009120 f_ctrs_msc_init();
9121
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009122 var MSC_ConnHdlr vc_conn1;
9123 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9124 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02009125 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
9126 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009127 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
9128 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009129 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009130 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009131}
9132
9133/* For round-robin, skip an MSC that has 'no allow-attach' set. */
9134/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
9135 * just as well using only RSL. */
9136testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
9137
9138 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9139 f_sleep(1.0);
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009140 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9141 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009142
9143 /* Control which MSC gets chosen next by the round-robin, otherwise
9144 * would be randomly affected by which other tests ran before this. */
9145 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9146
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009147 f_ctrs_msc_init();
9148
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009149 var MSC_ConnHdlr vc_conn1;
9150 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9151 pars1.mscpool.rsl_idx := 0;
9152 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9153 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9154 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009155 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009156
9157 var MSC_ConnHdlr vc_conn2;
9158 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9159 pars2.mscpool.rsl_idx := 1;
9160 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9161 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9162 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009163 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009164
9165 var MSC_ConnHdlr vc_conn3;
9166 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
9167 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009168 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009169 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9170 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009171 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009172 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009173}
9174
9175/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
9176 * TMSI NRI. */
9177testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
9178
9179 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9180 f_sleep(1.0);
9181
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009182 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9183 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
9184
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009185 /* Control which MSC gets chosen next by the round-robin, otherwise
9186 * would be randomly affected by which other tests ran before this. */
9187 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9188
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009189 f_ctrs_msc_init();
9190
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009191 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
9192 var MSC_ConnHdlr vc_conn1;
9193 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
9194 pars1.mscpool.rsl_idx := 0;
9195 /* An NRI of the second MSC's range (256-511) */
9196 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_TMSI_NRI_LV(260))));
9197 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9198 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009199 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009200
9201 var MSC_ConnHdlr vc_conn2;
9202 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9203 pars2.mscpool.rsl_idx := 1;
9204 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9205 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9206 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009207 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009208
9209 var MSC_ConnHdlr vc_conn3;
9210 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 2);
9211 pars3.mscpool.rsl_idx := 2;
9212 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000003'H))));
9213 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9214 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009215 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009216 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009217}
9218
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009219/* When an MSC point-code gets an SCCP N-PCSTATE saying it is unreachable, immediately mark the MSC as unusable. */
9220testcase TC_mscpool_sccp_n_pcstate_detaches_msc() runs on test_CT {
9221
9222 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
9223 f_sleep(1.0);
9224
9225 /* Control which MSC gets chosen next by the round-robin, otherwise
9226 * would be randomly affected by which other tests ran before this. */
9227 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9228
9229 f_ctrs_msc_init();
9230
9231 var MSC_ConnHdlr vc_conn1;
9232 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9233 pars1.mscpool.rsl_idx := 0;
9234 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9235 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9236 vc_conn1.done;
9237 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9238
9239 var MSC_ConnHdlr vc_conn2;
9240 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
9241 pars2.mscpool.rsl_idx := 1;
9242 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9243 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9244 vc_conn2.done;
9245 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9246
9247 f_logp(BSCVTY, "disconnecting msc0");
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009248 f_bssap_idx_disconnect(0);
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009249
9250 /* Now round-robin would wrap to the first MSC, but since the first MSC is disconnected, it wraps around to msc
9251 * 2 again. */
9252 var MSC_ConnHdlr vc_conn3;
9253 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
9254 pars3.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009255 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +02009256 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9257 vc_conn3.done;
9258 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9259 f_shutdown_helper();
9260}
9261
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009262/* When an MSC point-code gets an SCCP N-PCSTATE saying it is now reachable, immediately trigger RESET and bring up the
9263 * MSC. */
9264testcase TC_mscpool_sccp_n_pcstate_attaches_msc() runs on test_CT {
9265
9266 f_init(nr_bts := 3, handler_mode := true, nr_msc := 1);
9267 f_sleep(1.0);
9268
9269 /* Control which MSC gets chosen next by the round-robin, otherwise
9270 * would be randomly affected by which other tests ran before this. */
9271 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9272
9273 f_ctrs_msc_init();
9274
9275 /* There is only one MSC, round robin stays on msc0 */
9276 var MSC_ConnHdlr vc_conn1;
9277 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9278 pars1.mscpool.rsl_idx := 0;
9279 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('0010100230000001'H)), '00F110'O));
9280 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9281 vc_conn1.done;
9282 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9283
9284 var MSC_ConnHdlr vc_conn2;
9285 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9286 pars2.mscpool.rsl_idx := 1;
9287 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010023000002'H))));
9288 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9289 vc_conn2.done;
9290 f_ctrs_msc_expect(0, "mscpool:subscr:new");
9291
9292 f_logp(BSCVTY, "connecting msc1");
9293 f_vty_msc_allow_attach(BSCVTY, { true, true });
9294 f_bssap_idx_init(1);
9295 f_sleep(1.0);
9296
9297 /* This time round-robin wraps to the second MSC, because it is now online. */
9298 var MSC_ConnHdlr vc_conn4;
9299 var TestHdlrParams pars4 := f_gen_test_hdlr_pars(bssap_idx := 1);
9300 pars4.mscpool.rsl_idx := 2;
Neels Hofmeyr2bc75892023-04-07 00:00:34 +02009301 pars4.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010023000003'H)));
Neels Hofmeyr38632aa2023-04-05 03:50:51 +02009302 vc_conn4 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars4);
9303 vc_conn4.done;
9304 f_ctrs_msc_expect(1, "mscpool:subscr:new");
9305
9306 f_shutdown_helper();
9307}
9308
Philipp Maier783681c2020-07-16 16:47:06 +02009309/* Allow/Deny emergency calls globally via VTY */
9310private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
9311 f_vty_enter_cfg_msc(BSCVTY, 0);
9312 if (allow) {
9313 f_vty_transceive(BSCVTY, "allow-emergency allow");
9314 } else {
9315 f_vty_transceive(BSCVTY, "allow-emergency deny");
9316 }
9317 f_vty_transceive(BSCVTY, "exit");
9318 f_vty_transceive(BSCVTY, "exit");
9319}
9320
9321/* Allow/Deny emergency calls per BTS via VTY */
9322private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
9323 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9324 if (allow) {
9325 f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
9326 } else {
9327 f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
9328 }
9329 f_vty_transceive(BSCVTY, "exit");
9330 f_vty_transceive(BSCVTY, "exit");
Neels Hofmeyrb6ed80c2020-10-12 22:52:39 +00009331 f_vty_transceive(BSCVTY, "exit");
Philipp Maier783681c2020-07-16 16:47:06 +02009332}
9333
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02009334/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
9335private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
9336 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9337 if (allow) {
9338 f_vty_transceive(BSCVTY, "srvcc fast-return allow");
9339 } else {
9340 f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
9341 }
9342 f_vty_transceive(BSCVTY, "exit");
9343 f_vty_transceive(BSCVTY, "exit");
9344 f_vty_transceive(BSCVTY, "exit");
9345}
9346
Pau Espin Pedrol14475352021-07-22 15:48:16 +02009347/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
9348private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
9349 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9350 if (allow) {
9351 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
9352 } else {
9353 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
9354 }
9355 f_vty_transceive(BSCVTY, "exit");
9356 f_vty_transceive(BSCVTY, "exit");
9357 f_vty_transceive(BSCVTY, "exit");
9358}
9359
Pau Espin Pedrol35609792023-01-03 16:56:59 +01009360/* Begin assignment procedure and send an EMERGENCY SETUP (RR) */
Philipp Maier783681c2020-07-16 16:47:06 +02009361private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
9362 var PDU_ML3_MS_NW emerg_setup;
9363 var octetstring emerg_setup_enc;
9364 var RSL_Message emerg_setup_data_ind;
9365
9366 f_establish_fully(omit, omit);
9367
9368 emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
9369 emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
9370 emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
9371
9372 RSL.send(emerg_setup_data_ind);
9373}
9374
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009375/* expect EmergencySetup on BSSAP after calling f_assignment_emerg_setup() */
9376private function f_assignment_emerg_setup_exp_bssap()
9377runs on MSC_ConnHdlr {
Philipp Maier783681c2020-07-16 16:47:06 +02009378 var PDU_BSSAP emerg_setup_data_ind_bssap;
9379 var PDU_ML3_MS_NW emerg_setup;
9380 timer T := 3.0;
9381
Philipp Maier783681c2020-07-16 16:47:06 +02009382 T.start;
9383 alt {
9384 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
9385 emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
9386 if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
9387 setverdict(fail, "no emergency setup");
9388 }
9389 }
9390 [] BSSAP.receive {
9391 setverdict(fail, "unexpected BSSAP message!");
9392 }
9393 [] T.timeout {
9394 setverdict(fail, "timout waiting for EMERGENCY SETUP!");
9395 }
9396 }
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009397}
9398
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009399private function f_assignment_emerg_setup_voice()
9400runs on MSC_ConnHdlr {
9401 /* Go on with voice call assignment */
9402 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
9403 var PDU_BSSAP ass_cmd := f_gen_ass_req();
9404
9405 /* Below speechOrDataIndicator and codecList are copied from an emergency call captured during tests.
9406 * They seem a bit weird (AMR-WB, and the order differ between speechId_DataIndicator and the codecList), but
9407 * seems a good idea to see how osmo-bsc reacts to this. */
9408 ass_cmd.pdu.bssmap.assignmentRequest.channelType := {
9409 elementIdentifier := '0B'O, /* overwritten */
9410 lengthIndicator := 0, /* overwritten */
9411 speechOrDataIndicator := '0001'B, /* speech */
9412 spare1_4 := '0000'B,
9413 channelRateAndType := ChRate_TCHForH_Fpref,
9414 speechId_DataIndicator := 'c2918105'O
9415 };
9416 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({
9417 ts_CodecHR, ts_CodecAMR_WB, ts_CodecEFR, ts_CodecFR}));
9418
9419 f_rslem_dchan_queue_enable();
9420
9421 var ExpectCriteria mgcpcrit := {
9422 connid := omit,
9423 endpoint := omit,
9424 transid := omit
9425 };
9426 f_create_mgcp_expect(mgcpcrit);
9427
9428 BSSAP.send(ass_cmd);
9429
9430 var AssignmentState st := valueof(ts_AssignmentStateInit);
Oliver Smithce2dd692023-04-17 10:25:50 +02009431 st.rtp_stream := true;
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009432 st.is_assignment := false;
9433 alt {
9434 [] as_modify(st);
9435 [] as_Media();
9436 [st.modify_done] BSSAP.receive(exp_compl) {
9437 setverdict(pass);
9438 }
9439 }
9440
9441 /* Voice call carries on ... */
9442 f_sleep(2.0);
9443}
9444
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009445/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
9446 * CALLS are permitted by the BSC config. */
9447private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
9448
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009449 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
9450 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
9451 * another lchan. */
9452 g_pars.ra := f_rnd_ra_emerg();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009453 f_assignment_emerg_setup();
9454 f_assignment_emerg_setup_exp_bssap();
Pau Espin Pedrol14076d32023-01-03 17:07:59 +01009455 f_assignment_emerg_setup_voice();
Philipp Maier783681c2020-07-16 16:47:06 +02009456
9457 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009458 f_perform_clear();
Philipp Maier783681c2020-07-16 16:47:06 +02009459}
9460
9461/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
9462 * forbidden by the BSC config. */
9463private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
9464 var PDU_BSSAP emerg_setup_data_ind_bssap;
9465 timer T := 3.0;
9466
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +01009467 f_assignment_emerg_setup();
Philipp Maier783681c2020-07-16 16:47:06 +02009468
9469 T.start;
9470 alt {
9471 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
9472 setverdict(pass);
9473 }
9474 [] RSL.receive {
9475 setverdict(fail, "unexpected RSL message!");
9476 }
9477 [] T.timeout {
9478 setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
9479 }
9480 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009481 BSSAP.receive(tr_BSSMAP_ClearRequest);
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01009482 f_perform_clear_no_rr_rel();
Philipp Maier783681c2020-07-16 16:47:06 +02009483}
9484
9485/* EMERGENCY CALL situation #1, allowed globally and by BTS */
9486testcase TC_assignment_emerg_setup_allow() runs on test_CT {
9487 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9488 var MSC_ConnHdlr vc_conn;
9489
9490 f_init(1, true);
9491 f_sleep(1.0);
9492
9493 f_vty_allow_emerg_msc(true);
9494 f_vty_allow_emerg_bts(true, 0);
9495 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9496 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009497 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009498}
9499
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +01009500/* Test MO emergency call using MobileIdentity=IMEI (possible for emergency
9501 * calls from phones without SIM card).
9502 * 3GPP TS 24.008 section 10.5.1.4, OS#5849 */
9503testcase TC_assignment_emerg_setup_allow_imei() runs on test_CT {
9504 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9505 var MSC_ConnHdlr vc_conn;
9506
9507 /* Remove IMSI set by f_gen_test_hdlr_pars(), then IMEI will be used to place the call */
9508 pars.imsi := omit;
9509
9510 f_init(1, true);
9511 f_sleep(1.0);
9512
9513 f_vty_allow_emerg_msc(true);
9514 f_vty_allow_emerg_bts(true, 0);
9515 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9516 vc_conn.done;
9517 f_shutdown_helper();
9518}
9519
Philipp Maier783681c2020-07-16 16:47:06 +02009520/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
9521testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
9522 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9523 var MSC_ConnHdlr vc_conn;
9524
9525 f_init(1, true);
9526 f_sleep(1.0);
9527
9528 f_vty_allow_emerg_msc(false);
9529 f_vty_allow_emerg_bts(true, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009530 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx): */
9531 pars.ra := f_rnd_ra_emerg();
Philipp Maier783681c2020-07-16 16:47:06 +02009532 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9533 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009534 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009535}
9536
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009537/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS.
9538 * The RACH req (and hence CHAN RQD) indicate other than emergency call.
9539 * Hence BSC only learns about it being an emergency call later during call setup.
9540 * If interested in the ra="emergency call" + deny bts policy case,
9541 * see TC_chan_rqd_emerg_deny.
9542 */
Philipp Maier783681c2020-07-16 16:47:06 +02009543testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
9544 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9545 var MSC_ConnHdlr vc_conn;
9546
9547 /* Note: This simulates a spec violation by the MS, correct MS
9548 * implementations would not try to establish an emergency call because
9549 * the system information tells in advance that emergency calls are
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009550 * not allowed */
Philipp Maier783681c2020-07-16 16:47:06 +02009551
9552 f_init(1, true);
9553 f_sleep(1.0);
9554
9555 f_vty_allow_emerg_msc(true);
9556 f_vty_allow_emerg_bts(false, 0);
Pau Espin Pedrol6b869f42023-01-17 12:06:03 +01009557 /* Note: Here we implicitly leave default g_pars.ra which is different than "emergency call" */
Philipp Maier783681c2020-07-16 16:47:06 +02009558 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9559 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009560 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009561}
9562
Philipp Maier82812002020-08-13 18:48:27 +02009563/* Test what happens when an emergency call arrives while all TCH channels are
9564 * busy, the BSC is expected to terminate one call in favor of the incoming
9565 * emergency call */
9566testcase TC_emerg_premption() runs on test_CT {
9567 var ASP_RSL_Unitdata rsl_ud;
9568 var integer i;
9569 var integer chreq_total, chreq_nochan;
9570 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009571 var octetstring l3_payload := gen_l3_valid_payload();
Philipp Maier82812002020-08-13 18:48:27 +02009572
9573 f_init(1);
9574 f_sleep(1.0);
9575
9576 f_vty_allow_emerg_msc(true);
9577 f_vty_allow_emerg_bts(true, 0);
9578
9579 /* Fill up all channels on the BTS */
9580 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
9581 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
9582 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 +02009583 f_chreq_act_ack('33'O, i);
Philipp Maier82812002020-08-13 18:48:27 +02009584 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009585 IPA_RSL[0][0].clear;
Philipp Maier82812002020-08-13 18:48:27 +02009586 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
9587 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
9588
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009589 /* Send EST IND for the first TCH, so we get to test the RR release cause */
9590 var RslChannelNr first_tch := valueof(t_RslChanNr_Bm(1));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009591 f_ipa_tx(ts_RSL_EST_IND(first_tch, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009592
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009593 /* Accept BSSAP conn, so we get to test the Clear Request cause */
9594 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009595 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009596 var integer sccp_conn_id := rx_c_ind.connectionId;
9597 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
9598
Philipp Maier82812002020-08-13 18:48:27 +02009599 /* Send Channel request for emegergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009600 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier82812002020-08-13 18:48:27 +02009601
9602 /* Expect the BSC to release one (the first) TCH/F on the BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009603 f_expect_chan_rel(first_tch, expect_rr_chan_rel := true, expect_rll_rel_req := false,
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009604 expect_rr_cause := GSM48_RR_CAUSE_PREMPTIVE_REL);
Philipp Maier82812002020-08-13 18:48:27 +02009605
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009606 /* Also expect a BSSMAP Clear Request with PREEMPTION */
9607 var BSSAP_N_DATA_ind rx_clear_req;
9608 const myBSSMAP_Cause preemption := GSM0808_CAUSE_PREEMPTION;
9609 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_clear_req;
9610 log("XXX ", rx_clear_req);
9611 if (rx_clear_req.userData.pdu.bssmap.clearRequest.cause.causeValue != int2bit(enum2int(preemption), 7)) {
9612 setverdict(fail, "BSSMAP Clear Request: expected cause PREEMPTION");
9613 }
9614
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009615 /* Expect the BSC to send activate/assign the channel for the emergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009616 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009617 if (first_tch != rx_rsl.ies[0].body.chan_nr) {
9618 setverdict(fail, "different TCH lchan activated than expected");
9619 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009620 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(first_tch, 33));
9621 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Philipp Maier104f4c02020-09-11 18:12:18 +02009622
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009623 /* complete the BSSMAP Clear to satisfy the conn leak check */
9624 BSSAP.send(ts_BSSAP_DATA_req(sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(preemption))));
9625 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearComplete)) {
9626 BSSAP.send(ts_BSSAP_DISC_req(sccp_conn_id, 0));
9627 }
9628
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009629 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009630}
9631
9632/* Hopping parameters per a timeslot */
Vadim Yanitskiybc6654a2020-09-13 01:27:40 +07009633private type record length(0..64) of GsmArfcn ArfcnList;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009634private type record FHParamsTs {
9635 boolean enabled,
9636 uint6_t hsn,
9637 uint6_t maio,
9638 ArfcnList ma
9639};
9640
9641/* Hopping parameters per a transceiver */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009642private type record FHParamsTrx {
Philipp Maier798d8952021-10-19 14:43:19 +02009643 GsmBandArfcn arfcn,
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009644 FHParamsTs ts[8]
9645};
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009646
9647/* Randomly generate the hopping parameters for the given timeslot numbers */
9648private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
9649runs on test_CT return FHParamsTrx {
9650 var FHParamsTrx fhp;
9651
Philipp Maier798d8952021-10-19 14:43:19 +02009652 /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
9653 * fall in the GSM900 band. */
9654 fhp.arfcn.arfcn := f_rnd_int(3);
9655 fhp.arfcn.pcs := false;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009656
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009657 for (var integer tn := 0; tn < 8; tn := tn + 1) {
9658 if (not match(tn, tr_tn)) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009659 fhp.ts[tn].enabled := false;
9660 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009661 continue;
9662 }
9663
9664 /* Random HSN / MAIO values: 0..63 */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009665 fhp.ts[tn].hsn := f_rnd_int(64);
9666 fhp.ts[tn].maio := f_rnd_int(64);
9667 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009668
9669 /* Random Mobile Allocation (hopping channels) */
9670 var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
9671 var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
9672 for (var integer i := 1; i <= ma_len; i := i + 1) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009673 fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009674 }
9675
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009676 fhp.ts[tn].enabled := true;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009677 }
9678
9679 log("f_TC_fh_params_gen(): ", fhp);
9680 return fhp;
9681}
9682
9683/* Make sure that the given Channel Description IE matches the hopping configuration */
9684private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
9685{
9686 var template (present) ChannelDescription tr_cd;
9687 var template (present) MaioHsn tr_maio_hsn;
9688 var uint3_t tn := cd.chan_nr.tn;
9689
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009690 if (fhp.ts[tn].enabled) {
9691 tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009692 tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
9693 } else {
Philipp Maier798d8952021-10-19 14:43:19 +02009694 tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009695 }
9696
9697 if (not match(cd, tr_cd)) {
9698 setverdict(fail, "Channel Description IE does not match: ",
9699 cd, " vs expected ", tr_cd);
9700 }
9701}
9702
9703/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
9704private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
9705 in MobileAllocationLV ma)
9706{
9707 var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
9708
9709 if (not match(ma, tr_ma)) {
9710 setverdict(fail, "Mobile Allocation IE does not match (tn := ",
9711 tn, "): ", ma, " vs expected: ", tr_ma);
9712 } else {
9713 setverdict(pass);
9714 }
9715}
9716
9717private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
9718 in MobileAllocationLV ma)
9719return template MobileAllocationLV {
9720 /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009721 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009722 return { len := 0, ma := ''B };
9723 }
9724
9725 var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
9726 var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
9727 var bitstring ma_mask := ''B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009728
9729 /* Compose the full bit-mask (all channels, up to 1024 entries) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009730 for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
9731 for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
9732 if (full_mask[fhp.ts[i].ma[j]] == '1'B)
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009733 { continue; }
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009734 full_mask[fhp.ts[i].ma[j]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009735 }
9736 }
9737
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009738 /* Take ARFCN of the TRX itself into account */
Philipp Maier798d8952021-10-19 14:43:19 +02009739 full_mask[fhp.arfcn.arfcn] := '1'B;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009740
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009741 /* Compose a bit-mask for the given timeslot number */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009742 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9743 slot_mask[fhp.ts[tn].ma[i]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009744 }
9745
9746 /* Finally, compose the Mobile Allocation bit-mask */
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009747 for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009748 if (full_mask[i] != '1'B)
9749 { continue; }
9750
9751 /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
9752 if (slot_mask[i] == '1'B) {
9753 ma_mask := ma_mask & '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009754 } else {
9755 ma_mask := ma_mask & '0'B;
9756 }
9757 }
9758
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009759 /* ARFCN 0 (if present) goes to the last position of the bit-mask */
9760 if (full_mask[0] == '1'B) {
9761 /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
9762 if (slot_mask[0] == '1'B) {
9763 ma_mask := ma_mask & '1'B;
9764 } else {
9765 ma_mask := ma_mask & '0'B;
9766 }
9767 }
9768
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009769 /* Ensure that ma_mask is octet-aligned */
Vadim Yanitskiy2aa02522020-09-06 14:05:23 +07009770 var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009771 ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
9772
9773 return { len := ma_mask_len, ma := ma_mask };
9774}
9775
Philipp Maier798d8952021-10-19 14:43:19 +02009776/* Configure the appropriate band for a given arfcn, exc */
9777private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
9778{
9779 var charstring band;
9780 var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
9781
9782 select (arfcn_) {
9783 case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
9784 case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
9785 case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
9786 case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
9787 case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
9788 case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
9789 case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
9790 case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
9791 case else { return; }
9792 }
9793
9794 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9795 f_vty_transceive(BSCVTY, "band " & band);
9796 f_vty_transceive(BSCVTY, "end");
9797}
9798
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009799/* Configure the hopping parameters in accordance with the given record */
9800private function f_TC_fh_params_set(in FHParamsTrx fhp,
9801 uint8_t bts_nr := 0,
9802 uint8_t trx_nr := 0)
9803runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009804
9805 f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
9806
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009807 /* Enter the configuration node for the given BTS/TRX numbers */
9808 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9809
Philipp Maier798d8952021-10-19 14:43:19 +02009810 f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009811
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009812 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009813 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9814
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009815 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009816 f_vty_transceive(BSCVTY, "hopping enabled 0");
9817 f_vty_transceive(BSCVTY, "exit"); /* go back */
9818 continue;
9819 }
9820
9821 /* Configure HSN / MAIO values */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009822 f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
9823 f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009824
9825 /* Configure the Mobile Allocation (hopping channels) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009826 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9827 f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009828 }
9829
9830 f_vty_transceive(BSCVTY, "hopping enabled 1");
9831 f_vty_transceive(BSCVTY, "exit"); /* go back */
9832 }
9833
9834 f_vty_transceive(BSCVTY, "end");
9835}
9836
9837/* Disable frequency hopping on all timeslots */
9838private function f_TC_fh_params_unset(in FHParamsTrx fhp,
9839 uint8_t bts_nr := 0,
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009840 uint8_t trx_nr := 0,
Philipp Maier798d8952021-10-19 14:43:19 +02009841 GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009842runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009843
9844 f_TC_set_band_by_arfcn(bts_nr, arfcn);
9845
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009846 /* Enter the configuration node for the given BTS/TRX numbers */
9847 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9848
Philipp Maier798d8952021-10-19 14:43:19 +02009849 f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009850
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009851 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009852 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9853
9854 /* Delete all ARFCNs from the Mobile Allocation (if any) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009855 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9856 f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009857 }
9858
9859 f_vty_transceive(BSCVTY, "hopping enabled 0");
9860 f_vty_transceive(BSCVTY, "exit"); /* go back */
9861 }
9862
9863 f_vty_transceive(BSCVTY, "end");
9864 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9865}
9866
9867/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
9868 * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
9869testcase TC_fh_params_chan_activ() runs on test_CT {
9870 var FHParamsTrx fhp := f_TC_fh_params_gen();
9871 var RSL_Message rsl_msg;
9872 var RSL_IE_Body ie;
9873
9874 f_init_vty();
9875
9876 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9877 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9878
9879 f_init(1);
9880
9881 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9882 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009883 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9884 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009885
9886 /* Make sure that Channel Identification IE is present */
9887 if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
9888 setverdict(fail, "RSL Channel Identification IE is absent");
9889 continue;
9890 }
9891
9892 /* Make sure that hopping parameters (HSN/MAIO) match */
9893 f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
9894
9895 /* "Mobile Allocation shall be included but empty" - let's check this */
9896 if (ie.chan_ident.ma.v.len != 0) {
9897 setverdict(fail, "Mobile Allocation IE is not empty: ",
9898 ie.chan_ident.ma, ", despite it shall be");
9899 continue;
9900 }
9901 }
9902
9903 /* Disable frequency hopping */
9904 f_TC_fh_params_unset(fhp);
9905
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009906 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009907}
9908
9909/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
9910testcase TC_fh_params_imm_ass() runs on test_CT {
9911 var FHParamsTrx fhp := f_TC_fh_params_gen();
9912 var RSL_Message rsl_msg;
9913 var RSL_IE_Body ie;
9914
9915 f_init_vty();
9916
9917 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9918 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9919
9920 f_init(1);
9921
9922 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9923 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009924 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9925 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009926
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009927 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9928 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009929
9930 /* Make sure that Full Immediate Assign Info IE is present */
9931 if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
9932 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
9933 continue;
9934 }
9935
9936 /* Decode the actual Immediate Assignment message */
9937 var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
9938 if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
9939 setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
9940 continue;
9941 }
9942
9943 /* Make sure that hopping parameters (HSN/MAIO) match */
9944 f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
9945
9946 /* Make sure that the Mobile Allocation IE matches */
9947 f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
9948 rr_msg.payload.imm_ass.mobile_allocation);
9949 }
9950
9951 /* Disable frequency hopping */
9952 f_TC_fh_params_unset(fhp);
Philipp Maier82812002020-08-13 18:48:27 +02009953
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009954 f_shutdown_helper();
Philipp Maier82812002020-08-13 18:48:27 +02009955}
9956
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009957/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
9958testcase TC_fh_params_assignment_cmd() runs on test_CT {
9959 var FHParamsTrx fhp := f_TC_fh_params_gen();
9960 var RSL_Message rsl_msg;
9961 var RSL_IE_Body ie;
9962
9963 f_init_vty();
9964
9965 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9966 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9967
9968 f_init(1);
9969
9970 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02009971 vc_MGCP[0].stop;
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009972
9973 var template PDU_BSSAP ass_cmd := f_gen_ass_req();
9974 ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
9975
9976 /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
9977 * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
9978 for (var integer i := 0; i < 3; i := i + 1) {
9979 /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009980 var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009981
9982 /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
9983 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009984 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009985
9986 /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009987 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9988 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009989
9990 /* Make sure that L3 Information IE is present */
9991 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9992 setverdict(fail, "RSL L3 Information IE is absent");
9993 continue;
9994 }
9995
9996 /* Decode the L3 message and make sure it is (RR) Assignment Command */
9997 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9998 if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
9999 setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
10000 continue;
10001 }
10002
10003 /* Make sure that hopping parameters (HSN/MAIO) match */
10004 var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
10005 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10006
10007 /* Make sure that Cell Channel Description IE is present if FH is enabled */
10008 if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
Vadim Yanitskiy38d069d2020-09-02 17:18:57 +070010009 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010010 continue;
10011 }
10012
10013 /* Make sure that the Mobile Allocation IE matches (if present) */
10014 var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
10015 if (chan_desc.h and ma_present) {
10016 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10017 l3_msg.payload.ass_cmd.mobile_allocation.v);
10018 } else if (chan_desc.h and not ma_present) {
10019 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10020 continue;
10021 } else if (not chan_desc.h and ma_present) {
10022 setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
10023 continue;
10024 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010025
10026 f_perform_clear_test_ct(dt);
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010027 }
10028
10029 /* Give the IUT some time to release all channels */
10030 f_sleep(3.0);
10031
10032 /* Disable frequency hopping */
10033 f_TC_fh_params_unset(fhp);
10034
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010035 f_shutdown_helper();
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070010036}
10037
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010038/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
10039private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
10040runs on test_CT {
10041 var RSL_Message rsl_msg;
10042 var RSL_IE_Body ie;
10043 var DchanTuple dt;
10044
10045 /* Establish a dedicated channel, so we can trigger handover */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010010046 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyc18ff472021-11-18 20:15:37 +030010047 f_sleep(0.5);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010048
10049 /* Trigger handover from BTS0 to BTS1 */
10050 f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
10051 f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
10052
10053 /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010054 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx := {1, 0});
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010055
10056 /* ACKnowledge channel activation and expect (RR) Handover Command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010057 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33), idx := {1, 0});
10058 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010059
10060 /* Make sure that L3 Information IE is present */
10061 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
10062 setverdict(fail, "RSL L3 Information IE is absent");
10063 return;
10064 }
10065
10066 /* Decode the L3 message and make sure it is (RR) Handover Command */
10067 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
10068 if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
10069 setverdict(fail, "Failed to match Handover Command: ", l3_msg);
10070 return;
10071 }
10072
10073 /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
10074 var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
10075 if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
10076 setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
10077 return;
10078 }
10079
10080 /* Make sure that hopping parameters (HSN/MAIO) match */
10081 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10082
10083 /* Make sure that Cell Channel Description IE is present */
10084 if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
10085 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
10086 return;
10087 }
10088
10089 /* Make sure that the Mobile Allocation (after time) IE is present and matches */
10090 var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
10091 if (ma_present) {
10092 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10093 l3_msg.payload.ho_cmd.mobile_allocation.v);
10094 } else {
10095 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10096 return;
10097 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010098
10099 f_perform_clear_test_ct(dt);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070010100}
10101testcase TC_fh_params_handover_cmd() runs on test_CT {
10102 var FHParamsTrx fhp := f_TC_fh_params_gen();
10103
10104 f_init_vty();
10105
10106 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
10107 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
10108
10109 f_vty_transceive(BSCVTY, "timeslot 0");
10110 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10111 f_vty_transceive(BSCVTY, "exit"); /* go back */
10112
10113 f_vty_transceive(BSCVTY, "timeslot 1");
10114 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
10115 f_vty_transceive(BSCVTY, "end"); /* we're done */
10116
10117 f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
10118 f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
10119
10120 f_init(2);
10121
10122 f_TC_fh_params_handover_cmd(fhp);
10123
10124 /* Disable frequency hopping on BTS1 */
10125 f_TC_fh_params_unset(fhp, 1);
10126
10127 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
10128 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
10129
10130 f_vty_transceive(BSCVTY, "timeslot 0");
10131 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
10132 f_vty_transceive(BSCVTY, "exit"); /* go back */
10133
10134 f_vty_transceive(BSCVTY, "timeslot 1");
10135 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10136 f_vty_transceive(BSCVTY, "end"); /* we're done */
10137
10138 f_shutdown_helper();
10139}
10140
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010141/* Verify the hopping parameters in System Information Type 4 */
10142testcase TC_fh_params_si4_cbch() runs on test_CT {
10143 var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
10144 var ASP_RSL_Unitdata rx_rsl_ud;
10145 timer T := 5.0;
10146
10147 f_init_vty();
10148
10149 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
10150 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10151
10152 f_vty_transceive(BSCVTY, "timeslot 0");
10153 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
10154 f_vty_transceive(BSCVTY, "exit"); /* go back */
10155
10156 f_vty_transceive(BSCVTY, "timeslot 1");
10157 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
10158 f_vty_transceive(BSCVTY, "end"); /* we're done */
10159
10160 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
10161 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10162
10163 f_init(1);
10164
10165 T.start;
10166 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010167 [] 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 +070010168 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
10169 var SystemInformation si := dec_SystemInformation(ie.other.payload);
10170
10171 /* Make sure that what we decoded is System Information Type 4 */
10172 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
10173 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
10174 repeat;
10175 }
10176
10177 /* Make sure that CBCH Channel Description IE is present */
10178 if (not ispresent(si.payload.si4.cbch_chan_desc)) {
10179 setverdict(fail, "CBCH Channel Description IE is absent");
10180 break;
10181 }
10182
10183 /* Finally, check the hopping parameters (HSN, MAIO) */
10184 var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
10185 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
10186
10187 /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
10188 * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
10189 if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
10190 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
10191 break;
10192 } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
10193 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
10194 si.payload.si4.cbch_mobile_alloc.v);
10195 }
10196 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010197 [] IPA_RSL[0][0].receive { repeat; }
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010198 [] T.timeout {
10199 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
10200 }
10201 }
10202
10203 /* Disable frequency hopping */
10204 f_TC_fh_params_unset(fhp);
10205
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010206 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010207 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
10208
10209 f_vty_transceive(BSCVTY, "timeslot 0");
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +070010210 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010211 f_vty_transceive(BSCVTY, "exit"); /* go back */
10212
10213 f_vty_transceive(BSCVTY, "timeslot 1");
10214 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
10215 f_vty_transceive(BSCVTY, "end"); /* we're done */
10216
Vadim Yanitskiy21726312020-09-04 01:45:36 +070010217 f_shutdown_helper();
Vadim Yanitskiyca974032020-09-01 07:20:39 +070010218}
10219
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010220template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
10221 := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
10222
10223private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
10224 template (present) BSSLAP_PDU expect_bsslap)
10225{
10226 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
10227 if (not match(bsslap, expect_bsslap)) {
10228 log("EXPECTING BSSLAP: ", expect_bsslap);
10229 log("GOT BSSLAP: ", bsslap);
10230 setverdict(fail, "BSSLAP is not as expected");
10231 mtc.stop;
10232 }
10233 setverdict(pass);
10234}
10235
10236/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
10237const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
10238
10239private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
10240 var PDU_BSSAP_LE rx_bsslap;
10241 BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
10242 f_match_bsslap(rx_bsslap, expect_rx_bsslap);
10243}
10244
10245/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10246 * Request on Lb interface. Either with or without the SMLC doing a BSSLAP TA Request. */
10247private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
10248 f_sleep(1.0);
10249
10250 f_establish_fully(omit, omit);
10251 f_bssap_le_register_imsi(g_pars.imsi, omit);
10252
10253 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10254 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10255
10256 var PDU_BSSAP_LE plr;
10257 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10258
10259 if (not do_ta_request) {
10260 /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
10261 var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
10262 if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
10263 log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
10264 log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
10265 setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
10266 mtc.stop;
10267 }
10268 var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
10269 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
10270 if (not match(bsslap, expect_ta_layer3)) {
10271 log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
10272 log("GOT BSSLAP: ", bsslap);
10273 setverdict(fail, "BSSLAP is not as expected");
10274 mtc.stop;
10275 }
10276 /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
10277 * has no need to request the TA from the BSC and directly responds. */
10278 } else {
10279 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10280 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10281 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10282 }
10283
10284 /* SMLC got the TA from the BSC, now responds with geo information data. */
10285 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10286 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10287 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10288
10289 /* The LCS was using an active A-interface conn. It should still remain active after this. */
10290 f_mo_l3_transceive();
10291
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010292 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010293
10294 f_sleep(2.0);
10295 setverdict(pass);
10296}
10297
10298/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10299 * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
10300private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
10301 f_lcs_loc_req_for_active_ms(false);
10302}
10303testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
10304 var MSC_ConnHdlr vc_conn;
10305 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10306
10307 f_init(1, true);
10308 f_sleep(1.0);
10309 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
10310 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010311 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010312}
10313
10314/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10315 * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
10316private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
10317 f_lcs_loc_req_for_active_ms(true);
10318}
10319testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
10320 var MSC_ConnHdlr vc_conn;
10321 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10322
10323 f_init(1, true);
10324 f_sleep(1.0);
10325 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
10326 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010327 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010328}
10329
10330/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
10331 * conn without an active lchan. */
10332private function f_clear_A_conn() runs on MSC_ConnHdlr
10333{
10334 var BssmapCause cause := 0;
10335 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10336 BSSAP.receive(tr_BSSMAP_ClearComplete);
10337 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10338
10339 timer no_more_bssap := 5.0;
10340 no_more_bssap.start;
10341 alt {
10342 [] no_more_bssap.timeout { break; }
10343 [] BSSAP.receive(tr_BSSAP_BSSMAP) {
10344 setverdict(fail, "Expected no more BSSAP after Clear Complete");
10345 mtc.stop;
10346 }
10347 }
10348 setverdict(pass);
10349}
10350
10351/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
10352 * for LCS, for cases where there is only an A conn without an active lchan. */
10353private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
10354{
10355 f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
10356
10357 /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
10358 * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
10359 * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
10360 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10361 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10362 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10363
10364 /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
10365 f_clear_A_conn();
10366 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10367 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10368}
10369
10370/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10371 * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
10372 */
10373private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
10374 f_sleep(1.0);
10375
10376 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10377 f_bssap_le_register_imsi(g_pars.imsi, omit);
10378
10379 /* Register to receive the Paging Command */
10380 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10381 g_chan_nr := new_chan_nr;
10382 f_rslem_register(0, g_chan_nr);
10383
10384 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10385 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10386 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10387 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10388
10389 var PDU_BSSAP_LE plr;
10390 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10391
10392 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10393 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10394
10395 /* OsmoBSC needs to Page */
10396 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
10397 f_logp(BSCVTY, "got Paging Command");
10398
10399 /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
10400 * the MSC, and releases the lchan directly. */
Neels Hofmeyr2bc75892023-04-07 00:00:34 +020010401 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 +020010402 f_expect_lchan_rel(RSL, RSL_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010403
10404 /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
10405
10406 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10407
10408 /* SMLC got the TA from the BSC, now responds with geo information data. */
10409 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10410 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10411
10412 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10413
10414 /* The lchan is gone, the A-interface conn was created for the LCS only.
10415 * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
10416 f_verify_active_A_conn_and_clear();
10417
10418 f_sleep(2.0);
10419 setverdict(pass);
10420}
10421testcase TC_lcs_loc_req_for_idle_ms() runs on test_CT {
10422 var MSC_ConnHdlr vc_conn;
10423 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10424
10425 f_init(1, true);
10426 f_sleep(1.0);
10427
10428 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10429 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10430
10431 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
10432 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010433 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010434}
10435
10436/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
10437 */
10438private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
10439 f_sleep(1.0);
10440
10441 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10442 f_bssap_le_register_imsi(g_pars.imsi, omit);
10443
10444 /* provoke an abort by omitting both IMSI and IMEI */
10445 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10446 valueof(ts_BSSMAP_Perform_Location_Request(omit,
10447 ts_CellId_CGI('262'H, '42'H, 23, 42)))));
10448 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10449
10450 /* BSC tells MSC about failure */
10451 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10452 locationEstimate := omit, positioningData := omit,
10453 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
10454
10455 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10456 f_verify_active_A_conn_and_clear();
10457
10458 f_sleep(2.0);
10459 setverdict(pass);
10460}
10461testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
10462 var MSC_ConnHdlr vc_conn;
10463 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10464
10465 f_init(1, true);
10466 f_sleep(1.0);
10467
10468 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10469 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10470
10471 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
10472 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010473 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010474}
10475
10476/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10477 * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
10478private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
10479 f_sleep(1.0);
10480
10481 f_establish_fully(omit, omit);
10482 f_bssap_le_register_imsi(g_pars.imsi, omit);
10483
10484 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10485 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10486
10487 var PDU_BSSAP_LE plr;
10488 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10489
10490 if (do_ta) {
10491 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10492 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10493 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10494 }
10495
10496 /* SMLC fails to respond, BSC runs into timeout */
10497 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
10498 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10499
10500 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10501 locationEstimate := omit, positioningData := omit,
10502 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
10503
10504 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10505 f_verify_active_A_conn_and_clear();
10506
10507 f_sleep(2.0);
10508 setverdict(pass);
10509}
10510
10511/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10512 * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
10513private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
10514 f_lcs_loc_req_for_active_ms_le_timeout(false);
10515}
10516
10517testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
10518 var MSC_ConnHdlr vc_conn;
10519 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10520
10521 f_init(1, true);
10522 f_sleep(1.0);
10523 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
10524 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010525 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010526}
10527
10528/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10529 * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
10530private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
10531 f_lcs_loc_req_for_active_ms_le_timeout(true);
10532}
10533
10534testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
10535 var MSC_ConnHdlr vc_conn;
10536 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10537
10538 f_init(1, true);
10539 f_sleep(1.0);
10540 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
10541 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010542 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010543}
10544
10545/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
10546private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
10547 f_sleep(1.0);
10548
10549 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10550 f_bssap_le_register_imsi(g_pars.imsi, omit);
10551
10552 /* Register to receive the Paging Command */
10553 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10554 g_chan_nr := new_chan_nr;
10555 f_rslem_register(0, g_chan_nr);
10556
10557 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10558 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10559 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10560 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10561
10562 var PDU_BSSAP_LE plr;
10563 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10564
10565 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10566 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10567
10568 /* OsmoBSC needs to Page */
10569 var PDU_BSSAP_LE rx_bsslap;
10570 alt {
10571 [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
10572 f_logp(BSCVTY, "got Paging Command");
10573 repeat;
10574 }
10575 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10576 /* MS does not respond to Paging, TA Req runs into timeout. */
10577 f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
10578 }
10579 }
10580
10581 /* SMLC responds with failure */
10582 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10583 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10584
10585 /* BSC tells MSC about failure */
10586 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10587 locationEstimate := omit, positioningData := omit,
10588 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
10589
10590 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10591 f_verify_active_A_conn_and_clear();
10592
10593 f_sleep(2.0);
10594 setverdict(pass);
10595}
10596testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
10597 var MSC_ConnHdlr vc_conn;
10598 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10599
10600 f_init(1, true);
10601 f_sleep(1.0);
10602
10603 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10604 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10605
10606 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
10607 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010608 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010609}
10610
10611/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
10612 * over. */
10613private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10614 f_sleep(1.0);
10615
10616 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10617 f_bssap_le_register_imsi(g_pars.imsi, omit);
10618
10619 /* Register to receive the Paging Command */
10620 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10621 g_chan_nr := new_chan_nr;
10622 f_rslem_register(0, g_chan_nr);
10623
10624 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10625 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10626 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10627 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10628
10629 var PDU_BSSAP_LE plr;
10630 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10631
10632 /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
10633 * and establish Layer 3. It should use the existing A-interface conn. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010634 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 +020010635 do_clear := false, expect_bssmap_l3 := true);
10636
10637 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10638 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10639
10640 /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
10641 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10642
10643 /* SMLC got the TA from the BSC, now responds with geo information data. */
10644 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10645 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10646 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10647
10648 /* The lchan should still exist, it was from a CM Service Request. */
10649 f_mo_l3_transceive();
10650
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010651 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010652
10653 f_sleep(2.0);
10654 setverdict(pass);
10655}
10656testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
10657 var MSC_ConnHdlr vc_conn;
10658 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10659
10660 f_init(1, true);
10661 f_sleep(1.0);
10662
10663 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10664 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10665
10666 vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
10667 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010668 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010669}
10670
10671/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
10672 * the new lchan after handover. */
10673private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10674 f_sleep(1.0);
10675
10676 f_establish_fully(omit, omit);
10677 f_bssap_le_register_imsi(g_pars.imsi, omit);
10678
10679 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10680 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10681
10682 var PDU_BSSAP_LE plr;
10683 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10684
10685 /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
10686 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
10687
10688 var HandoverState hs := {
10689 rr_ho_cmpl_seen := false,
10690 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +020010691 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010692 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010693 };
10694 /* issue hand-over command on VTY */
10695 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
10696 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
10697 f_rslem_suspend(RSL1_PROC);
10698
10699 /* From the MGW perspective, a handover is is characterized by
10700 * performing one MDCX operation with the MGW. So we expect to see
10701 * one more MDCX during handover. */
10702 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
10703
10704 alt {
10705 [] as_handover(hs);
10706 }
10707
10708 var PDU_BSSAP_LE rx_bsslap;
10709
10710 interleave {
10711 /* Expect the BSC to inform the MSC about the handover */
10712 [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
10713
10714 /* Expect the BSC to inform the SMLC about the handover */
10715 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10716 f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
10717 }
10718 }
10719
10720 /* SMLC now responds with geo information data. */
10721 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10722 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10723 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10724
10725 /* lchan still active */
10726 f_mo_l3_transceive(RSL1);
10727
10728 /* MSC decides it is done now. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010729 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010730
10731 f_sleep(2.0);
10732 setverdict(pass);
10733}
10734testcase TC_ho_during_lcs_loc_req() runs on test_CT {
10735 var MSC_ConnHdlr vc_conn;
10736 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10737
10738 f_init(2, true);
10739 f_sleep(1.0);
10740 vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
10741 vc_conn.done;
Oliver Smith39f53072022-10-27 14:44:04 +020010742 f_shutdown_helper(ho := true);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010743}
10744
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010745private function f_tc_emerg_call_and_lcs_loc_req(charstring id) runs on MSC_ConnHdlr
10746{
10747 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
10748 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
10749 * another lchan. */
Pau Espin Pedrol1809bce2023-01-03 16:54:41 +010010750 g_pars.ra := f_rnd_ra_emerg();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010751 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010752 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010753
10754 /* Here would usually be a CC Call Proceeding from the MSC, but what does the BSC care about DTAP. */
10755
10756 /* Do a Location Request in-between the CC call setup */
10757 f_bssap_le_register_imsi(g_pars.imsi, omit);
10758 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10759 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10760 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10761 /* SMLC got the TA from the BSC, now responds with geo information data. */
10762 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10763 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10764 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10765
Pau Espin Pedrol14076d32023-01-03 17:07:59 +010010766 f_assignment_emerg_setup_voice();
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010767
10768 setverdict(pass);
10769 f_perform_clear();
10770}
10771
10772testcase TC_emerg_call_and_lcs_loc_req() runs on test_CT {
10773 var MSC_ConnHdlr vc_conn;
10774 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10775
10776 f_init(1, true);
10777 f_sleep(1.0);
10778 f_vty_allow_emerg_msc(true);
10779 f_vty_allow_emerg_bts(true, 0);
10780 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req), pars);
10781 vc_conn.done;
10782 f_shutdown_helper();
10783}
10784
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010785private altstep no_bssmap_clear_req() runs on MSC_ConnHdlr {
10786 [] BSSAP.receive(tr_BSSMAP_ClearRequest) {
10787 setverdict(fail, "unexpected BSSMAP Clear Request");
10788 mtc.stop;
10789 }
10790}
10791
10792private type enumerated RslRel {
10793 RSLREL_REL_IND,
10794 RSLREL_CONN_FAIL
10795};
10796
10797private function f_emerg_call_and_lcs_loc_req_early_lchan_release(RslRel rsl_rel) runs on MSC_ConnHdlr
10798{
10799 g_pars.ra := f_rnd_ra_emerg();
10800 f_assignment_emerg_setup();
Pau Espin Pedrol39bd33c2023-01-03 17:05:27 +010010801 f_assignment_emerg_setup_exp_bssap();
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010802
10803 /* Start a Location Request to locate the emergency */
10804 f_bssap_le_register_imsi(g_pars.imsi, omit);
10805 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10806 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10807 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10808
10809 /* 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
10810 * do a Clear Command when the Location Response arrives. */
10811 activate(no_bssmap_clear_req());
10812
10813 /* the lchan gets interrupted while the Location Request has no response */
10814 select (rsl_rel) {
10815 case (RSLREL_REL_IND) {
10816 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
10817 f_expect_lchan_rel(RSL, RSL_PROC);
10818 }
10819 case (RSLREL_CONN_FAIL) {
10820 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
10821 }
10822 case else {
10823 setverdict(fail, "Unknown RslRel type");
10824 mtc.stop;
10825 }
10826 }
10827
10828 /* Still expect the Location Response to find its way to the MSC. */
10829 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10830 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10831 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10832
10833 setverdict(pass);
10834
10835 select (rsl_rel) {
10836 case (RSLREL_REL_IND) {
10837 f_perform_clear_no_lchan();
10838 }
10839 case (RSLREL_CONN_FAIL) {
10840 f_perform_clear();
10841 }
10842 }
10843}
10844
10845private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind(charstring id) runs on MSC_ConnHdlr
10846{
10847 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_REL_IND);
10848}
10849
10850testcase TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() runs on test_CT {
10851 var MSC_ConnHdlr vc_conn;
10852 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10853
10854 f_init(1, true);
10855 f_sleep(1.0);
10856 f_vty_allow_emerg_msc(true);
10857 f_vty_allow_emerg_bts(true, 0);
10858 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind), pars);
10859 vc_conn.done;
10860 f_shutdown_helper();
10861}
10862
10863private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail(charstring id) runs on MSC_ConnHdlr
10864{
10865 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_CONN_FAIL);
10866}
10867
10868testcase TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() runs on test_CT {
10869 var MSC_ConnHdlr vc_conn;
10870 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10871
10872 f_init(1, true);
10873 f_sleep(1.0);
10874 f_vty_allow_emerg_msc(true);
10875 f_vty_allow_emerg_bts(true, 0);
10876 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail), pars);
10877 vc_conn.done;
10878 f_shutdown_helper();
10879}
10880
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010881/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
10882private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
10883 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10884
10885 /* Also disable attach for the single connected MSC */
10886 f_vty_msc_allow_attach(BSCVTY, { false });
10887
10888 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) ));
10889 f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
10890
10891 /* No MSC is found, expecting a proper release on RSL */
10892 interleave {
10893 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
10894 f_logp(BSCVTY, "Got RSL RR Release");
10895 }
10896 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10897 f_logp(BSCVTY, "Got RSL Deact SACCH");
10898 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010899 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010900 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
10901 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010902 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010903 }
10904 }
10905 setverdict(pass);
10906}
10907testcase TC_no_msc() runs on test_CT {
10908
10909 f_init(1, true);
10910 f_sleep(1.0);
10911 var MSC_ConnHdlr vc_conn;
10912 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10913
10914 f_ctrs_bsc_init(counternames_bsc_mscpool);
10915
10916 vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
10917 vc_conn.done;
10918
10919 f_ctrs_bsc_add("mscpool:subscr:no_msc");
10920 f_ctrs_bsc_verify();
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010921 f_shutdown_helper();
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010922}
10923
Harald Welte0ea2d5e2018-04-07 21:40:29 +020010924/* Dyn PDCH todo:
10925 * activate OSMO as TCH/F
10926 * activate OSMO as TCH/H
10927 * does the BSC-located PCU socket get the updated INFO?
10928 * what if no PCU is connected at the time?
10929 * is the info correct on delayed PCU (re)connect?
10930 */
Harald Welte94e0c342018-04-07 11:33:23 +020010931
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010932private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +020010933 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020010934 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010935
10936 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
10937 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10938 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
10939 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
10940 g_pars.ass_codec_list.codecElements[0];
10941 if (isvalue(g_pars.expect_mr_s0_s7)) {
10942 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
10943 g_pars.expect_mr_s0_s7;
10944 }
10945 }
10946 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
10947 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
10948 log("expecting ASS COMPL like this: ", exp_compl);
10949
10950 f_establish_fully(ass_cmd, exp_compl);
10951
Neels Hofmeyr8746b0d2021-06-01 17:25:39 +020010952 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 +000010953
10954 var RSL_Message rsl;
10955
10956 timer T := 5.0;
10957 T.start;
10958 alt {
10959 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
10960 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
10961 log("Rx L3 from net: ", l3);
10962 if (ischosen(l3.msgs.rrm.channelModeModify)) {
10963 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10964 mtc.stop;
10965 }
10966 }
10967 [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
10968 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10969 mtc.stop;
10970 }
10971 [] T.timeout {
10972 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
10973 setverdict(pass);
10974 }
10975 }
10976 T.stop;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010977
10978 f_perform_clear();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010979}
10980
10981/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
10982 * osmo-bsc. */
10983testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
10984 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10985 var MSC_ConnHdlr vc_conn;
10986
10987 f_init(1, true);
10988 f_sleep(1.0);
10989
10990 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10991 vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
10992 vc_conn.done;
10993 f_shutdown_helper();
10994}
10995
10996/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
10997 */
10998testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
10999 f_init_vty();
11000
11001 f_init(1, false);
11002 f_sleep(1.0);
11003
11004 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
11005
11006 var ASP_RSL_Unitdata rx_rsl_ud;
11007 timer T := 5.0;
11008
11009 T.start;
11010 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011011 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011012 if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
11013 T.stop;
11014 setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
11015 mtc.stop;
11016 }
11017 repeat;
11018 }
11019 [] T.timeout {
11020 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
11021 setverdict(pass);
11022 }
11023 }
11024}
11025
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011026private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
11027 /* First fully set up a speech lchan */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011028 f_assignment_codec(id, do_perform_clear := false);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011029
11030 /* Trigger re-assignment to another lchan */
11031 var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
11032
11033 /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
11034 * one MDCX on MGCP. */
11035 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
11036
11037 /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
11038 * as the old lchan used. */
11039 g_media.bts.ipa_crcx_seen := false;
11040 g_media.bts.ipa_mdcx_seen := false;
11041
11042 /* Send different BTS side RTP port number for the new lchan */
11043 g_media.bts.bts.port_nr := 4223;
11044
11045 f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
11046
11047 /* Trigger re-assignment. */
11048 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
11049
11050 timer T := 5.0;
11051 T.start;
11052 alt {
11053 [] as_assignment(assignment_st);
11054 [] as_Media();
11055 [] T.timeout {
11056 break;
11057 }
11058 }
11059
11060 if (not assignment_st.assignment_done) {
11061 setverdict(fail, "Assignment did not complete");
11062 mtc.stop;
11063 }
11064
11065 f_check_mgcp_expectations()
11066 setverdict(pass);
11067
11068 f_sleep(2.0);
11069 log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
11070
11071 /* Instruct BSC to clear channel */
11072 var BssmapCause cause := 0;
11073 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
11074 interleave {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011075 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
11076 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020011077 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011078 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020011079 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011080 }
11081 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
11082 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11083 }
11084 }
Neels Hofmeyr40a45d12021-09-23 22:57:12 +020011085 f_expect_dlcx_conns();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011086
11087 f_sleep(0.5);
11088}
11089
11090testcase TC_reassignment_fr() runs on test_CT {
11091 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11092 var MSC_ConnHdlr vc_conn;
11093
11094 f_init(1, true);
11095 f_sleep(1.0);
11096
Neels Hofmeyrac432fa2021-11-02 16:45:56 +010011097 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011098
11099 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11100 vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
11101 vc_conn.done;
11102
11103 /* from f_establish_fully() */
11104 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
11105 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
11106 /* from re-assignment */
11107 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
11108 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
11109 f_ctrs_bsc_and_bts_verify();
11110 f_shutdown_helper();
11111}
11112
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011113const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
11114const charstring REEST_CLEAR := "REEST_CLEAR";
11115const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
11116
11117/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
11118 * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
11119 * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
11120 * the MSC as the CM Re-Establishment is handled.
11121 *
11122 * MS bts0 bts1 bsc msc test-component
11123 * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
11124 * | | _1 wait a bit, to settle down
11125 * |<-x x--| | _1 "lose connection"
11126 * | | REEST_LOST_CONNECTION
11127 * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
11128 * | | REEST_CLEAR
11129 * | |<-0---| _1 Clear Command on first A-conn
11130 * | |--0-->| _1 Clear Complete
11131 * | |<----------------->| | _1 Release first channel
11132 * | | REEST_CLEAR_DONE
11133 * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
11134 * |<-----------------|<-------|<-1---| _2 Clear Command, Release
11135 *
11136 */
11137private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
11138 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
11139 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11140
11141 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11142 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11143
11144 f_establish_fully(ass_cmd, exp_compl);
11145
11146 /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
11147 * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
11148 * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
11149 f_sleep(2.0);
11150 COORD.send(REEST_LOST_CONNECTION);
11151
11152 alt {
11153 [] COORD.receive(REEST_CLEAR);
11154 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
11155 setverdict(fail, "Unexpected channel release");
11156 mtc.stop;
11157 }
11158 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
11159 setverdict(fail, "Unexpected channel release");
11160 mtc.stop;
11161 }
11162 }
11163 f_perform_clear()
Neels Hofmeyr969abd02021-09-23 22:24:08 +020011164 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011165 COORD.send(REEST_CLEAR_DONE);
11166}
11167
11168private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
11169 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
11170
11171 /* The MS lost the connection on the first channel, now establishes another one */
11172 COORD.receive(REEST_LOST_CONNECTION);
11173
11174 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
11175 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
11176 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
11177
11178 f_create_bssmap_exp(l3_enc);
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011179 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 +020011180 BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
11181
11182 /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
11183 COORD.send(REEST_CLEAR);
11184 COORD.receive(REEST_CLEAR_DONE);
11185
11186 f_sleep(2.0);
11187
11188 /* Answer the CM Re-Establishment with an Assignment Command. */
11189 var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
11190 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11191 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11192 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11193
11194 var AssignmentState st := valueof(ts_AssignmentStateInit);
Oliver Smithce2dd692023-04-17 10:25:50 +020011195 st.rtp_stream := true;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011196 st.is_assignment := true;
11197
11198 var ExpectCriteria mgcpcrit := {
11199 connid := omit,
11200 endpoint := omit,
11201 transid := omit
11202 };
11203 f_create_mgcp_expect(mgcpcrit);
11204
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011205 f_rslem_dchan_queue_enable(RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011206
11207 BSSAP.send(ass_cmd);
11208
11209 var PDU_BSSAP bssap;
11210
11211 alt {
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011212 [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
11213 [] as_Media_ipacc(RSL1, RSL2);
11214 [] as_Media_mgw();
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011215 [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
11216 break;
11217 }
11218 }
11219
11220 f_sleep(3.0);
11221
11222 f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020011223 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011224}
11225
11226testcase TC_cm_reestablishment() runs on test_CT {
11227 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
11228 var MSC_ConnHdlr vc_conn1;
11229
11230 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
11231 var MSC_ConnHdlr vc_conn2;
11232 pars2.imsi := pars1.imsi;
11233 pars2.media_nr := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011234 pars2.expect_tsc := c_BtsParams[1].tsc;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011235
11236 f_init(2, true, guard_timeout := 40.0);
11237 f_sleep(1.0);
11238
11239 vc_conn1 := f_start_handler_create(pars1);
11240 vc_conn2 := f_start_handler_create(pars2);
11241 connect(vc_conn1:COORD, vc_conn2:COORD);
11242 f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
11243 f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
11244 vc_conn1.done;
11245 vc_conn2.done;
11246
11247 f_shutdown_helper();
11248}
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011249
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011250function f_exp_ipa_rx_nonfatal(template (present) RSL_Message t_rx,
11251 boolean ignore_other_rx := true,
11252 BtsTrxIdx idx := {0, 0},
11253 float Tval := 2.0)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011254runs on test_CT return template (omit) RSL_Message {
11255 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011256 timer T := Tval;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011257
11258 T.start;
11259 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011260 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011261 T.stop;
11262 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011263 [ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
11264 [not ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011265 log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
11266 T.stop;
11267 return omit;
11268 }
11269 [] T.timeout {
11270 return omit;
11271 }
11272 }
11273 return rx_rsl_ud.rsl;
11274}
11275
11276private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
11277 f_vty_enter_cfg_bts(pt, bts_nr);
11278 f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
11279 f_vty_transceive(pt, "exit");
11280 f_vty_transceive(pt, "exit");
11281 f_vty_transceive(pt, "exit");
11282}
11283
11284private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +030011285 template (present) RslChannelNr chan_nr := ?,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011286 template (present) uint12_t arfcn := ?,
11287 template (present) uint3_t tsc := ?)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011288{
11289 var RSL_IE_Body full_imm_ass_info;
11290 if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
11291 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
11292 mtc.stop;
11293 }
11294
11295 var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
11296 var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
11297 fn := fn,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011298 ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011299 page_mode := ?);
11300 if (not match(rr_imm_ass, expect_imm_ass)) {
11301 log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
11302 setverdict(fail, "Failed to match Immediate Assignment");
11303 mtc.stop;
11304 }
11305}
11306
11307testcase TC_imm_ass_post_chan_ack() runs on test_CT {
11308 var RSL_Message chan_act;
11309 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011310 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011311
11312 f_init(1, false);
11313 f_sleep(1.0);
11314
11315 /* (should be the default anyway, just to make things clear) */
11316 f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
11317
11318 /* RA containing reason=LU */
11319 var GsmFrameNumber fn := 2342;
11320 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011321 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011322
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011323 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011324
11325 /* First send the Chan Act ACK */
11326 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011327 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011328 var RSL_IE_Body chan_ident_ie;
11329 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11330 setverdict(fail, "RSL Channel Identification IE is absent");
11331 mtc.stop;
11332 }
11333
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011334 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011335
11336 /* Then expect the Immediate Assignment, after we ACKed the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011337 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011338
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011339 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11340 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011341
11342 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011343 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011344
11345 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011346 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011347 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011348 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11349
11350 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011351 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011352 f_shutdown_helper();
11353}
11354
11355testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
11356 var RSL_Message chan_act;
11357 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011358 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011359
11360 f_init(1, false);
11361 f_sleep(1.0);
11362
11363 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11364
11365 /* RA containing reason=LU */
11366 var GsmFrameNumber fn := 2342;
11367 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011368 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011369
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011370 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011371 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011372 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011373 var RSL_IE_Body chan_ident_ie;
11374 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11375 setverdict(fail, "RSL Channel Identification IE is absent");
11376 mtc.stop;
11377 }
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011378
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011379 /* (set bts 0 cfg back to default) */
11380 f_vty_set_imm_ass(BSCVTY);
11381
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011382 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011383 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011384 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11385 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011386
11387 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011388 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011389
11390 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011391 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011392
11393 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011394 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011395 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011396 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11397
11398 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011399 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011400 f_shutdown_helper();
11401}
11402
Neels Hofmeyr23158742021-09-07 19:08:07 +020011403testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
11404 var RSL_Message chan_act;
11405 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011406 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr23158742021-09-07 19:08:07 +020011407
11408 f_init(1, false);
11409 f_sleep(1.0);
11410
11411 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11412
11413 /* RA containing reason=LU */
11414 var GsmFrameNumber fn := 2342;
11415 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011416 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011417
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011418 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011419 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011420 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr23158742021-09-07 19:08:07 +020011421 var RSL_IE_Body chan_ident_ie;
11422 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11423 setverdict(fail, "RSL Channel Identification IE is absent");
11424 mtc.stop;
11425 }
11426
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011427 /* (set bts 0 cfg back to default) */
11428 f_vty_set_imm_ass(BSCVTY);
11429
Neels Hofmeyr23158742021-09-07 19:08:07 +020011430 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011431 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011432 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11433 chan_ident_ie.chan_ident.ch_desc.v.tsc);
11434
11435 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011436 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011437
11438 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011439 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011440
11441 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011442 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011443 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr23158742021-09-07 19:08:07 +020011444 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11445
11446 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011447 f_perform_clear_test_ct(dt);
Neels Hofmeyr23158742021-09-07 19:08:07 +020011448 f_shutdown_helper();
11449}
11450
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011451testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
11452 /* change Timeslot 6 before f_init() starts RSL */
11453 f_init_vty();
11454 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11455 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11456
11457 f_init(1, false);
11458 f_sleep(1.0);
11459
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011460 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011461 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11462 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011463 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11464 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011465
11466 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11467 f_ts_set_chcomb(0, 0, 6, "PDCH");
11468
11469 /* block all static timeslots so that the dyn TS will be used */
11470 f_disable_all_tch_f();
11471 f_disable_all_tch_h();
11472 f_disable_all_sdcch();
11473
11474 var RSL_Message chan_act;
11475 var RSL_Message imm_ass;
11476
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011477 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11478
11479 /* RA containing reason=LU */
11480 var GsmFrameNumber fn := 2342;
11481 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011482 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011483
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011484 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011485 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
11486 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011487
11488 /* Now activation as SDCCH8 */
11489 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011490 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011491
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011492 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011493 var RSL_IE_Body chan_ident_ie;
11494 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11495 setverdict(fail, "RSL Channel Identification IE is absent");
11496 mtc.stop;
11497 }
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011498
11499 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011500 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011501 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11502 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011503
11504 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011505 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011506
11507 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011508 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011509
11510 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011511 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011512 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011513 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11514
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011515 /* (set bts 0 cfg back to default) */
11516 f_vty_set_imm_ass(BSCVTY);
11517
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011518 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011519 f_perform_clear_test_ct(dt);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011520 f_shutdown_helper();
11521}
11522
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011523testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
11524 /* change Timeslot 6 before f_init() starts RSL */
11525 f_init_vty();
11526 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11527 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11528
11529 f_init(1, false);
11530 f_sleep(1.0);
11531
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011532 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011533 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11534 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011535 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11536 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011537
11538 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11539 f_ts_set_chcomb(0, 0, 6, "PDCH");
11540
11541 /* block all static timeslots so that the dyn TS will be used */
11542 f_disable_all_tch_f();
11543 f_disable_all_tch_h();
11544 f_disable_all_sdcch();
11545
11546 var RSL_Message chan_act;
11547 var RSL_Message imm_ass;
11548
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011549 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11550
11551 /* RA containing reason=LU */
11552 var GsmFrameNumber fn := 2342;
11553 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011554 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011555
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011556 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011557 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011558
11559 /* And already the Immediate Assignment even before the PDCH Deact ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011560 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011561
11562 /* continue the Osmo style PDCH Deact (usual chan rel) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011563 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011564
11565 /* Now activation as SDCCH8 */
11566 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011567 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011568
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011569 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011570 var RSL_IE_Body chan_ident_ie;
11571 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11572 setverdict(fail, "RSL Channel Identification IE is absent");
11573 mtc.stop;
11574 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011575 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011576
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011577 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11578 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011579
11580 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011581 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011582
11583 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011584 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011585 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011586 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11587
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011588 /* (set bts 0 cfg back to default) */
11589 f_vty_set_imm_ass(BSCVTY);
11590
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011591 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011592 f_perform_clear_test_ct(dt);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011593 f_shutdown_helper();
11594}
11595
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011596/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
11597testcase TC_ctrl_trx_rf_locked() runs on test_CT {
11598 var MSC_ConnHdlr vc_conn;
11599
11600 f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
11601 f_sleep(1.0);
11602
11603 /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
11604 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11605 "0,0,operational,unlocked,on,rsl-up;" &
11606 "1,0,operational,unlocked,on,rsl-up;" &
11607 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011608 "2,1,operational,unlocked,on,rsl-down;" &
11609 "2,2,operational,unlocked,on,rsl-down;" &
11610 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011611 "3,0,inoperational,locked,on,rsl-down;");
11612
11613 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock BTS 1 TRX 0");
11614 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11615 /* give it a moment to settle the FSM status */
11616 f_sleep(1.0);
11617
11618 /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
11619 * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
11620 * of "off"? But that's for a future patch if at all. */
11621 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11622 "0,0,operational,unlocked,on,rsl-up;" &
11623 "1,0,operational,locked,on,rsl-up;" &
11624 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011625 "2,1,operational,unlocked,on,rsl-down;" &
11626 "2,2,operational,unlocked,on,rsl-down;" &
11627 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011628 "3,0,inoperational,locked,on,rsl-down;");
11629
11630 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
11631 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11632 f_sleep(1.0);
11633 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11634 "0,0,operational,unlocked,on,rsl-up;" &
11635 "1,0,operational,locked,on,rsl-up;" &
11636 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011637 "2,1,operational,unlocked,on,rsl-down;" &
11638 "2,2,operational,unlocked,on,rsl-down;" &
11639 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011640 "3,0,inoperational,locked,on,rsl-down;");
11641
11642 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
11643 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
11644 f_sleep(1.0);
11645 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11646 "0,0,operational,unlocked,on,rsl-up;" &
11647 "1,0,operational,unlocked,on,rsl-up;" &
11648 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011649 "2,1,operational,unlocked,on,rsl-down;" &
11650 "2,2,operational,unlocked,on,rsl-down;" &
11651 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011652 "3,0,inoperational,locked,on,rsl-down;");
11653
11654 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
11655 f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
11656 f_sleep(1.0);
11657 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11658 "0,0,operational,unlocked,on,rsl-up;" &
11659 "1,0,operational,unlocked,on,rsl-up;" &
11660 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011661 "2,1,operational,unlocked,on,rsl-down;" &
11662 "2,2,operational,unlocked,on,rsl-down;" &
11663 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011664 "3,0,inoperational,locked,on,rsl-down;");
11665
11666 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
11667 f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
11668 f_sleep(1.0);
11669 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11670 "0,0,operational,unlocked,on,rsl-up;" &
11671 "1,0,operational,unlocked,on,rsl-up;" &
11672 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011673 "2,1,operational,unlocked,on,rsl-down;" &
11674 "2,2,operational,unlocked,on,rsl-down;" &
11675 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011676 "3,0,inoperational,locked,on,rsl-down;");
11677
11678 f_shutdown_helper();
11679}
11680
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011681const CounterNameVals counternames_cm_serv_rej := {
11682 { "cm_serv_rej", 0 },
11683 { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
11684 { "cm_serv_rej:illegal_ms", 0 },
11685 { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
11686 { "cm_serv_rej:imei_not_accepted", 0 },
11687 { "cm_serv_rej:illegal_me", 0 },
11688 { "cm_serv_rej:plmn_not_allowed", 0 },
11689 { "cm_serv_rej:loc_not_allowed", 0 },
11690 { "cm_serv_rej:roaming_not_allowed", 0 },
11691 { "cm_serv_rej:network_failure", 0 },
11692 { "cm_serv_rej:synch_failure", 0 },
11693 { "cm_serv_rej:congestion", 0 },
11694 { "cm_serv_rej:srv_opt_not_supported", 0 },
11695 { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
11696 { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
11697 { "cm_serv_rej:call_can_not_be_identified", 0 },
11698 { "cm_serv_rej:incorrect_message", 0 },
11699 { "cm_serv_rej:invalid_mandantory_inf", 0 },
11700 { "cm_serv_rej:msg_type_not_implemented", 0 },
11701 { "cm_serv_rej:msg_type_not_compatible", 0 },
11702 { "cm_serv_rej:inf_eleme_not_implemented", 0 },
11703 { "cm_serv_rej:condtional_ie_error", 0 },
11704 { "cm_serv_rej:msg_not_compatible", 0 },
11705 { "cm_serv_rej:protocol_error", 0 },
11706 { "cm_serv_rej:retry_in_new_cell", 0 }
11707};
11708
11709private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
11710{
11711 f_create_chan_and_exp();
Vadim Yanitskiya7fc5a62021-12-04 20:10:08 +030011712 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011713 BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011714 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_CM_SERV_REJ));
11715 f_perform_clear();
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011716 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011717}
11718testcase TC_cm_serv_rej() runs on test_CT {
11719 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11720 var MSC_ConnHdlr vc_conn;
11721
11722 f_init(1, true);
11723 f_sleep(1.0);
11724
11725 f_ctrs_bts_init(1, counternames_cm_serv_rej);
11726
11727 vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
11728 vc_conn.done;
11729
11730 f_ctrs_bts_add(0, "cm_serv_rej", 1);
11731 f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
11732 f_ctrs_bts_verify();
11733
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011734 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011735 f_shutdown_helper();
11736}
11737
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011738/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
11739 * Activ Ack (SYS#5627). */
11740private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
11741 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Vadim Yanitskiyf0310e32021-10-26 00:30:59 +030011742
11743 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11744 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011745
11746 var BSSMAP_FIELD_CodecType codecType;
11747 codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
11748
11749 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
11750
11751 /* First establish a signalling lchan */
11752 f_create_chan_and_exp();
11753 f_rslem_dchan_queue_enable();
11754
11755 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011756
11757 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
Oliver Smith735b47c2023-02-15 16:03:54 +010011758 activate(as_Media_mgw());
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011759
11760 var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
11761 f_rslem_register(0, chan_nr);
11762
11763 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
11764 BSSAP.send(ass_cmd);
11765
11766
11767 /* Wait for the Channel Activ for the TCH channel */
11768 var ASP_RSL_Unitdata rx_rsl_ud;
11769 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
11770
11771 /* make the original SDCCH disappear */
11772 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
11773
11774 /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
11775 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
11776
11777 interleave {
11778 [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
11779 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
11780 }
11781
11782 BSSAP.send(ts_BSSMAP_ClearCommand(0));
11783 BSSAP.receive(tr_BSSMAP_ClearComplete);
11784 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11785
11786 var MgcpCommand mgcp;
Vadim Yanitskiy6be4cf42022-06-04 21:25:47 +060011787 var MGCP_RecvFrom mrf;
11788 var template MgcpMessage msg_dlcx := { command := tr_DLCX };
11789 alt {
11790 [g_pars.aoip] MGCP.receive(tr_DLCX) -> value mgcp {
11791 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
11792 }
11793 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
11794 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
11795 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
11796 }));
11797 }
11798 }
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011799
11800 f_sleep(0.5);
11801}
11802testcase TC_lost_sdcch_during_assignment() runs on test_CT {
11803 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11804 var MSC_ConnHdlr vc_conn;
11805
Oliver Smith735b47c2023-02-15 16:03:54 +010011806 pars.fail_on_dlcx := false;
11807
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011808 f_init(1, true);
11809 f_sleep(1.0);
11810
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011811 vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
11812 vc_conn.done;
11813
11814 f_shutdown_helper();
11815}
11816
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011817const CounterNameVals counternames_bsc_bts_all_available_allocated := {
11818 { "all_allocated:sdcch", 0 },
11819 { "all_allocated:static_sdcch", 0 },
11820 { "all_allocated:tch", 0 },
11821 { "all_allocated:static_tch", 0 }
11822}
11823
11824private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
11825{
11826 /* Make sure counters settle first */
11827 f_sleep(1.0);
11828
11829 /* Take a baseline of counters */
11830 f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
11831
11832 /* Elapse some time so that we see changes in counters, hopefully where expected */
11833 f_sleep(2.0);
11834
11835 /* Get new counters */
11836 var charstring_list all_changed := {};
11837 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
11838 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
11839
11840 /* Compare with expectations */
11841 var charstring_list all_expect_changed := {};
11842 for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
11843 all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
11844 }
11845 f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
11846}
11847
11848testcase TC_ratectr_all_available_allocated() runs on test_CT {
11849 var ASP_RSL_Unitdata rsl_ud;
11850 var integer i;
11851 var integer chreq_total, chreq_nochan;
11852
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011853 f_init(1, guard_timeout := 60.0);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011854 f_sleep(1.0);
11855
11856 /* Exhaust all dedicated SDCCH lchans.
11857 /* GSM 44.018 Table 9.1.8.2:
11858 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11859 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011860 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011861 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011862 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 +020011863 }
11864
11865 /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
11866 * level.
11867 * All SDCCH are now occupied. */
11868 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11869
11870 /* Also fill up all remaining (TCH) channels */
11871 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011872 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 +020011873 }
11874
11875 /* All TCH are now also occupied */
11876 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11877 "all_allocated:tch", "all_allocated:static_tch"});
11878
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011879 /* Clean up SDCCH lchans */
11880 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11881 f_perform_clear_test_ct(chan_cleanup[i]);
11882 }
11883
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011884 f_shutdown_helper();
11885}
11886
11887testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
11888 var ASP_RSL_Unitdata rsl_ud;
11889 var integer i;
11890 var integer chreq_total, chreq_nochan;
11891
11892 f_init_vty();
11893 f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
11894 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11895 /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
11896
11897 f_init(1, guard_timeout := 60.0);
11898 f_sleep(1.0);
11899
11900 /* The dyn TS wants to activate PDCH mode, ACK that. */
11901 var RslChannelNr chan_nr;
11902 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011903 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11904 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011905
11906 /* Exhaust all dedicated SDCCH lchans.
11907 /* GSM 44.018 Table 9.1.8.2:
11908 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11909 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011910 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011911 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011912 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 +020011913 }
11914
11915 /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
11916 * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
11917 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
11918
11919 /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
11920 * Will release them later, so remember all the DchanTuples. */
11921 var DchanTuples dyn_sddch := {};
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011922 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 +020011923
11924 /* Also occupy the seven other SDCCH of the dyn TS */
11925 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011926 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 +020011927 }
11928
11929 /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
11930 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11931
11932 /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
11933 for (i := 0; i < 5; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011934 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 +020011935 }
11936
11937 /* All TCH lchans are now also occupied, both static and dynamic */
11938 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11939 "all_allocated:tch", "all_allocated:static_tch"});
11940
11941 /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
11942 * incrementing. */
11943 var BssmapCause cause := 0;
11944 var DchanTuple dt := dyn_sddch[0];
11945 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011946 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011947
11948 /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
11949 * count as occupied, so those still both increment. */
11950 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
11951 "all_allocated:tch", "all_allocated:static_tch"});
11952
11953 /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
11954 for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
11955 dt := dyn_sddch[i];
11956 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011957 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011958 }
11959
11960 /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
11961 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011962 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11963 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011964
11965 /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
11966 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
11967
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011968 /* Clean up SDCCH lchans */
11969 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11970 f_perform_clear_test_ct(chan_cleanup[i]);
11971 }
11972
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011973 /* clean up config */
11974 f_ts_reset_chcomb(0);
11975
11976 f_shutdown_helper();
11977}
11978
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011979private function f_TC_chan_alloc_algo(DchanTuple dt, BtsTrxIdx idx)
11980runs on test_CT {
11981 /* MSC sends an Assignment Request */
11982 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11983 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11984 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11985 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
11986
11987 /* Expect the BSC to allocate a TCH channel on the given BTS/TRX */
11988 var RSL_Message rsl_chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
11989 /* Send CHAN ACT NACK, so that the requested TCH channel becomes BORKEN */
11990 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(rsl_chan_act.ies[0].body.chan_nr, RSL_ERR_EQUIPMENT_FAIL), idx);
11991 /* Expect to receive an Assignment Failure */
11992 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail));
11993}
11994
11995testcase TC_chan_alloc_algo_ascending() 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 ascending");
12004 f_vty_transceive(BSCVTY, "end");
12005
12006 /* Expect the BSC to allocate 4 x TCH/F channels on BTS2/TRX0 */
12007 for (var integer i := 0; i < 4; 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, 0});
12010 f_perform_clear_test_ct(dt);
12011 }
12012
12013 /* At this point all 4 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
12018testcase TC_chan_alloc_algo_descending() runs on test_CT {
12019 /* We need to access BTS2, which has 4 TRXs */
12020 f_init(nr_bts := 3);
12021
12022 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012023 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012024
12025 f_vty_enter_cfg_bts(BSCVTY, 2);
12026 f_vty_transceive(BSCVTY, "channel allocator descending");
12027 f_vty_transceive(BSCVTY, "end");
12028
12029 /* Expect the BSC to allocate 5 x TCH/F channels on BTS2/TRX3 */
12030 for (var integer i := 0; i < 5; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012031 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012032 f_TC_chan_alloc_algo(dt, {2, 3});
12033 f_perform_clear_test_ct(dt);
12034 }
12035
12036 /* At this point all 5 x TCH/F channels are BORKEN, but they will be
12037 * resurrected upon the A-bis/OML link re-establishment. */
12038 f_shutdown_helper();
12039}
12040
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012041testcase TC_chan_alloc_algo_ass_dynamic() runs on test_CT {
12042 const BtsTrxIdx TRX0 := {2, 0};
12043 const BtsTrxIdx TRX3 := {2, 3};
12044
12045 /* We need to access BTS2, which has 4 TRXs */
12046 f_init(nr_bts := 3);
12047
12048 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020012049 vc_MGCP[0].stop;
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012050
12051 f_vty_enter_cfg_bts(BSCVTY, 2);
12052 f_vty_transceive(BSCVTY, "channel allocator mode assignment dynamic");
12053 f_vty_transceive(BSCVTY, "channel allocator dynamic-param ul-rxlev thresh 50 avg-num 2");
12054 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 0");
12055 f_vty_transceive(BSCVTY, "end");
12056
12057 var DchanTuple dt;
12058
12059 f_logp(BSCVTY, "Case a) Unknown Uplink RxLev, fall-back to ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012060 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012061 f_TC_chan_alloc_algo(dt, TRX0);
12062 f_perform_clear_test_ct(dt);
12063
12064 f_logp(BSCVTY, "Case b) Not enough RxLev samples, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012065 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012066 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12067 ts_RSL_IE_UplinkMeas(30, 0),
12068 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012069 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012070 f_TC_chan_alloc_algo(dt, TRX0);
12071 f_perform_clear_test_ct(dt);
12072
12073 f_logp(BSCVTY, "Case c) Uplink RxLev below the threshold, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012074 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012075 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12076 ts_RSL_IE_UplinkMeas(45, 0),
12077 ts_RSL_IE_BS_Power(0)), TRX0);
12078 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12079 ts_RSL_IE_UplinkMeas(48, 0),
12080 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012081 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012082 f_TC_chan_alloc_algo(dt, TRX0);
12083 f_perform_clear_test_ct(dt);
12084
12085 f_logp(BSCVTY, "Case d) Uplink RxLev above the threshold, use descending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012086 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012087 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12088 ts_RSL_IE_UplinkMeas(50, 0),
12089 ts_RSL_IE_BS_Power(0)), TRX0);
12090 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12091 ts_RSL_IE_UplinkMeas(58, 0),
12092 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012093 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012094 f_TC_chan_alloc_algo(dt, TRX3);
12095 f_perform_clear_test_ct(dt);
12096
12097 f_vty_enter_cfg_bts(BSCVTY, 2);
12098 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 90");
12099 f_vty_transceive(BSCVTY, "end");
12100
12101 f_logp(BSCVTY, "Case e) Uplink RxLev above the threshold, but C0 load is not");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010012102 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012103 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
12104 ts_RSL_IE_UplinkMeas(50, 0),
12105 ts_RSL_IE_BS_Power(0)), TRX0);
12106 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
12107 ts_RSL_IE_UplinkMeas(58, 0),
12108 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070012109 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012110 f_TC_chan_alloc_algo(dt, TRX0);
12111 f_perform_clear_test_ct(dt);
12112
12113 f_vty_enter_cfg_bts(BSCVTY, 2);
12114 f_vty_transceive(BSCVTY, "channel allocator ascending");
12115 f_vty_transceive(BSCVTY, "end");
12116
12117 /* At this point some TCH/F channels are BORKEN, but they will be
12118 * resurrected upon the A-bis/OML link re-establishment. */
12119 f_shutdown_helper();
12120}
12121
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012122private function f_vty_mgw_enable(integer mgw_nr := 1) runs on test_CT {
12123 var rof_charstring cmds := {
12124 "remote-ip " & mp_test_ip,
12125 "remote-port " & int2str(2427 + mgw_nr)
12126 };
12127 f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
12128 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " reconnect")
12129}
12130private function f_vty_mgw_disable(integer mgw_nr := 1) runs on test_CT {
12131 f_vty_config3(BSCVTY, {"network"}, { "no mgw " &int2str(mgw_nr) });
12132}
12133private function f_vty_mgw_block(integer mgw_nr := 1, boolean blocked := true) runs on test_CT {
12134 var charstring arg;
12135 if (blocked) {
12136 arg := "block";
12137 } else {
12138 arg := "unblock";
12139 }
12140 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " " & arg);
12141}
12142private const charstring COORD_CMD_ESTABLISHED := "COORD_CMD_ESTABLISHED";
12143private function f_TC_mgwpool_call_seq_1(charstring id) runs on MSC_ConnHdlr {
12144 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12145 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12146 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12147 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12148
12149 f_establish_fully(ass_cmd, exp_compl);
12150 COORD.send(COORD_CMD_ESTABLISHED);
12151
12152 COORD.receive(COORD_CMD_ESTABLISHED);
12153 f_perform_clear()
12154 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12155}
12156private function f_TC_mgwpool_call_seq_2(charstring id) runs on MSC_ConnHdlr {
12157 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12158 var PDU_BSSAP ass_cmd := f_gen_ass_req();
12159 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12160 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12161
12162
12163 COORD.receive(COORD_CMD_ESTABLISHED);
12164 f_establish_fully(ass_cmd, exp_compl);
12165 COORD.send(COORD_CMD_ESTABLISHED);
12166
12167 f_perform_clear()
12168 f_create_mgcp_delete_ep(g_media.mgcp_ep);
12169}
12170/* Test load is spread around 2 available MGWs */
12171testcase TC_mgwpool_all_used() runs on test_CT {
12172 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12173 var MSC_ConnHdlr vc_conn1;
12174 pars1.mgwpool_idx := 0;
12175
12176 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12177 var MSC_ConnHdlr vc_conn2;
12178 pars2.mgwpool_idx := 1;
12179
12180 f_init(1, true, nr_mgw := 2);
12181 f_sleep(1.0);
12182
12183 f_vty_mgw_enable(1);
12184
12185 vc_conn1 := f_start_handler_create(pars1);
12186 vc_conn2 := f_start_handler_create(pars2);
12187 connect(vc_conn1:COORD, vc_conn2:COORD);
12188 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12189 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12190 vc_conn1.done;
12191 vc_conn2.done;
12192
12193 f_vty_mgw_disable(1);
12194
12195 f_shutdown_helper();
12196}
12197
12198/* Test blocked MGW in the pool are not selected */
12199testcase TC_mgwpool_blocked_not_used() runs on test_CT {
12200 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12201 var MSC_ConnHdlr vc_conn1;
12202 pars1.mgwpool_idx := 0;
12203
12204 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12205 var MSC_ConnHdlr vc_conn2;
12206 pars2.mgwpool_idx := 0; /* expect it in the first one, since the second will be blocked */
12207 pars2.media_nr := 2;
12208
12209 f_init(1, true, nr_mgw := 2);
12210 f_sleep(1.0);
12211
12212 f_vty_mgw_enable(1);
12213 f_vty_mgw_block(1, true);
12214
12215 vc_conn1 := f_start_handler_create(pars1);
12216 vc_conn2 := f_start_handler_create(pars2);
12217 connect(vc_conn1:COORD, vc_conn2:COORD);
12218 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12219 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12220 vc_conn1.done;
12221 vc_conn2.done;
12222
12223 f_vty_mgw_disable(1);
12224
12225 f_shutdown_helper();
12226}
12227
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012228/* Test BTS pinning to an MGW is applied */
12229testcase TC_mgwpool_pin_bts() runs on test_CT {
12230 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12231 var MSC_ConnHdlr vc_conn1;
12232 pars1.mgwpool_idx := 0;
12233
12234 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12235 var MSC_ConnHdlr vc_conn2;
12236 pars2.mgwpool_idx := 0; /* expect it in the first one, since the BTS is pinned to the first MGW */
12237 pars2.media_nr := 2;
12238
12239 f_init(1, true, nr_mgw := 2);
12240 f_sleep(1.0);
12241
12242 f_vty_mgw_enable(1);
12243 f_vty_cfg_bts(BSCVTY, 0, { "mgw pool-target 0" });
12244
12245 vc_conn1 := f_start_handler_create(pars1);
12246 vc_conn2 := f_start_handler_create(pars2);
12247 connect(vc_conn1:COORD, vc_conn2:COORD);
12248 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12249 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12250 vc_conn1.done;
12251 vc_conn2.done;
12252
12253 f_vty_cfg_bts(BSCVTY, 0, { "no mgw pool-target" } );
Vadim Yanitskiy389d7e02022-10-25 17:44:05 +070012254 f_vty_mgw_disable(1);
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012255
12256 f_shutdown_helper();
12257}
12258
Oliver Smithc9a5f532022-10-21 11:32:23 +020012259private function f_tc_ho_meas_rep_multi_band(charstring id) runs on MSC_ConnHdlr {
12260 g_pars := f_gen_test_hdlr_pars();
12261 var PDU_BSSAP ass_req := f_gen_ass_req();
12262 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12263 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12264 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12265 f_establish_fully(ass_req, exp_compl);
12266
12267 /* Send a measurement report with bad rxlev except on 3rd entry. The
12268 * measurement report is divided into two sub lists, as described in
12269 * 3GPP TS 04.08 § 10.5.2.20. */
12270 var NcellReports neighbor_rep := {
12271 /* Sub list 1: same band */
Oliver Smitha6773042022-10-24 12:56:30 +020012272 { rxlev := 0, bcch_freq := 0, bsic := 12 }, /* ARFCN 800, band 1800, LAC 98 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012273 /* Sub list 2: different band */
Oliver Smitha6773042022-10-24 12:56:30 +020012274 { rxlev := 0, bcch_freq := 1, bsic := 13 }, /* ARFCN 200, band 850, LAC 97 */
12275 { rxlev := 40, bcch_freq := 2, bsic := 14 }, /* ARFCN 1000, band 900, LAC 99 */
12276 { rxlev := 0, bcch_freq := 3, bsic := 11 } /* ARFCN 0, band 900, LAC 96 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012277 };
12278 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
12279 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
12280 l3_mr, 0));
12281
12282 /* Expect a handover to the third entry. If the BSC parsed the report
Oliver Smitha6773042022-10-24 12:56:30 +020012283 * correctly, the third entry has LAC 99. */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012284 var template BSSMAP_FIELD_CellIdentificationList cid_list := {
Oliver Smitha6773042022-10-24 12:56:30 +020012285 cIl_LAC := { ts_BSSMAP_CI_LAC(99) }
Oliver Smithc9a5f532022-10-21 11:32:23 +020012286 };
12287 alt {
12288 [] BSSAP.receive(tr_BSSMAP_HandoverRequired(cid_list := cid_list)) {
12289 setverdict(pass);
12290 }
12291 [] BSSAP.receive(tr_BSSMAP_HandoverRequired()) {
12292 setverdict(fail, "Handover has unexpected LAC in Cell Identification List. The BSC probably"
12293 & " didn't parse the multi-band measurement report correctly.");
12294 }
12295 }
12296
12297 f_ho_out_of_this_bsc(skip_meas_rep := true);
12298}
12299testcase TC_ho_meas_rep_multi_band() runs on test_CT {
12300 /* Verify that the BSC parses the measurement report correctly when
12301 * neighbors in multiple bands are configured (OS#5717). See
12302 * gsm_arfcn2band_rc() in libosmocore src/gsm/gsm_utils.c for the
12303 * ARFCN -> band mapping. The MS is connected to band 1800. */
12304 var MSC_ConnHdlr vc_conn;
12305
12306 f_init_vty();
12307 f_bts_0_cfg(BSCVTY,
12308 {"neighbor-list mode automatic",
12309 "handover 1",
12310 "handover algorithm 2",
12311 "handover2 window rxlev averaging 1",
12312 "no neighbors",
12313 "neighbor lac 99 arfcn 1000 bsic any", /* band 900 */
12314 "neighbor lac 98 arfcn 800 bsic any", /* band 1800 */
12315 "neighbor lac 97 arfcn 200 bsic any", /* band 850 */
Oliver Smitha6773042022-10-24 12:56:30 +020012316 "neighbor lac 96 arfcn 0 bsic any"}); /* band 900 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012317 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
12318
12319 f_init(1, true);
12320 f_sleep(1.0);
12321
12322 f_ctrs_bsc_and_bts_handover_init();
12323
12324 vc_conn := f_start_handler(refers(f_tc_ho_meas_rep_multi_band));
12325 vc_conn.done;
12326
12327 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
12328 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
12329 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
12330 f_ctrs_bsc_and_bts_add(0, "handover:completed");
12331 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
12332 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
12333 f_ctrs_bsc_and_bts_verify();
12334 f_shutdown_helper(ho := true);
12335}
12336
Harald Welte28d943e2017-11-25 15:00:50 +010012337control {
Harald Welte898113b2018-01-31 18:32:21 +010012338 /* CTRL interface testing */
Harald Welte4003d112017-12-09 22:35:39 +010012339 execute( TC_ctrl_msc_connection_status() );
Stefan Sperlingb041b3d2018-01-03 17:14:55 +010012340 execute( TC_ctrl_msc0_connection_status() );
Neels Hofmeyrf65ce872021-09-23 18:40:10 +020012341 /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
12342 * these in the AoIP test suite. */
12343 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12344 execute( TC_stat_num_msc_connected_1() );
12345 execute( TC_stat_num_msc_connected_2() );
12346 execute( TC_stat_num_msc_connected_3() );
12347 }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020012348 execute( TC_stat_num_bts_connected_1() );
12349 execute( TC_stat_num_bts_connected_2() );
12350 execute( TC_stat_num_bts_connected_3() );
Harald Welte96c94412017-12-09 03:12:45 +010012351 execute( TC_ctrl() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012352 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +020012353 execute( TC_ctrl_location() );
12354 }
Harald Welte898113b2018-01-31 18:32:21 +010012355
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012356 execute( TC_si_default() );
Neels Hofmeyr66aeba42020-07-06 02:21:21 +020012357 execute( TC_si2quater_2_earfcns() );
12358 execute( TC_si2quater_3_earfcns() );
12359 execute( TC_si2quater_4_earfcns() );
12360 execute( TC_si2quater_5_earfcns() );
12361 execute( TC_si2quater_6_earfcns() );
Neels Hofmeyrad132f22020-07-08 02:20:16 +020012362 execute( TC_si2quater_12_earfcns() );
12363 execute( TC_si2quater_23_earfcns() );
12364 execute( TC_si2quater_32_earfcns() );
12365 execute( TC_si2quater_33_earfcns() );
12366 execute( TC_si2quater_42_earfcns() );
12367 execute( TC_si2quater_48_earfcns() );
12368 execute( TC_si2quater_49_earfcns() );
Pau Espin Pedrol85a84432020-07-20 18:45:03 +020012369 execute( TC_si_acc_rotate() );
Alexander Couzens4ad3a352020-09-10 22:29:12 +020012370 execute( TC_si_acc_ramp_rotate() );
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012371
Harald Welte898113b2018-01-31 18:32:21 +010012372 /* RSL DCHAN Channel ACtivation / Deactivation */
Harald Welteae026692017-12-09 01:03:01 +010012373 execute( TC_chan_act_noreply() );
Harald Welte4003d112017-12-09 22:35:39 +010012374 execute( TC_chan_act_counter() );
Harald Welteae026692017-12-09 01:03:01 +010012375 execute( TC_chan_act_ack_noest() );
Philipp Maier9c60a622020-07-09 15:08:46 +020012376 execute( TC_chan_act_ack_noest_emerg() );
Philipp Maier606f07d2020-08-12 17:21:58 +020012377 execute( TC_chan_rqd_emerg_deny() );
Harald Welteae026692017-12-09 01:03:01 +010012378 execute( TC_chan_act_ack_est_ind_noreply() );
12379 execute( TC_chan_act_ack_est_ind_refused() );
Harald Welte618ef642017-12-14 14:58:20 +010012380 execute( TC_chan_act_nack() );
Harald Welte799c97b2017-12-14 17:50:30 +010012381 execute( TC_chan_exhaustion() );
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +070012382 execute( TC_chan_deact_silence() );
Harald Welte4003d112017-12-09 22:35:39 +010012383 execute( TC_chan_rel_rll_rel_ind() );
12384 execute( TC_chan_rel_conn_fail() );
12385 execute( TC_chan_rel_hard_clear() );
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +020012386 execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
12387 execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
Harald Welte99787102019-02-04 10:41:36 +010012388 execute( TC_chan_rel_hard_clear_csfb() );
Harald Welted8c36cd2017-12-09 23:05:31 +010012389 execute( TC_chan_rel_hard_rlsd() );
Harald Welte550daf92018-06-11 19:22:13 +020012390 execute( TC_chan_rel_hard_rlsd_ms_dead() );
Harald Welte85804d42017-12-10 14:11:58 +010012391 execute( TC_chan_rel_a_reset() );
Pau Espin Pedrolc675b612020-01-09 19:55:40 +010012392 execute( TC_chan_rel_sccp_tiar_timeout() );
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +020012393 execute( TC_chan_rel_rr_cause() );
Harald Welte6f521d82017-12-11 19:52:02 +010012394
Harald Weltecfe2c962017-12-15 12:09:32 +010012395 execute( TC_outbound_connect() );
Harald Welte898113b2018-01-31 18:32:21 +010012396
12397 /* Assignment related */
Harald Welte16a4adf2017-12-14 18:54:01 +010012398 execute( TC_assignment_cic_only() );
Harald Welte235ebf12017-12-15 14:18:16 +010012399 execute( TC_assignment_csd() );
12400 execute( TC_assignment_ctm() );
12401 execute( TC_assignment_sign() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012402 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12403 execute( TC_assignment_aoip_tla_v6() );
12404 }
Harald Welte235ebf12017-12-15 14:18:16 +010012405 execute( TC_assignment_fr_a5_0() );
12406 execute( TC_assignment_fr_a5_1() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012407 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte8f67d1d2018-05-25 20:38:42 +020012408 execute( TC_assignment_fr_a5_1_codec_missing() );
12409 }
Harald Welte235ebf12017-12-15 14:18:16 +010012410 execute( TC_assignment_fr_a5_3() );
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +020012411 execute( TC_assignment_fr_a5_4() );
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +020012412 execute( TC_assignment_fr_a5_4_fail() );
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +020012413 execute( TC_assignment_fr_a5_not_sup() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012414 execute( TC_ciph_mode_a5_0() );
12415 execute( TC_ciph_mode_a5_1() );
Oliver Smith50b98122021-07-09 15:00:28 +020012416 execute( TC_ciph_mode_a5_2_0() );
Oliver Smith1dff88d2021-07-09 08:45:51 +020012417 execute( TC_ciph_mode_a5_2_1() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012418 execute( TC_ciph_mode_a5_3() );
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +020012419 execute( TC_ciph_mode_a5_4() );
Harald Welte16a4adf2017-12-14 18:54:01 +010012420
Harald Welte60aa5762018-03-21 19:33:13 +010012421 execute( TC_assignment_codec_fr() );
Neels Hofmeyr559d5d02021-04-16 16:50:49 +020012422 execute( TC_assignment_codec_fr_by_mode_modify() );
Harald Welte60aa5762018-03-21 19:33:13 +010012423 execute( TC_assignment_codec_hr() );
12424 execute( TC_assignment_codec_efr() );
12425 execute( TC_assignment_codec_amr_f() );
12426 execute( TC_assignment_codec_amr_h() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012427
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012428 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier8a581d22019-03-26 18:32:48 +010012429 execute( TC_assignment_codec_amr_f_S1() );
12430 execute( TC_assignment_codec_amr_h_S1() );
12431 execute( TC_assignment_codec_amr_f_S124() );
12432 execute( TC_assignment_codec_amr_h_S124() );
12433 execute( TC_assignment_codec_amr_f_S0() );
12434 execute( TC_assignment_codec_amr_f_S02() );
12435 execute( TC_assignment_codec_amr_f_S024() );
12436 execute( TC_assignment_codec_amr_f_S0247() );
12437 execute( TC_assignment_codec_amr_h_S0() );
12438 execute( TC_assignment_codec_amr_h_S02() );
12439 execute( TC_assignment_codec_amr_h_S024() );
12440 execute( TC_assignment_codec_amr_h_S0247() );
12441 execute( TC_assignment_codec_amr_f_S01234567() );
12442 execute( TC_assignment_codec_amr_f_S0234567() );
12443 execute( TC_assignment_codec_amr_f_zero() );
12444 execute( TC_assignment_codec_amr_f_unsupp() );
12445 execute( TC_assignment_codec_amr_h_S7() );
Neels Hofmeyr21863562020-11-26 00:34:33 +000012446 execute( TC_assignment_codec_amr_f_start_mode_auto() );
12447 execute( TC_assignment_codec_amr_h_start_mode_auto() );
Neels Hofmeyr3eb94562020-11-26 02:40:26 +000012448 execute( TC_assignment_codec_amr_f_start_mode_4() );
12449 execute( TC_assignment_codec_amr_h_start_mode_4() );
Neels Hofmeyr454d7922020-11-26 02:24:57 +000012450 execute( TC_assignment_codec_amr_startmode_cruft() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012451 }
Harald Welte60aa5762018-03-21 19:33:13 +010012452
Philipp Maierac09bfc2019-01-08 13:41:39 +010012453 execute( TC_assignment_codec_fr_exhausted_req_hr() );
12454 execute( TC_assignment_codec_fr_exhausted_req_fr() );
12455 execute( TC_assignment_codec_fr_exhausted_req_fr_hr() );
12456 execute( TC_assignment_codec_fr_exhausted_req_hr_fr() );
12457 execute( TC_assignment_codec_hr_exhausted_req_fr() );
12458 execute( TC_assignment_codec_hr_exhausted_req_hr() );
12459 execute( TC_assignment_codec_hr_exhausted_req_hr_fr() );
12460 execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
12461 execute( TC_assignment_codec_req_hr_fr() );
12462 execute( TC_assignment_codec_req_fr_hr() );
Pau Espin Pedrol14475352021-07-22 15:48:16 +020012463 execute( TC_assignment_sdcch_exhausted_req_signalling() );
12464 execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
12465 execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
Philipp Maierac09bfc2019-01-08 13:41:39 +010012466
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +020012467 execute( TC_assignment_codec_hr_osmux_on() );
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +020012468 execute( TC_assignment_osmux() );
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020012469 execute( TC_assignment_osmux_cn() );
12470 execute( TC_assignment_osmux_bts() );
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +020012471
Harald Welte898113b2018-01-31 18:32:21 +010012472 /* RLL Establish Indication on inactive DCHAN / SAPI */
Harald Welte5cd20ed2017-12-13 21:03:20 +010012473 execute( TC_rll_est_ind_inact_lchan() );
12474 execute( TC_rll_est_ind_inval_sapi1() );
12475 execute( TC_rll_est_ind_inval_sapi3() );
12476 execute( TC_rll_est_ind_inval_sacch() );
12477
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +070012478 /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
12479 execute( TC_tch_dlci_link_id_sapi() );
12480
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012481 /* SAPI N Reject triggered by RLL establishment failures */
12482 execute( TC_rll_rel_ind_sapi_n_reject() );
12483 execute( TC_rll_err_ind_sapi_n_reject() );
12484 execute( TC_rll_timeout_sapi_n_reject() );
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +070012485 execute( TC_rll_sapi_n_reject_dlci_cc() );
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012486
Harald Welte898113b2018-01-31 18:32:21 +010012487 /* Paging related tests */
Harald Welte6f521d82017-12-11 19:52:02 +010012488 execute( TC_paging_imsi_nochan() );
12489 execute( TC_paging_tmsi_nochan() );
12490 execute( TC_paging_tmsi_any() );
12491 execute( TC_paging_tmsi_sdcch() );
12492 execute( TC_paging_tmsi_tch_f() );
12493 execute( TC_paging_tmsi_tch_hf() );
12494 execute( TC_paging_imsi_nochan_cgi() );
12495 execute( TC_paging_imsi_nochan_lac_ci() );
12496 execute( TC_paging_imsi_nochan_ci() );
12497 execute( TC_paging_imsi_nochan_lai() );
12498 execute( TC_paging_imsi_nochan_lac() );
12499 execute( TC_paging_imsi_nochan_all() );
Harald Welte751d3eb2018-01-31 15:51:06 +010012500 execute( TC_paging_imsi_nochan_plmn_lac_rnc() );
12501 execute( TC_paging_imsi_nochan_rnc() );
12502 execute( TC_paging_imsi_nochan_lac_rnc() );
12503 execute( TC_paging_imsi_nochan_lacs() );
12504 execute( TC_paging_imsi_nochan_lacs_empty() );
Stefan Sperling049a86e2018-03-20 15:51:00 +010012505 execute( TC_paging_imsi_nochan_cgi_unknown_cid() );
Harald Welte10985002017-12-12 09:29:15 +010012506 execute( TC_paging_imsi_a_reset() );
Harald Weltee65d40e2017-12-13 00:09:06 +010012507 execute( TC_paging_imsi_load() );
Philipp Maier779a7922018-02-16 11:00:37 +010012508 execute( TC_paging_counter() );
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +010012509 execute( TC_paging_resp_unsol() );
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +020012510 execute( TC_paging_500req() );
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +020012511 execute( TC_paging_450req_no_paging_load_ind() );
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +010012512 execute( TC_paging_imsi_nochan_ci_resp_invalid_mi() );
Harald Welte4e9b9cc2017-12-14 18:31:02 +010012513
12514 execute( TC_rsl_drop_counter() );
Stefan Sperling830dc9d2018-02-12 21:08:28 +010012515 execute( TC_rsl_unknown_unit_id() );
12516
12517 execute( TC_oml_unknown_unit_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012518
12519 execute( TC_classmark() );
Harald Welteeddf0e92020-06-21 19:42:15 +020012520 execute( TC_common_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012521 execute( TC_unsol_ass_fail() );
Harald Welteea99a002018-01-31 20:46:43 +010012522 execute( TC_unsol_ass_compl() );
Harald Weltefbf9b5e2018-01-31 20:41:23 +010012523 execute( TC_unsol_ho_fail() );
Harald Weltee3bd6582018-01-31 22:51:25 +010012524 execute( TC_err_82_short_msg() );
Harald Weltee9e02e42018-01-31 23:36:25 +010012525 execute( TC_err_84_unknown_msg() );
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012526
Harald Welte261af4b2018-02-12 21:20:39 +010012527 execute( TC_ho_int() );
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +020012528 execute( TC_ho_int_a5_0() );
12529 execute( TC_ho_int_a5_1() );
12530 execute( TC_ho_int_a5_3() );
12531 execute( TC_ho_int_a5_4() );
Neels Hofmeyr5f144212020-11-03 15:41:58 +000012532 execute( TC_ho_int_radio_link_failure() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012533
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012534 /* TC_ho_out_of_this_bsc is run last, see comment below */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +020012535 execute( TC_ho_out_fail_no_msc_response() );
12536 execute( TC_ho_out_fail_rr_ho_failure() );
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +020012537 execute( TC_ho_out_fail_no_result_after_ho_cmd() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012538
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012539 execute( TC_ho_into_this_bsc() );
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +020012540 execute( TC_ho_into_this_bsc_a5_0() );
12541 execute( TC_ho_into_this_bsc_a5_1() );
12542 execute( TC_ho_into_this_bsc_a5_3() );
12543 execute( TC_ho_into_this_bsc_a5_4() );
Neels Hofmeyr93182e02022-02-17 21:59:07 +010012544 execute( TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() );
12545 execute( TC_ho_into_this_bsc_a5_1_3() );
Neels Hofmeyr907b23b2022-02-17 21:58:47 +010012546 execute( TC_ho_into_this_bsc_a5_mismatch() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012547 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12548 execute( TC_ho_into_this_bsc_tla_v6() );
12549 }
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +020012550 execute( TC_srvcc_eutran_to_geran() );
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +030012551 execute( TC_srvcc_eutran_to_geran_a5_3() );
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +010012552 execute( TC_srvcc_eutran_to_geran_src_sai() );
Pau Espin Pedrol35801c32021-04-19 13:03:20 +020012553 execute( TC_srvcc_eutran_to_geran_ho_out() );
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +020012554 execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
12555 execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012556 execute( TC_ho_in_fail_msc_clears() );
12557 execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
12558 execute( TC_ho_in_fail_no_detect() );
12559 execute( TC_ho_in_fail_no_detect2() );
Oliver Smith7a8594a2023-02-13 14:30:49 +010012560 execute( TC_ho_in_fail_mgw_mdcx_timeout() );
Oliver Smith4eed06f2023-02-15 15:43:19 +010012561 execute( TC_ho_in_fail_ipa_crcx_timeout() );
Neels Hofmeyra23f3b12022-03-02 19:57:12 +010012562 execute( TC_ho_into_this_bsc_sccp_cr_without_bssap() );
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012563
Neels Hofmeyr91401012019-07-11 00:42:35 +020012564 execute( TC_ho_neighbor_config_1() );
12565 execute( TC_ho_neighbor_config_2() );
12566 execute( TC_ho_neighbor_config_3() );
12567 execute( TC_ho_neighbor_config_4() );
12568 execute( TC_ho_neighbor_config_5() );
12569 execute( TC_ho_neighbor_config_6() );
12570 execute( TC_ho_neighbor_config_7() );
12571
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012572 execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() );
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010012573 execute( TC_bssmap_clear_does_not_cause_bssmap_reset() );
Neels Hofmeyrfd445c32018-03-09 15:39:31 +010012574 execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() );
Harald Welte94e0c342018-04-07 11:33:23 +020012575
12576 execute( TC_dyn_pdch_ipa_act_deact() );
12577 execute( TC_dyn_pdch_ipa_act_nack() );
12578 execute( TC_dyn_pdch_osmo_act_deact() );
12579 execute( TC_dyn_pdch_osmo_act_nack() );
Pau Espin Pedrol37a4c152021-11-16 19:02:23 +010012580 execute( TC_dyn_ts_sdcch8_act_deact() );
12581 execute( TC_dyn_ts_sdcch8_all_subslots_used() );
12582 execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
12583 execute( TC_dyn_ts_sdcch8_act_nack() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012584
Stefan Sperling0796a822018-10-05 13:01:39 +020012585 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +020012586 execute( TC_chopped_ipa_payload() );
Stefan Sperling0796a822018-10-05 13:01:39 +020012587
Pau Espin Pedrol8f773632019-11-05 11:46:53 +010012588 /* Power control related */
12589 execute( TC_assignment_verify_ms_power_params_ie() );
Vadim Yanitskiy4b233042021-06-30 00:58:43 +020012590 execute( TC_c0_power_red_mode() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012591
12592 /* MSC pooling */
12593 /* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
12594 * RESET->RESET-ACK is unconditionally negotiated for all configured MSCs, they always all appear as connected
12595 * to osmo-bsc. The MSC pooling tests however require disconnecting selected MSCs, and hence don't work out as
12596 * intended on SCCPlite. So for now, run these only for SCCP/M3UA. */
12597 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12598 execute( TC_mscpool_L3Compl_on_1_msc() );
12599 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
12600 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
12601 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
12602 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
12603 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
12604 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
12605 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
12606 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
12607 execute( TC_mscpool_paging_and_response_imsi() );
12608 execute( TC_mscpool_paging_and_response_tmsi() );
12609 execute( TC_mscpool_no_allow_attach_round_robin() );
12610 execute( TC_mscpool_no_allow_attach_valid_nri() );
Neels Hofmeyr2bdc6b62023-04-05 02:45:19 +020012611
12612 execute( TC_mscpool_sccp_n_pcstate_detaches_msc() );
Neels Hofmeyr38632aa2023-04-05 03:50:51 +020012613 execute( TC_mscpool_sccp_n_pcstate_attaches_msc() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012614 }
12615
Harald Welte99f3ca02018-06-14 13:40:29 +020012616 execute( TC_early_conn_fail() );
12617 execute( TC_late_conn_fail() );
Oliver Smithaf03bef2021-08-24 15:34:51 +020012618 execute( TC_stats_conn_fail() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012619
Philipp Maier783681c2020-07-16 16:47:06 +020012620 /* Emergency call handling (deny / allow) */
12621 execute( TC_assignment_emerg_setup_allow() );
Pau Espin Pedrolb27653c2023-01-03 14:07:21 +010012622 execute( TC_assignment_emerg_setup_allow_imei() );
Philipp Maier783681c2020-07-16 16:47:06 +020012623 execute( TC_assignment_emerg_setup_deny_msc() );
12624 execute( TC_assignment_emerg_setup_deny_bts() );
Philipp Maier82812002020-08-13 18:48:27 +020012625 execute( TC_emerg_premption() );
12626
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +070012627 /* Frequency hopping parameters handling */
12628 execute( TC_fh_params_chan_activ() );
12629 execute( TC_fh_params_imm_ass() );
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070012630 execute( TC_fh_params_assignment_cmd() );
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070012631 execute( TC_fh_params_handover_cmd() );
Vadim Yanitskiyca974032020-09-01 07:20:39 +070012632 execute( TC_fh_params_si4_cbch() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012633
12634 if (mp_enable_lcs_tests) {
12635 execute( TC_lcs_loc_req_for_active_ms() );
12636 execute( TC_lcs_loc_req_for_active_ms_ta_req() );
12637 execute( TC_lcs_loc_req_for_idle_ms() );
12638 execute( TC_lcs_loc_req_no_subscriber() );
12639 execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
12640 execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
12641 execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
12642 execute( TC_cm_service_during_lcs_loc_req() );
12643 execute( TC_ho_during_lcs_loc_req() );
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020012644 execute( TC_emerg_call_and_lcs_loc_req() );
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020012645 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() );
12646 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012647 }
Neels Hofmeyrbf037052020-10-28 22:52:02 +000012648
12649 execute( TC_no_msc() );
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000012650
12651 execute( TC_refuse_chan_act_to_vamos() );
12652 execute( TC_refuse_mode_modif_to_vamos() );
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000012653
12654 execute( TC_reassignment_fr() );
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020012655
12656 execute( TC_cm_reestablishment() );
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020012657
12658 execute( TC_imm_ass_post_chan_ack() );
12659 execute( TC_imm_ass_pre_chan_ack() );
Neels Hofmeyr23158742021-09-07 19:08:07 +020012660 execute( TC_imm_ass_pre_ts_ack() );
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020012661 execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020012662 execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020012663
12664 execute( TC_ctrl_trx_rf_locked() );
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012665
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012666 execute( TC_ratectr_all_available_allocated() );
12667 execute( TC_ratectr_all_available_allocated_dyn() );
12668
Neels Hofmeyrb7581872021-11-07 14:02:49 +010012669 execute( TC_cm_serv_rej() );
12670
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012671 execute( TC_lost_sdcch_during_assignment() );
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012672
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012673 /* Channel allocator */
12674 execute( TC_chan_alloc_algo_ascending() );
12675 execute( TC_chan_alloc_algo_descending() );
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012676 execute( TC_chan_alloc_algo_ass_dynamic() );
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012677
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012678 /* MGW pool */
Pau Espin Pedrol4e431832023-02-08 12:43:47 +010012679 execute( TC_mgwpool_all_used() );
12680 execute( TC_mgwpool_blocked_not_used() );
12681 execute( TC_mgwpool_pin_bts() );
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012682
Oliver Smithc9a5f532022-10-21 11:32:23 +020012683 execute( TC_ho_meas_rep_multi_band() );
12684
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012685 /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
12686 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
12687 execute( TC_ho_out_of_this_bsc() );
Harald Welte28d943e2017-11-25 15:00:50 +010012688}
12689
12690}