blob: ea73f4a10cd368636066109b48dcdac632f55837 [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;
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +020025
Neels Hofmeyr4f118412020-06-04 15:25:10 +020026import from Misc_Helpers all;
Harald Welte4003d112017-12-09 22:35:39 +010027import from General_Types all;
Harald Welte28d943e2017-11-25 15:00:50 +010028import from Osmocom_Types all;
Harald Welteae026692017-12-09 01:03:01 +010029import from GSM_Types all;
Harald Welte28d943e2017-11-25 15:00:50 +010030import from IPL4asp_Types all;
31
Harald Welte6f521d82017-12-11 19:52:02 +010032import from BSSAP_Types all;
Harald Welte6811d102019-04-14 22:23:14 +020033import from RAN_Adapter all;
Harald Welte47cd0e32020-08-21 12:39:11 +020034import from BSSAP_LE_Adapter all;
35import from BSSAP_LE_CodecPort all;
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020036import from BSSAP_LE_Types all;
37import from BSSLAP_Types all;
Harald Welteae026692017-12-09 01:03:01 +010038import from BSSAP_CodecPort all;
39import from BSSMAP_Templates all;
Harald Welte28d943e2017-11-25 15:00:50 +010040import from IPA_Emulation all;
Stefan Sperling830dc9d2018-02-12 21:08:28 +010041import from IPA_CodecPort all;
Harald Welteae026692017-12-09 01:03:01 +010042import from IPA_Types all;
Stefan Sperling0796a822018-10-05 13:01:39 +020043import from IPA_Testing all;
Harald Welteae026692017-12-09 01:03:01 +010044import from RSL_Types all;
Harald Welte624f9632017-12-16 19:26:04 +010045import from RSL_Emulation all;
Daniel Willmann191e0d92018-01-17 12:44:35 +010046import from MGCP_Emulation all;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010047import from MGCP_Templates all;
48import from MGCP_Types all;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +020049import from MGCP_CodecPort all;
Harald Welte28d943e2017-11-25 15:00:50 +010050
Harald Welte96c94412017-12-09 03:12:45 +010051import from Osmocom_CTRL_Functions all;
Harald Weltea5d2ab22017-12-09 14:21:42 +010052import from Osmocom_CTRL_Types all;
Harald Welteffe55fc2018-01-17 22:39:54 +010053import from Osmocom_CTRL_Adapter all;
Harald Welte96c94412017-12-09 03:12:45 +010054
Daniel Willmannebdecc02020-08-12 15:30:17 +020055import from StatsD_Types all;
56import from StatsD_CodecPort all;
57import from StatsD_CodecPort_CtrlFunct all;
58import from StatsD_Checker all;
59
Harald Weltebc03c762018-02-12 18:09:38 +010060import from Osmocom_VTY_Functions all;
61import from TELNETasp_PortType all;
62
Harald Welte6f521d82017-12-11 19:52:02 +010063import from MobileL3_CommonIE_Types all;
Harald Weltee3bd6582018-01-31 22:51:25 +010064import from MobileL3_Types all;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010065import from MobileL3_RRM_Types all;
Harald Welte6f521d82017-12-11 19:52:02 +010066import from L3_Templates all;
67import from GSM_RR_Types all;
68
Stefan Sperlingc307e682018-06-14 15:15:46 +020069import from SCCP_Templates all;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010070import from BSSMAP_Templates all;
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020071import from BSSMAP_LE_Templates all;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010072
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010073import from SCCPasp_Types all;
74
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020075import from GSM_SystemInformation all;
76import from GSM_RestOctets all;
Neels Hofmeyrad132f22020-07-08 02:20:16 +020077import from TCCConversion_Functions all;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020078
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060079const integer NUM_TRX := 4;
Harald Welte5d1a2202017-12-13 19:51:29 +010080const integer NUM_BTS := 3;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020081const 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 +060082const 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 +020083const integer NUM_MSC := 3;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020084const integer NUM_MGW := 2;
Harald Welteae026692017-12-09 01:03:01 +010085const float T3101_MAX := 12.0;
Harald Welte28d943e2017-11-25 15:00:50 +010086
Harald Welte799c97b2017-12-14 17:50:30 +010087/* make sure to sync this with the osmo-bts.cfg you're using */
Philipp Maiercb6cc482018-03-26 13:08:00 +020088const integer NUM_TCHH_PER_BTS := 2;
89const integer NUM_TCHF_PER_BTS := 4;
Neels Hofmeyr74083c22020-07-29 00:43:01 +020090const integer NUM_SDCCH_PER_BTS := 3;
Harald Welte799c97b2017-12-14 17:50:30 +010091
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060092friend type record BtsTrxIdx {
93 uint8_t bts,
94 uint8_t trx
95}
96
97private type record BtsParams {
98 integer trx_num,
99 integer tsc
100}
101
Neels Hofmeyrbf720202021-10-02 12:58:24 +0200102/* Default Training Sequence Code expected for bts[i]:
103 * BTS 0 has BSIC 10 (and no explicit timeslot training_sequence_code config), so expecting TSC = (BSIC & 7) = 2.
104 * BTS 1 has BSIC 11, TSC = (BSIC & 7) = 3.
105 * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
106 * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
107 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600108private const BtsParams c_BtsParams[NUM_BTS_CFG] := {
109 /* BTS0 */ { trx_num := 1, tsc := 2 },
110 /* BTS1 */ { trx_num := 1, tsc := 3 },
Vadim Yanitskiy7a3d2932022-05-29 20:37:46 +0600111 /* BTS2 */ { trx_num := 4, tsc := 4 },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600112 /* BTS3 */ { trx_num := 1, tsc := 4 }
Neels Hofmeyrbf720202021-10-02 12:58:24 +0200113}
Harald Welte4003d112017-12-09 22:35:39 +0100114
Vadim Yanitskiy59494702022-09-14 15:29:04 +0700115private const RSL_IE_Body c_mr_conf_5_90 :=
Pau Espin Pedrolf7634dc2022-09-02 17:56:00 +0200116 valueof(RSL_IE_Body:{multirate_cfg := ts_RSL_MultirateCfg(true, 0, '00000100'B /* 5,90k */)});
117
Harald Welte21b46bd2017-12-17 19:46:32 +0100118/* per-BTS state which we keep */
Harald Welte96c94412017-12-09 03:12:45 +0100119type record BTS_State {
Harald Welte21b46bd2017-12-17 19:46:32 +0100120 /* component reference to the IPA_Client component used for RSL */
Harald Weltea5d2ab22017-12-09 14:21:42 +0100121 IPA_Client rsl
Harald Welte96c94412017-12-09 03:12:45 +0100122}
123
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200124/* Default list of counters for an 'msc' entity. */
125const CounterNameVals counternames_msc_mscpool := {
126 { "mscpool:subscr:new", 0 },
127 { "mscpool:subscr:known", 0 },
128 { "mscpool:subscr:reattach", 0 },
129 { "mscpool:subscr:attach_lost", 0 },
130 { "mscpool:subscr:paged", 0 }
131};
132
Neels Hofmeyrbf037052020-10-28 22:52:02 +0000133/* List of global mscpool counters, not related to a specific 'msc' entity. */
134const CounterNameVals counternames_bsc_mscpool := {
135 { "mscpool:subscr:no_msc", 0 }
136};
137
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000138/* Default list of counters for 'bsc' and 'bts' entities. */
139const CounterNameVals counternames_bsc_bts_handover := {
140 { "assignment:attempted", 0 },
141 { "assignment:completed", 0 },
142 { "assignment:stopped", 0 },
143 { "assignment:no_channel", 0 },
144 { "assignment:timeout", 0 },
145 { "assignment:failed", 0 },
146 { "assignment:error", 0 },
147
148 { "handover:attempted", 0 },
149 { "handover:completed", 0 },
150 { "handover:stopped", 0 },
151 { "handover:no_channel", 0 },
152 { "handover:timeout", 0 },
153 { "handover:failed", 0 },
154 { "handover:error", 0 },
155
156 { "intra_cell_ho:attempted", 0 },
157 { "intra_cell_ho:completed", 0 },
158 { "intra_cell_ho:stopped", 0 },
159 { "intra_cell_ho:no_channel", 0 },
160 { "intra_cell_ho:timeout", 0 },
161 { "intra_cell_ho:failed", 0 },
162 { "intra_cell_ho:error", 0 },
163
164 { "intra_bsc_ho:attempted", 0 },
165 { "intra_bsc_ho:completed", 0 },
166 { "intra_bsc_ho:stopped", 0 },
167 { "intra_bsc_ho:no_channel", 0 },
168 { "intra_bsc_ho:timeout", 0 },
169 { "intra_bsc_ho:failed", 0 },
170 { "intra_bsc_ho:error", 0 },
171
172 { "interbsc_ho_out:attempted", 0 },
173 { "interbsc_ho_out:completed", 0 },
174 { "interbsc_ho_out:stopped", 0 },
175 { "interbsc_ho_out:timeout", 0 },
176 { "interbsc_ho_out:failed", 0 },
177 { "interbsc_ho_out:error", 0 },
178
179 { "interbsc_ho_in:attempted", 0 },
180 { "interbsc_ho_in:completed", 0 },
181 { "interbsc_ho_in:stopped", 0 },
182 { "interbsc_ho_in:no_channel", 0 },
183 { "interbsc_ho_in:timeout", 0 },
184 { "interbsc_ho_in:failed", 0 },
185 { "interbsc_ho_in:error", 0 }
186};
187
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100188const CounterNameVals counternames_bts_handover := {
189 { "incoming_intra_bsc_ho:attempted", 0 },
190 { "incoming_intra_bsc_ho:completed", 0 },
191 { "incoming_intra_bsc_ho:stopped", 0 },
192 { "incoming_intra_bsc_ho:no_channel", 0 },
193 { "incoming_intra_bsc_ho:timeout", 0 },
194 { "incoming_intra_bsc_ho:failed", 0 },
195 { "incoming_intra_bsc_ho:error", 0 }
196};
197
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200198/* Set of all System Information received during one RSL port's startup.
199 * Note that some System Information may be sent on RSL, but lacking actual SI data, to indicate that the BTS should not
200 * broadcast that SI type. That will be reflected as 'omit' here.
201 */
202type record SystemInformationConfig {
203 SystemInformationType1 si1 optional,
204 SystemInformationType2 si2 optional,
205 SystemInformationType2bis si2bis optional,
206 SystemInformationType2ter si2ter optional,
Neels Hofmeyrad132f22020-07-08 02:20:16 +0200207 SI2quaterRestOctetsList si2quater optional,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200208 SystemInformationType3 si3 optional,
209 SystemInformationType4 si4 optional,
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100210 SystemInformationType13 si13 optional,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200211 SystemInformationType5 si5 optional,
212 SystemInformationType5bis si5bis optional,
213 SystemInformationType5ter si5ter optional,
214 SystemInformationType6 si6 optional
215};
216
217const SystemInformationConfig SystemInformationConfig_omit := {
218 si1 := omit,
219 si2 := omit,
220 si2bis := omit,
221 si2ter := omit,
222 si2quater := omit,
223 si3 := omit,
224 si4 := omit,
225 si13 := omit,
226 si5 := omit,
227 si5bis := omit,
228 si5ter := omit,
229 si6 := omit
230};
231
232/* tr_EUTRAN_CellDesc with defaults used in BSC_Tests.ttcn */
233template EUTRAN_CellDesc tr_EUTRAN_CellDesc_default(template (present) uint16_t e_arfcn := ?,
234 template uint3_t meas_bw := 3)
235:= tr_EUTRAN_CellDesc(e_arfcn := e_arfcn,
236 meas_bw_presence := '1'B,
237 meas_bw := meas_bw);
238
239/* tr_EUTRAN_NeighbourCells with defaults used in BSC_Tests.ttcn */
Harald Welte65e419a2020-08-21 12:38:33 +0200240template EUTRAN_NeighbourCells tr_EUTRAN_NeighbourCells_default(template (present) EUTRAN_CellDescs cell_desc_list := { tr_EUTRAN_CellDesc_default },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200241 template uint3_t prio := 3,
242 template (present) uint5_t thresh_high := 20,
243 template uint5_t thresh_low := 10,
244 template uint5_t qrxlevmin := 22)
245:= tr_EUTRAN_NeighbourCells(
246 cell_desc_list := cell_desc_list,
247 prio_presence := '1'B,
248 prio := prio,
249 thresh_high := thresh_high,
250 thresh_low_presence := '1'B,
251 thresh_low := thresh_low,
252 qrxlevmin_presence := '1'B,
253 qrxlevmin := qrxlevmin);
254
255template SystemInformationConfig SystemInformationConfig_default := {
256 si1 := {
257 cell_chan_desc := '8FB38000000000000000000000000000'O,
258 rach_control := {
259 max_retrans := RACH_MAX_RETRANS_7,
260 tx_integer := '1001'B,
261 cell_barr_access := false,
262 re_not_allowed := true,
263 acc := '0000010000000000'B
264 },
265 rest_octets := ?
266 },
267 si2 := {
268 bcch_freq_list := '00000000000000000000000000000000'O,
269 ncc_permitted := '11111111'B,
270 rach_control := {
271 max_retrans := RACH_MAX_RETRANS_7,
272 tx_integer := '1001'B,
273 cell_barr_access := false,
274 re_not_allowed := true,
275 acc := '0000010000000000'B
276 }
277 },
278 si2bis := omit,
279 si2ter := {
280 extd_bcch_freq_list := '8E320000000000000000000000000800'O,
281 rest_octets := ?
282 },
283 si2quater := {
284 tr_SI2quaterRestOctets_EUTRAN( repeated_neigh_cells := { tr_EUTRAN_NeighbourCells_default } )
285 },
286 si3 := {
287 cell_id := 0,
288 lai := {
289 mcc_mnc := '001F01'H,
290 lac := 1
291 },
292 ctrl_chan_desc := {
293 msc_r99 := true,
294 att := true,
295 bs_ag_blks_res := 1,
296 ccch_conf := CCHAN_DESC_1CCCH_COMBINED,
297 si22ind := false,
298 cbq3 := CBQ3_IU_MODE_NOT_SUPPORTED,
299 spare := '00'B,
300 bs_pa_mfrms := 3,
301 t3212 := 30
302 },
303 cell_options := {
304 dn_ind := false,
305 pwrc := false,
306 dtx := MS_SHALL_USE_UL_DTX,
307 radio_link_tout_div4 := 7
308 },
309 cell_sel_par := {
310 cell_resel_hyst_2dB := 2,
311 ms_txpwr_max_cch := 7,
312 acs := '0'B,
313 neci := true,
314 rxlev_access_min := 0
315 },
316 rach_control := {
317 max_retrans := RACH_MAX_RETRANS_7,
318 tx_integer := '1001'B,
319 cell_barr_access := false,
320 re_not_allowed := true,
321 acc := '0000010000000000'B
322 },
323 rest_octets := {
324 sel_params := {
325 presence := '0'B,
326 params := omit
327 },
328 pwr_offset := {
329 presence := '0'B,
330 offset := omit
331 },
332 si_2ter_ind := '1'B,
333 early_cm_ind := '0'B,
334 sched_where := {
335 presence := '0'B,
336 where := omit
337 },
338 gprs_ind := {
339 presence := '1'B,
340 ind := {
341 ra_colour := 0,
342 si13_pos := '0'B
343 }
344 },
345 umts_early_cm_ind := '1'B,
346 si2_quater_ind := {
347 presence := '1'B,
348 ind := '0'B
349 },
350 iu_mode_ind := omit,
351 si21_ind := {
352 presence := '0'B,
353 pos := omit
354 }
355 }
356 },
357 si4 := {
358 lai := {
359 mcc_mnc := '001F01'H,
360 lac := 1
361 },
362 cell_sel_par := {
363 cell_resel_hyst_2dB := 2,
364 ms_txpwr_max_cch := 7,
365 acs := '0'B,
366 neci := true,
367 rxlev_access_min := 0
368 },
369 rach_control := {
370 max_retrans := RACH_MAX_RETRANS_7,
371 tx_integer := '1001'B,
372 cell_barr_access := false,
373 re_not_allowed := true,
374 acc := '0000010000000000'B
375 },
Neels Hofmeyr74083c22020-07-29 00:43:01 +0200376 cbch_chan_desc := {
377 iei := '64'O,
378 v := {
379 chan_nr := {
380 u := {
381 sdcch4 := {
382 tag := '001'B,
383 sub_chan := 2
384 }
385 },
386 tn := 0
387 },
388 tsc := 2,
389 h := false,
390 arfcn := 871,
391 maio_hsn := omit
392 }
393 },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200394 cbch_mobile_alloc := omit,
395 rest_octets := {
396 sel_params := {
397 presence := '0'B,
398 params := omit
399 },
400 pwr_offset := {
401 presence := '0'B,
402 offset := omit
403 },
404 gprs_ind := {
405 presence := '1'B,
406 ind := {
407 ra_colour := 0,
408 si13_pos := '0'B
409 }
410 },
411 s_presence := '0'B,
412 s := omit
413 }
414 },
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100415 si13 := {
416 rest_octets := {
417 presence := '1'B,
418 bcch_change_mark := ?,
419 si_change_field := '0000'B,
420 presence2 := '0'B,
421 si13_change_mark := omit,
422 gprs_ma := omit,
423 zero := '0'B, /* PBCCH not present in cell */
424 rac := 0,
425 spgc_ccch_sup := '0'B,
426 priority_access_thr := '110'B,
427 network_control_order := '00'B,
428 gprs_cell_opts := {
429 nmo := '01'B,
430 t3168 := '011'B,
431 t3192 := '010'B,
432 drx_timer_max := '011'B,
433 access_burst_type := '0'B,
434 control_ack_type := '1'B,
435 bs_cv_max := 15,
436 pan_presence := '1'B,
437 pan_dec := 1,
438 pan_inc := 1,
439 pan_max := '111'B,
440 ext_info_presence := ?,
441 ext_info_length := *,
442 ext_info := *
443 },
444 gprs_pwr_ctrl_params := {
445 alpha := 0,
446 t_avg_w := '10000'B,
447 t_avg_t := '10000'B,
448 pc_meas_chan := '0'B,
449 n_avg_i := '1000'B
450 }
451 }
452 },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200453 si5 := {
454 bcch_freq_list := '10000000000000000000000000000000'O
455 },
456 si5bis := omit,
457 si5ter := {
458 extd_bcch_freq_list := '9E050020000000000000000000000000'O
459 },
460 si6 := {
461 cell_id := 0,
462 lai := {
463 mcc_mnc := '001F01'H,
464 lac := 1
465 },
466 cell_options := {
467 dtx_ext := '1'B,
468 pwrc := false,
469 dtx := '01'B,
470 radio_link_timeout := '0111'B
471 },
472 ncc_permitted := '11111111'B,
Vadim Yanitskiy348b07c2022-03-10 17:11:22 +0300473 rest_octets := {
474 pch_nch_info := ?,
475 vbs_vgcs_options := ?,
476 dtm_support := '0'B,
477 rac := omit,
478 max_lapdm := omit,
479 band_ind := '0'B /* C0 ARFCN indicates 1800 band */
480 }
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200481 }
482 };
483
484
485/* List of all the System Information received on all RSL ports */
486type record of SystemInformationConfig SystemInformationConfig_list;
487
488function f_sysinfo_dec_raw(inout SystemInformationConfig si, RSL_Message rsl)
489{
490 var RSL_IE_Body sysinfo_type_ie;
491 var RSL_IE_SysinfoType si_type;
492 var octetstring data;
493
494 if (f_rsl_find_ie(rsl, RSL_IE_SYSINFO_TYPE, sysinfo_type_ie) == false) {
495 setverdict(fail, "Cannot find RSL_IE_SYSINFO_TYPE");
496 mtc.stop;
497 }
498 si_type := sysinfo_type_ie.sysinfo_type;
499
500 if (rsl.msg_type == RSL_MT_BCCH_INFO) {
501 var RSL_IE_Body bcch_ie;
502 if (f_rsl_find_ie(rsl, RSL_IE_FULL_BCCH_INFO, bcch_ie)) {
503 data := bcch_ie.other.payload;
504 }
505 } else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
506 var RSL_IE_Body l3_ie;
507 if (f_rsl_find_ie(rsl, RSL_IE_L3_INFO, l3_ie)) {
508 data := l3_ie.l3_info.payload;
509 }
510 } else {
511 setverdict(fail, "Don't understand this System Information message");
512 mtc.stop;
513 }
514
515 var boolean handled := false;
516
517 if (rsl.msg_type == RSL_MT_BCCH_INFO) {
518 handled := true;
519
520 if (si_type == RSL_SYSTEM_INFO_1) {
521 if (not isbound(data)) {
522 si.si1 := omit;
523 } else {
524 si.si1 := dec_SystemInformation(data).payload.si1;
525 }
526 } else if (si_type == RSL_SYSTEM_INFO_2) {
527 if (not isbound(data)) {
528 si.si2 := omit;
529 } else {
530 si.si2 := dec_SystemInformation(data).payload.si2;
531 }
532 } else if (si_type == RSL_SYSTEM_INFO_2bis) {
533 if (not isbound(data)) {
534 si.si2bis := omit;
535 } else {
536 si.si2bis := dec_SystemInformation(data).payload.si2bis;
537 }
538 } else if (si_type == RSL_SYSTEM_INFO_2ter) {
539 if (not isbound(data)) {
540 si.si2ter := omit;
541 } else {
542 si.si2ter := dec_SystemInformation(data).payload.si2ter;
543 }
544 } else if (si_type == RSL_SYSTEM_INFO_2quater) {
545 if (not isbound(data)) {
546 si.si2quater := {};
547 } else {
548 var SystemInformationType2quater decoded := dec_SystemInformation(data).payload.si2quater;
549 /* this is a *record* of SI2quaterRestOctets! (multiplexed) */
550 si.si2quater[decoded.rest_octets.si2quater_index] := decoded.rest_octets;
551 }
552 } else if (si_type == RSL_SYSTEM_INFO_3) {
553 if (not isbound(data)) {
554 si.si3 := omit;
555 } else {
556 si.si3 := dec_SystemInformation(data).payload.si3;
557 }
558 } else if (si_type == RSL_SYSTEM_INFO_4) {
559 if (not isbound(data)) {
560 si.si4 := omit;
561 } else {
562 si.si4 := dec_SystemInformation(data).payload.si4;
563 }
564 } else if (si_type == RSL_SYSTEM_INFO_13) {
565 if (not isbound(data)) {
566 si.si13 := omit;
567 } else {
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100568 si.si13 := dec_SystemInformation(data).payload.si13;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200569 }
570 } else {
571 handled := false;
572 }
573 } else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
574 handled := true;
575
576 if (si_type == RSL_SYSTEM_INFO_5) {
577 if (not isbound(data)) {
578 si.si5 := omit;
579 } else {
580 si.si5 := dec_SystemInformation(data).payload.si5;
581 }
582 } else if (si_type == RSL_SYSTEM_INFO_5bis) {
583 if (not isbound(data)) {
584 si.si5bis := omit;
585 } else {
586 si.si5bis := dec_SystemInformation(data).payload.si5bis;
587 }
588 } else if (si_type == RSL_SYSTEM_INFO_5ter) {
589 if (not isbound(data)) {
590 si.si5ter := omit;
591 } else {
592 si.si5ter := dec_SystemInformation(data).payload.si5ter;
593 }
594 } else if (si_type == RSL_SYSTEM_INFO_6) {
595 if (not isbound(data)) {
596 si.si6 := omit;
597 } else {
598 si.si6 := dec_SystemInformation(data).payload.si6;
599 }
600 } else {
601 handled := false;
602 }
603 }
604
605 if (not handled) {
606 setverdict(fail, "Unexpected SI type in ", rsl.msg_type, " message: ", si_type);
607 }
608}
609
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +0100610friend function gen_l3_valid_payload(hexstring imsi := ''H) return octetstring {
611 var octetstring l3_payload;
612 if (lengthof(imsi) == 0) {
613 imsi := f_rnd_imsi('00101'H);
614 }
615 l3_payload := enc_PDU_ML3_MS_NW(valueof(ts_LU_REQ(LU_Type_IMSI_Attach, ts_MI_LV(ts_MI_IMSI(imsi)))));
616 return l3_payload;
617}
618
Harald Weltea4ca4462018-02-09 00:17:14 +0100619type component test_CT extends CTRL_Adapter_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600620 /* Array of per-BTS/TRX state */
621 var BTS_State bts[NUM_BTS][NUM_TRX];
Harald Welte89ab1912018-02-23 18:56:29 +0100622 /* RSL common Channel Port (for RSL_Emulation) */
623 port RSL_CCHAN_PT RSL_CCHAN[NUM_BTS];
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600624 /* array of per-BTS/TRX RSL test ports */
625 port IPA_RSL_PT IPA_RSL[NUM_BTS][NUM_TRX];
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100626 port IPA_CODEC_PT IPA; /* Required for compilation of TC_rsl_unknown_unit_id() */
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +0200627 /* CTRL muxed over IPA in SCCPlite conn BSC<->MSC (or BSC-NAT) */
628 port IPA_CTRL_PT SCCPLITE_IPA_CTRL;
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200629 /* Configure/manage IPA_Emulation per-BTS/TRX port: */
630 port IPA_CFG_PT IPA_CFG_PORT[NUM_BTS][NUM_TRX];
Harald Weltea5d2ab22017-12-09 14:21:42 +0100631
Pau Espin Pedrol3c630532022-10-20 19:00:11 +0200632 var MGCP_Emulation_CT vc_MGCP[NUM_MGW];
633 var integer g_nr_mgw; /* number of vc_MGCP to initialize */
Harald Weltebc03c762018-02-12 18:09:38 +0100634 port TELNETasp_PT BSCVTY;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100635
Daniel Willmannebdecc02020-08-12 15:30:17 +0200636 /* StatsD */
637 var StatsD_Checker_CT vc_STATSD;
638
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200639 var RAN_Adapter g_bssap[NUM_MSC];
Harald Welte47cd0e32020-08-21 12:39:11 +0200640 var BSSAP_LE_Adapter g_bssap_le;
Harald Weltea4ca4462018-02-09 00:17:14 +0100641 /* for old legacy-tests only */
642 port BSSAP_CODEC_PT BSSAP;
Harald Welte47cd0e32020-08-21 12:39:11 +0200643 port BSSAP_LE_CODEC_PT BSSAP_LE;
Harald Weltea4ca4462018-02-09 00:17:14 +0100644
Harald Welte21b46bd2017-12-17 19:46:32 +0100645 /* are we initialized yet */
Harald Welte28d943e2017-11-25 15:00:50 +0100646 var boolean g_initialized := false;
Harald Welte21b46bd2017-12-17 19:46:32 +0100647
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200648 /* Osmux is enabled through VTY */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200649 var boolean g_osmux_enabled_cn := false;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +0200650 var boolean g_osmux_enabled_bts := false;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200651
Pau Espin Pedrolc675b612020-01-09 19:55:40 +0100652 /*Configure T(tias) over VTY, seconds */
653 var integer g_bsc_sccp_timer_ias := 7 * 60;
654 /*Configure T(tiar) over VTY, seconds */
655 var integer g_bsc_sccp_timer_iar := 15 * 60;
656
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +0200657 /* global test case guard timer (actual timeout value is set in f_init()) */
Harald Welteae026692017-12-09 01:03:01 +0100658 timer T_guard := 30.0;
659
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200660 var CounterNameValsList g_ctr_msc;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000661 var CounterNameValsList g_ctr_bsc;
662 var CounterNameValsList g_ctr_bts;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200663
664 /* System Information bytes as received during RSL startup, for each RSL[idx]. */
665 var SystemInformationConfig_list g_system_information := {};
Harald Welte28d943e2017-11-25 15:00:50 +0100666}
667
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200668type record of charstring phys_chan_configs;
Harald Welte28d943e2017-11-25 15:00:50 +0100669modulepar {
Harald Welte21b46bd2017-12-17 19:46:32 +0100670 /* IP address at which the BSC can be reached */
Harald Welte696ddb62017-12-08 14:01:43 +0100671 charstring mp_bsc_ip := "127.0.0.1";
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100672 /* port number to which to establish the IPA OML connections */
673 integer mp_bsc_oml_port := 3002;
Harald Welte21b46bd2017-12-17 19:46:32 +0100674 /* port number to which to establish the IPA RSL connections */
Harald Welte696ddb62017-12-08 14:01:43 +0100675 integer mp_bsc_rsl_port := 3003;
Harald Welte21b46bd2017-12-17 19:46:32 +0100676 /* port number to which to establish the IPA CTRL connection */
Harald Welte96c94412017-12-09 03:12:45 +0100677 integer mp_bsc_ctrl_port := 4249;
Daniel Willmannebdecc02020-08-12 15:30:17 +0200678 /* port number to which to listen for STATSD metrics */
679 integer mp_bsc_statsd_port := 8125;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100680 /* IP address at which the test binds */
681 charstring mp_test_ip := "127.0.0.1";
Harald Weltea4ca4462018-02-09 00:17:14 +0100682
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200683 RAN_Configurations mp_bssap_cfg := {
684 {
685 transport := BSSAP_TRANSPORT_AoIP,
686 sccp_service_type := "mtp3_itu",
687 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
688 own_pc := 185, /* 0.23.1 first MSC emulation */
689 own_ssn := 254,
690 peer_pc := 187, /* 0.23.3 osmo-bsc */
691 peer_ssn := 254,
692 sio := '83'O,
Harald Weltecb0cc432020-06-21 19:42:31 +0200693 rctx := 1
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200694 },
695 {
696 transport := BSSAP_TRANSPORT_AoIP,
697 sccp_service_type := "mtp3_itu",
698 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
699 own_pc := 2, /* 0.0.2 second MSC emulation */
700 own_ssn := 254,
701 peer_pc := 187, /* 0.23.3 osmo-bsc */
702 peer_ssn := 254,
703 sio := '83'O,
704 rctx := 2
705 },
706 {
707 transport := BSSAP_TRANSPORT_AoIP,
708 sccp_service_type := "mtp3_itu",
709 sctp_addr := { 23907, "127.0.0.1", 2905, "127.0.0.1" },
710 own_pc := 3, /* 0.0.3 third MSC emulation */
711 own_ssn := 254,
712 peer_pc := 187, /* 0.23.3 osmo-bsc */
713 peer_ssn := 254,
714 sio := '83'O,
715 rctx := 3
716 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100717 };
Pau Espin Pedrol58cf6822019-05-28 18:11:33 +0200718
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200719 /* Must match per BTS config in osmo-bsc.cfg */
720 phys_chan_configs phys_chan_config := {
721 "CCCH+SDCCH4+CBCH",
722 "TCH/F",
723 "TCH/F",
724 "TCH/F",
725 "TCH/F",
Vadim Yanitskiy343c9eb2021-07-16 18:36:01 +0600726 "TCH/H",
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200727 "PDCH",
728 "PDCH"
729 };
730
Harald Welte47cd0e32020-08-21 12:39:11 +0200731 BSSAP_LE_Configuration mp_bssap_le_cfg := {
732 sccp_service_type := "mtp3_itu",
733 sctp_addr := { 23908, "127.0.0.1", 2905, "127.0.0.1" },
Neels Hofmeyrac086c12020-09-18 23:46:42 +0200734 own_pc := 190, /* 0.23.6 SMLC emulation */
Harald Welte47cd0e32020-08-21 12:39:11 +0200735 own_ssn := 252, /* SMLC side SSN */
736 peer_pc := 187, /* 0.23.3 osmo-bsc */
737 peer_ssn := 250, /* BSC side SSN */
738 sio := '83'O,
739 rctx := 6
740 };
Neels Hofmeyrcfe44062020-10-15 02:28:08 +0200741 boolean mp_enable_lcs_tests := true;
Harald Welte47cd0e32020-08-21 12:39:11 +0200742
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100743 /* Value set in osmo-bsc.cfg "ms max power" */
744 uint8_t mp_exp_ms_power_level := 7;
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600745
746 /* Whether to check for memory leaks */
747 boolean mp_verify_talloc_count := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100748}
749
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200750friend function f_gen_test_hdlr_pars(integer bssap_idx := 0) return TestHdlrParams {
Philipp Maier48604732018-10-09 15:00:37 +0200751
752 var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200753 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier48604732018-10-09 15:00:37 +0200754 pars.aoip := true;
755 } else {
756 pars.aoip := false;
757 }
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100758 pars.exp_ms_power_level := mp_exp_ms_power_level;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200759 pars.mscpool.bssap_idx := bssap_idx;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600760 pars.expect_tsc := c_BtsParams[0].tsc;
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300761 pars.imsi := f_rnd_imsi('00101'H);
762
763 log(testcasename(), ": using IMSI ", pars.imsi);
Neels Hofmeyrb5b7a6e2021-06-04 19:03:45 +0200764
Philipp Maier48604732018-10-09 15:00:37 +0200765 return pars;
766}
767
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200768/* Convenience functions for rate counters using g_ctr_msc. */
769
770private function f_ctrs_msc_init(integer mscs_count := NUM_MSC, CounterNameVals counternames := counternames_msc_mscpool) runs on test_CT {
771 g_ctr_msc := f_counter_name_vals_get_n(IPA_CTRL, "msc", mscs_count, counternames);
772 log("initial msc rate counters: ", g_ctr_msc);
773}
774
775private function f_ctrs_msc_add(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr9656e922020-06-30 01:27:01 +0200776 f_counter_name_vals_list_add(g_ctr_msc, msc_nr, countername, val);
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200777}
778
779/* f_ctrs_msc_init();
780 * f_do_thing(on_msc := 0);
781 * f_do_thing(on_msc := 0);
782 * f_do_other(on_msc := 1);
783 * f_ctrs_msc_add(0, "thing", 2);
784 * f_ctrs_msc_add(1, "other");
785 * f_ctrs_msc_verify();
786 */
787private function f_ctrs_msc_verify() runs on test_CT {
788 log("verifying msc rate counters: ", g_ctr_msc);
789 f_counter_name_vals_expect_n(IPA_CTRL, "msc", g_ctr_msc);
790}
791
792/* convenience: f_ctrs_msc_add() and f_ctrs_msc_verify() in one call.
793 * f_ctrs_msc_init();
794 * f_do_thing(on_msc := 0);
795 * f_do_thing(on_msc := 0);
796 * f_do_thing(on_msc := 0);
797 * f_ctrs_msc_expect(0, "thing", 3);
798 */
799private function f_ctrs_msc_expect(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
800 f_ctrs_msc_add(msc_nr, countername, val);
801 f_ctrs_msc_verify();
802}
803
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000804/* Convenience functions for rate counters using g_ctr_bts, always also including g_ctr_bsc. */
805
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100806private 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 +0000807 g_ctr_bts := f_counter_name_vals_get_n(IPA_CTRL, "bts", bts_count, counternames);
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100808 log("initial bts rate counters: ", g_ctr_bts);
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100809}
810
811function f_ctrs_bsc_and_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
812 f_ctrs_bts_init(bts_count, counternames);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000813 f_ctrs_bsc_init(counternames);
814}
815
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100816private function f_ctrs_bsc_and_bts_handover_init(integer bts_count := NUM_BTS) runs on test_CT {
817 var CounterNameVals bts_names := counternames_bsc_bts_handover & counternames_bts_handover;
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100818 f_ctrs_bts_init(bts_count, bts_names);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100819 f_ctrs_bsc_init(counternames_bsc_bts_handover);
820}
821
822private function f_ctrs_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000823 f_counter_name_vals_list_add(g_ctr_bts, bts_nr, countername, val);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100824}
825
826private function f_ctrs_bsc_and_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
827 f_ctrs_bts_add(bts_nr, countername, val);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000828 f_ctrs_bsc_add(countername, val);
829}
830
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100831function f_ctrs_bts_verify() runs on test_CT {
832 f_counter_name_vals_expect_n(IPA_CTRL, "bts", g_ctr_bts);
833}
834
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000835/* f_ctrs_bsc_and_bts_init();
836 * f_do_thing(on_bts := 0);
837 * f_do_thing(on_bts := 0);
838 * f_do_other(on_bts := 1);
839 * f_ctrs_bsc_and_bts_add(0, "thing", 2);
840 * f_ctrs_bsc_and_bts_add(1, "other");
841 * f_ctrs_bsc_and_bts_verify();
842 */
843private function f_ctrs_bsc_and_bts_verify() runs on test_CT {
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100844 f_ctrs_bts_verify();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000845 f_ctrs_bsc_verify();
846}
847
848/* convenience: f_ctrs_bsc_and_bts_add() and f_ctrs_bsc_and_bts_verify() in one call.
849 * f_ctrs_bsc_and_bts_init();
850 * f_do_thing(on_bts := 0);
851 * f_do_thing(on_bts := 0);
852 * f_do_thing(on_bts := 0);
853 * f_ctrs_bsc_and_bts_expect(0, "thing", 3);
854 */
855private function f_ctrs_bsc_and_bts_expect(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
856 f_ctrs_bsc_and_bts_add(bts_nr, countername, val);
857 f_ctrs_bsc_and_bts_verify();
858}
859
860
861/* Convenience functions for rate counters using g_ctr_bsc. */
862
863private function f_ctrs_bsc_init(CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
864 g_ctr_bsc := f_counter_name_vals_get_n(IPA_CTRL, "bsc", 1, counternames);
865 log("initial bsc rate counters: ", g_ctr_bsc);
866}
867
868private function f_ctrs_bsc_add(charstring countername, integer val := 1) runs on test_CT {
869 f_counter_name_vals_list_add(g_ctr_bsc, 0, countername, val);
870}
871
872/* f_ctrs_bsc_init();
873 * f_do_thing();
874 * f_do_thing();
875 * f_do_other();
876 * f_ctrs_bsc_add("thing", 2);
877 * f_ctrs_bsc_add("other");
878 * f_ctrs_bsc_verify();
879 */
880private function f_ctrs_bsc_verify() runs on test_CT {
881 f_counter_name_vals_expect_n(IPA_CTRL, "bsc", g_ctr_bsc);
882}
883
884/* convenience: f_ctrs_bsc_add() and f_ctrs_bsc_verify() in one call.
885 * f_ctrs_bsc_init();
886 * f_do_thing();
887 * f_ctrs_bsc_expect("thing", 1);
888 */
889private function f_ctrs_bsc_expect(charstring countername, integer val := 1) runs on test_CT {
890 f_ctrs_bsc_add(countername, val);
891 f_ctrs_bsc_verify();
892}
893
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200894
Oliver Smith39f53072022-10-27 14:44:04 +0200895friend function f_shutdown_helper(boolean ho := false) runs on test_CT {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100896 /* Run the subscr and conn leak test only when the VTY is initialized */
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600897 if (BSCVTY.checkstate("Mapped") and mp_verify_talloc_count) {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100898 f_verify_talloc_count(BSCVTY, {"struct bsc_subscr", "struct gsm_subscriber_connection"});
899 }
900
Oliver Smith39f53072022-10-27 14:44:04 +0200901 /* Reset handover related configuration */
902 if (ho) {
903 f_bts_0_cfg(BSCVTY,
904 {"no neighbors",
905 "neighbor-list mode manual-si5",
906 "neighbor-list add arfcn 100",
907 "neighbor-list add arfcn 200",
908 "si5 neighbor-list add arfcn 10",
909 "si5 neighbor-list add arfcn 20",
910 "handover algorithm 1"});
911 }
912
Daniel Willmann637ef6c2018-07-25 10:49:09 +0200913 all component.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100914 setverdict(pass);
Daniel Willmannafce8662018-07-06 23:11:32 +0200915 mtc.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100916}
917
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200918private function f_legacy_bssap_reset(integer bssap_idx := 0) runs on test_CT {
Harald Weltea4ca4462018-02-09 00:17:14 +0100919 var BSSAP_N_UNITDATA_ind ud_ind;
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200920 var boolean reset_received := false;
Harald Weltea4ca4462018-02-09 00:17:14 +0100921 timer T := 5.0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200922 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 +0200923 ts_BSSMAP_Reset(0, g_osmux_enabled_cn)));
Harald Weltea4ca4462018-02-09 00:17:14 +0100924 T.start;
925 alt {
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200926 [] 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 +0200927 tr_BSSMAP_ResetAck(g_osmux_enabled_cn))) {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200928 log("BSSMAP: Received RESET-ACK in response to RESET, we're ready to go!");
Harald Weltea4ca4462018-02-09 00:17:14 +0100929 }
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200930 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200931 log("BSSMAP: Respoding to inbound RESET with RESET-ACK");
Harald Weltea4ca4462018-02-09 00:17:14 +0100932 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200933 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200934 reset_received := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100935 repeat;
936 }
937 [] BSSAP.receive { repeat; }
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200938 [] T.timeout {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200939 log("BSSMAP: Timeout waiting for RESET-ACK after sending RESET");
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200940 /* If we received a RESET after ours was sent, it
941 may be a race condition where the other peer beacame
942 available after we sent it, but we are in a desired
943 state anyway, so go forward. */
944 if (not reset_received) {
945 setverdict(fail);
946 }
947 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100948 }
Harald Welte28d943e2017-11-25 15:00:50 +0100949}
950
Harald Welteae026692017-12-09 01:03:01 +0100951type record IPA_Client {
Harald Welte21b46bd2017-12-17 19:46:32 +0100952 /* IPA Emulation component reference */
Harald Welteae026692017-12-09 01:03:01 +0100953 IPA_Emulation_CT vc_IPA,
Harald Welte21b46bd2017-12-17 19:46:32 +0100954 /* Unit-ID and other CCM parameters to use for IPA client emulation */
Harald Welteae026692017-12-09 01:03:01 +0100955 IPA_CCM_Parameters ccm_pars,
Harald Welte21b46bd2017-12-17 19:46:32 +0100956 /* String identifier for this IPA Client */
Harald Welte624f9632017-12-16 19:26:04 +0100957 charstring id,
Harald Welte21b46bd2017-12-17 19:46:32 +0100958 /* Associated RSL Emulation Component (if any). Only used in "Handler mode" */
Harald Welte624f9632017-12-16 19:26:04 +0100959 RSL_Emulation_CT vc_RSL optional
Harald Welte28d943e2017-11-25 15:00:50 +0100960}
961
Harald Welte21b46bd2017-12-17 19:46:32 +0100962/*! Start the IPA/RSL related bits for one IPA_Client.
963 * \param clnt IPA_Client for which to establish
964 * \param bsc_host IP address / hostname of the BSC
965 * \param bsc_port TCP port number of the BSC
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600966 * \param idx BTS/TRX index values
Harald Welte21b46bd2017-12-17 19:46:32 +0100967 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600968function f_ipa_rsl_start(inout IPA_Client clnt, charstring bsc_host, PortNumber bsc_port,
969 BtsTrxIdx idx := {0, 0}, boolean handler_mode := false)
Harald Welte28d943e2017-11-25 15:00:50 +0100970runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +0100971 timer T := 10.0;
972
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600973 clnt.id := "IPA-BTS" & int2str(idx.bts) & "-TRX" & int2str(idx.trx) & "-RSL";
Harald Welte71389132021-12-09 21:58:18 +0100974 clnt.vc_IPA := IPA_Emulation_CT.create(clnt.id & "-IPA") alive;
Harald Welteae026692017-12-09 01:03:01 +0100975 clnt.ccm_pars := c_IPA_default_ccm_pars;
976 clnt.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600977 clnt.ccm_pars.unit_id := int2str(1234 + idx.bts) & "/0/" & int2str(idx.trx);
Harald Welte624f9632017-12-16 19:26:04 +0100978 if (handler_mode) {
Harald Welte71389132021-12-09 21:58:18 +0100979 clnt.vc_RSL := RSL_Emulation_CT.create(clnt.id & "-RSL") alive;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600980 connect(clnt.vc_RSL:CCHAN_PT, self:RSL_CCHAN[idx.bts]);
Harald Welte624f9632017-12-16 19:26:04 +0100981 }
Harald Welteae026692017-12-09 01:03:01 +0100982
983 map(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200984 connect(clnt.vc_IPA:CFG_PORT, self:IPA_CFG_PORT[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100985 if (handler_mode) {
986 connect(clnt.vc_IPA:IPA_RSL_PORT, clnt.vc_RSL:IPA_PT);
987 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600988 connect(clnt.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100989 }
Harald Welteae026692017-12-09 01:03:01 +0100990
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600991 var integer local_port := 10000 + idx.bts * 1000 + idx.trx;
992 clnt.vc_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", local_port, clnt.ccm_pars));
Harald Welte624f9632017-12-16 19:26:04 +0100993 if (handler_mode) {
994 clnt.vc_RSL.start(RSL_Emulation.main());
995 return;
996 }
Harald Welteae026692017-12-09 01:03:01 +0100997
998 /* wait for IPA RSL link to connect and send ID ACK */
999 T.start;
1000 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001001 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) {
Harald Welteae026692017-12-09 01:03:01 +01001002 T.stop;
Harald Welteae026692017-12-09 01:03:01 +01001003 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001004 [] IPA_RSL[idx.bts][idx.trx].receive(ASP_IPA_Event:?) { repeat }
1005 [] IPA_RSL[idx.bts][idx.trx].receive { repeat }
Harald Welteae026692017-12-09 01:03:01 +01001006 [] T.timeout {
Harald Welte96c94412017-12-09 03:12:45 +01001007 setverdict(fail, "Timeout RSL waiting for ASP_IPA_EVENT_ID_ACK");
Daniel Willmannafce8662018-07-06 23:11:32 +02001008 mtc.stop;
Harald Welteae026692017-12-09 01:03:01 +01001009 }
1010 }
1011}
1012
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001013function f_ipa_rsl_stop(inout IPA_Client clnt, BtsTrxIdx idx := {0, 0}) runs on test_CT {
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001014 var IPL4asp_Types.Result res := {
1015 errorCode := omit,
1016 connId := omit,
1017 os_error_code := omit,
1018 os_error_text := omit
1019 };
1020
Harald Welte12055472018-03-17 20:10:08 +01001021 if (not isbound(clnt) or not isbound(clnt.vc_IPA)) {
1022 return;
1023 }
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001024
1025 /* Alive components don't finish sockets (TCP FIN) when they are
1026 * stopped. Hence, we need to manually call close() on them to make sure
1027 * the IUT knows about it. */
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001028 f_ipa_cfg_disconnect(IPA_CFG_PORT[idx.bts][idx.trx], res);
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001029
Harald Welte12055472018-03-17 20:10:08 +01001030 clnt.vc_IPA.stop;
1031 if (isbound(clnt.vc_RSL)) {
1032 clnt.vc_RSL.stop;
1033 }
1034}
1035
Harald Welte21b46bd2017-12-17 19:46:32 +01001036/* Wait for the OML connection to be brought up by the external osmo-bts-omldummy */
Harald Weltea5d2ab22017-12-09 14:21:42 +01001037function f_wait_oml(integer bts_nr, charstring status, float secs_max) runs on test_CT {
1038 timer T := secs_max;
1039 T.start;
1040 while (true) {
1041 if (f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-connection-state") == status) {
1042 T.stop;
Harald Weltebd868bd2017-12-10 18:28:40 +01001043 /* the 'degraded' state exists from OML connection time, and we have to wait
1044 * until all MO's are initialized */
1045 T.start(1.0);
1046 T.timeout;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001047 return;
1048 }
Harald Weltef0d6ac62017-12-17 17:02:21 +01001049 f_sleep(0.1);
Harald Weltea5d2ab22017-12-09 14:21:42 +01001050 if (not T.running) {
Max99253902018-11-16 17:57:39 +01001051 setverdict(fail, "Timeout waiting for BTS" & int2str(bts_nr) & " oml-connection-state ", status);
Daniel Willmannafce8662018-07-06 23:11:32 +02001052 mtc.stop;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001053 }
1054 }
1055}
1056
Harald Welte21b46bd2017-12-17 19:46:32 +01001057/* global altstep for global guard timer; also takes care of responding RESET witH RESET-ACK */
Harald Welteae026692017-12-09 01:03:01 +01001058altstep as_Tguard() runs on test_CT {
Harald Welte60e823a2017-12-10 14:10:59 +01001059 var BSSAP_N_UNITDATA_ind ud_ind;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001060 [] T_guard.timeout {
1061 setverdict(fail, "Timeout of T_guard");
Daniel Willmannafce8662018-07-06 23:11:32 +02001062 mtc.stop;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001063 }
Harald Welte60e823a2017-12-10 14:10:59 +01001064 /* always respond with RESET ACK to RESET */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001065 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Harald Welte60e823a2017-12-10 14:10:59 +01001066 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001067 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Harald Welte69c1c262017-12-13 21:02:08 +01001068 repeat;
Harald Welte60e823a2017-12-10 14:10:59 +01001069 }
Harald Welte28d943e2017-11-25 15:00:50 +01001070}
1071
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001072altstep no_bssmap_reset() runs on test_CT {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001073 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001074 setverdict(fail, "unexpected BSSMAP Reset");
Daniel Willmannafce8662018-07-06 23:11:32 +02001075 mtc.stop;
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001076 }
1077}
1078
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001079function f_init_mgcp(integer mgw_nr, charstring id) runs on test_CT {
1080 id := id & "-MGCP-" & int2str(mgw_nr);
Daniel Willmann191e0d92018-01-17 12:44:35 +01001081
1082 var MGCPOps ops := {
1083 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
1084 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
1085 };
1086 var MGCP_conn_parameters mgcp_pars := {
1087 callagent_ip := mp_bsc_ip,
Harald Welte9e4273e2018-01-29 22:01:22 +01001088 callagent_udp_port := -1,
Daniel Willmann191e0d92018-01-17 12:44:35 +01001089 mgw_ip := mp_test_ip,
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001090 mgw_udp_port := 2427 + mgw_nr,
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02001091 /* Enable it for SCCPlite, since we have 2 MGCP sockets towards MGW (UDP one +
Pau Espin Pedrol36eeaf72022-10-20 16:50:31 +02001092 the one with MGCP over IPA forwarded from MSC one) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001093 multi_conn_mode := (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER)
Daniel Willmann191e0d92018-01-17 12:44:35 +01001094 };
1095
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001096 vc_MGCP[mgw_nr] := MGCP_Emulation_CT.create(id) alive;
1097 vc_MGCP[mgw_nr].start(MGCP_Emulation.main(ops, mgcp_pars, id));
Daniel Willmann191e0d92018-01-17 12:44:35 +01001098}
1099
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001100/* Enable or disable (current default) Osmux. When enabling, BSSMAP Reset
1101 * contains extra IE (OsmuxSupport) and osmo-bsc will handle AssignReq with
1102 * OsmuxCID IE.
1103 */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001104private function f_vty_allow_osmux_cn(boolean allow) runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001105 f_vty_enter_cfg_msc(BSCVTY, 0);
1106 if (allow) {
1107 f_vty_transceive(BSCVTY, "osmux on");
1108 } else {
1109 f_vty_transceive(BSCVTY, "osmux off");
1110 }
1111 f_vty_transceive(BSCVTY, "exit");
1112 f_vty_transceive(BSCVTY, "exit");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001113}
1114
Max2253c0b2018-11-06 19:28:05 +01001115function f_init_vty(charstring id := "foo") runs on test_CT {
Harald Welte94e0c342018-04-07 11:33:23 +02001116 if (BSCVTY.checkstate("Mapped")) {
1117 /* skip initialization if already executed once */
1118 return;
1119 }
Harald Weltebc03c762018-02-12 18:09:38 +01001120 map(self:BSCVTY, system:BSCVTY);
1121 f_vty_set_prompts(BSCVTY);
1122 f_vty_transceive(BSCVTY, "enable");
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01001123 f_cs7_inst_0_cfg(BSCVTY, {"sccp-timer ias " & int2str(g_bsc_sccp_timer_ias),
1124 "sccp-timer iar " & int2str(g_bsc_sccp_timer_iar)});
Harald Weltebc03c762018-02-12 18:09:38 +01001125}
1126
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +02001127friend function f_logp(TELNETasp_PT pt, charstring log_msg)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001128{
1129 // log on TTCN3 log output
1130 log(log_msg);
1131 // log in stderr log
Neels Hofmeyr8bdafe52021-12-14 17:25:48 +01001132 if (pt.checkstate("Mapped")) {
1133 f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
1134 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001135}
1136
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001137private function f_sysinfo_seen(integer rsl_idx, RSL_Message rsl) runs on test_CT
1138{
1139 if (rsl_idx >= lengthof(g_system_information)) {
1140 g_system_information[rsl_idx] := SystemInformationConfig_omit
1141 }
1142 f_sysinfo_dec_raw(g_system_information[rsl_idx], rsl);
1143}
1144
1145altstep as_catch_RSL_sysinfo(integer rsl_idx) runs on test_CT {
1146 var ASP_RSL_Unitdata rx_rsl_ud;
1147
1148 /* For handler_mode := false, receiving the RSL bootstrap messages directly on IPA_RSL */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001149 [] 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 +02001150 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1151 repeat;
1152 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001153 [] 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 +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_NO_SACCH_FILL)) -> 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_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 }
1165
1166 /* For handler_mode := true, receiving the RSL bootstrap messages via RSL_Emulation */
1167 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
1168 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1169 repeat;
1170 }
1171 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_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_NO_SACCH_FILL)) -> 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_SACCH_FILL)) -> value rx_rsl_ud {
1180 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1181 repeat;
1182 }
1183}
1184
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001185/* TODO: use BooleanList from COMMON/src/General_Types.ttcn */
1186private type record of boolean my_BooleanList;
1187
1188private function f_vty_msc_allow_attach(TELNETasp_PT pt, my_BooleanList allow_attach_list)
1189{
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001190 var charstring config := f_vty_transceive_ret(pt, "show running-config");
1191
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001192 for (var integer msc_nr := 0; msc_nr < sizeof(allow_attach_list); msc_nr := msc_nr+1) {
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001193 if (f_strstr(config, "\nmsc " & int2str(msc_nr) & "\n") < 0) {
1194 /* There is no 'msc N' for this msc_nr in the running config, so don't create an empty msc by
1195 * stepping into that config node. */
1196 log("msc ", msc_nr, " is not configured, skipping");
1197 continue;
1198 }
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001199 f_vty_enter_cfg_msc(pt, msc_nr);
1200 if (allow_attach_list[msc_nr]) {
1201 /* strict := false: ignore if osmo-bsc does not support this config option (latest build) */
1202 f_vty_transceive(pt, "allow-attach", strict := false);
1203 } else {
1204 f_vty_transceive(pt, "no allow-attach", strict := false);
1205 }
1206 f_vty_transceive(pt, "exit");
1207 f_vty_transceive(pt, "exit");
1208 }
1209}
1210
Harald Welte21b46bd2017-12-17 19:46:32 +01001211/* global initialization function
1212 * \param nr_bts Number of BTSs we should start/bring up
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001213 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false).
1214 * \param nr_msc Number of virtual MSCs to bring up to connect to osmo-bsc.
1215 */
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001216function f_init(integer nr_bts := NUM_BTS, boolean handler_mode := false,
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001217 integer nr_msc := 1, integer nr_mgw := 1, float guard_timeout := 30.0) runs on test_CT {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001218 var integer bssap_idx;
Harald Welte28d943e2017-11-25 15:00:50 +01001219
Harald Welteae026692017-12-09 01:03:01 +01001220 if (g_initialized) {
1221 return;
Harald Welte28d943e2017-11-25 15:00:50 +01001222 }
Harald Welteae026692017-12-09 01:03:01 +01001223 g_initialized := true;
1224
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +02001225 T_guard.start(guard_timeout);
Daniel Willmanne68f9272018-11-27 15:15:28 +01001226 activate(as_Tguard());
1227
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001228 f_init_vty("VirtMSC");
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001229 f_vty_allow_osmux_cn(g_osmux_enabled_cn);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001230
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001231 var my_BooleanList allow_attach := { false, false, false };
Daniel Willmannebdecc02020-08-12 15:30:17 +02001232 f_init_statsd("VirtMSC", vc_STATSD, mp_test_ip, mp_bsc_statsd_port);
1233
Neels Hofmeyr9db8e0e2021-08-23 20:45:58 +02001234 /* Make sure each MSC's internal state is "DISCONNECTED" at first */
1235 for (bssap_idx := 0; bssap_idx < NUM_MSC; bssap_idx := bssap_idx+1) {
1236 f_vty_transceive(BSCVTY, "msc " & int2str(bssap_idx) & " bssmap reset", strict := false);
1237 }
1238
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001239 for (bssap_idx := 0; bssap_idx < nr_msc; bssap_idx := bssap_idx+1) {
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001240 allow_attach[bssap_idx] := true;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001241 /* Call a function of our 'parent component' RAN_Adapter_CT to start the
1242 * MSC-side BSSAP emulation */
1243 if (handler_mode) {
1244 var RanOps ranops := MSC_RanOps;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001245 ranops.use_osmux := g_osmux_enabled_cn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001246 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", ranops);
1247 connect(self:SCCPLITE_IPA_CTRL, g_bssap[bssap_idx].vc_RAN:CTRL_CLIENT);
1248 f_ran_adapter_start(g_bssap[bssap_idx]);
1249 } else {
1250 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", omit);
1251 connect(self:BSSAP, g_bssap[bssap_idx].vc_SCCP:SCCP_SP_PORT);
1252 f_ran_adapter_start(g_bssap[bssap_idx]);
1253 f_legacy_bssap_reset();
1254 }
Harald Welte67089ee2018-01-17 22:19:03 +01001255 }
Harald Welted5833a82018-05-27 16:52:56 +02001256
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02001257 if (mp_enable_lcs_tests) {
1258 if (handler_mode) {
1259 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", SMLC_BssapLeOps);
1260 } else {
1261 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", omit);
1262 connect(self:BSSAP_LE, g_bssap_le.vc_SCCP:SCCP_SP_PORT);
1263 }
1264 f_bssap_le_adapter_start(g_bssap_le);
Harald Welte47cd0e32020-08-21 12:39:11 +02001265 }
Harald Welte47cd0e32020-08-21 12:39:11 +02001266
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001267 /* start the test with exactly all enabled MSCs allowed to attach */
1268 f_vty_msc_allow_attach(BSCVTY, allow_attach);
1269
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01001270 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Harald Welte28d943e2017-11-25 15:00:50 +01001271
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02001272 g_nr_mgw := nr_mgw;
1273 for (var integer i := 0; i < g_nr_mgw; i := i+1) {
1274 f_init_mgcp(i, "VirtMGW");
1275 }
Daniel Willmann191e0d92018-01-17 12:44:35 +01001276
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001277 for (var integer i := 0; i < nr_bts; i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001278 f_init_bts(i, c_BtsParams[i].trx_num, handler_mode);
Harald Welte696ddb62017-12-08 14:01:43 +01001279 }
Neels Hofmeyr9c0f9c82022-01-23 01:20:28 +01001280
1281 /* Emit a marker to appear in the SUT's own logging output */
1282 f_logp(BSCVTY, testcasename() & "() start");
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001283}
Harald Welte696ddb62017-12-08 14:01:43 +01001284
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001285function f_init_bts(integer bts_idx := 0,
1286 integer trx_num := NUM_TRX_CFG,
1287 boolean handler_mode := false)
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001288runs on test_CT {
1289 /* wait until osmo-bts-omldummy has respawned */
1290 f_wait_oml(bts_idx, "degraded", 5.0);
1291
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001292 /* start RSL connection(s) */
1293 for (var integer trx_idx := 0; trx_idx < trx_num; trx_idx := trx_idx + 1) {
1294 f_ipa_rsl_start(bts[bts_idx][trx_idx].rsl,
1295 mp_bsc_ip, mp_bsc_rsl_port,
1296 {bts_idx, trx_idx}, handler_mode);
1297 }
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001298 /* wait until BSC tells us "connected" */
1299 f_wait_oml(bts_idx, "connected", 5.0);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001300
1301 /* Set up BTS with VTY commands: */
Vadim Yanitskiy4d852082022-09-14 14:07:20 +07001302 if (Misc_Helpers.f_osmo_repo_is("nightly")) {
1303 f_vty_enter_cfg_bts(BSCVTY, bts_idx);
1304 if (g_osmux_enabled_bts) {
1305 f_vty_transceive(BSCVTY, "osmux on");
1306 } else {
1307 f_vty_transceive(BSCVTY, "osmux off");
1308 }
1309 f_vty_transceive(BSCVTY, "end");
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001310 }
Harald Welte28d943e2017-11-25 15:00:50 +01001311}
1312
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001313function f_init_bts_and_check_sysinfo(integer bts_idx := 0,
1314 integer trx_num := NUM_TRX_CFG,
1315 boolean handler_mode := false,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001316 template SystemInformationConfig expect_si)
1317runs on test_CT {
1318 var default sysinfo := activate(as_catch_RSL_sysinfo(bts_idx));
1319
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001320 f_init_bts(bts_idx, trx_num, handler_mode);
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001321
1322 /* Give some time to (hopefully/most likely) collect all system informations from RSL startup.
1323 * We could stop as soon as all expected SI are received, but then we might miss SI that we don't expect and
1324 * that might be sent afterwards. So rather give a generous timeout and be quite sure to catch all SI.
1325 */
1326 f_sleep(5.0);
1327 log("RSL ", bts_idx, " SYSTEM INFORMATION: ", g_system_information[bts_idx]);
1328
1329 deactivate(sysinfo);
1330
1331 if (match(g_system_information[bts_idx], expect_si)) {
1332 setverdict(pass);
1333 } else {
1334 log("RSL ", bts_idx, ": EXPECTED SI: ", expect_si);
1335 log("RSL ", bts_idx, ": GOT SI: ", g_system_information[bts_idx]);
1336 setverdict(fail, "received SI does not match expectations");
1337 return;
1338 }
1339}
1340
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001341/* expect to receive a RSL message matching a specified template on a given BTS / TRX */
1342function f_exp_ipa_rx(template (present) RSL_Message t_rx,
1343 BtsTrxIdx idx := {0, 0},
1344 float Tval := 2.0)
Harald Welteae026692017-12-09 01:03:01 +01001345runs on test_CT return RSL_Message {
1346 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001347 timer T := Tval;
Harald Welteae026692017-12-09 01:03:01 +01001348
1349 T.start;
1350 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001351 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Harald Welteae026692017-12-09 01:03:01 +01001352 T.stop;
1353 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001354 [] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
Harald Welteb2917702017-12-10 15:48:52 +01001355 [] T.timeout {
1356 setverdict(fail, "Timeout expecting ", t_rx);
Daniel Willmannafce8662018-07-06 23:11:32 +02001357 mtc.stop;
Harald Welteb2917702017-12-10 15:48:52 +01001358 }
Harald Welteae026692017-12-09 01:03:01 +01001359 }
1360 return rx_rsl_ud.rsl;
1361}
1362
Harald Welte21b46bd2017-12-17 19:46:32 +01001363/* helper function to transmit RSL on a given BTS/stream */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001364function f_ipa_tx(template (value) RSL_Message t_tx,
1365 BtsTrxIdx idx := {0, 0},
1366 IpaStreamId sid := IPAC_PROTO_RSL_TRX0)
Harald Welteae026692017-12-09 01:03:01 +01001367runs on test_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001368 IPA_RSL[idx.bts][idx.trx].send(ts_ASP_RSL_UD(t_tx, sid));
Harald Welteae026692017-12-09 01:03:01 +01001369}
1370
1371
Harald Welte4003d112017-12-09 22:35:39 +01001372/* verify we get a CHAN_ACT after CHAN RQD */
Harald Welteae026692017-12-09 01:03:01 +01001373testcase TC_chan_act_noreply() runs on test_CT {
1374 var BSSAP_N_UNITDATA_ind ud_ind;
Harald Welte930d0a72018-03-22 22:08:40 +01001375 var RSL_Message rsl_unused;
Harald Welte28d943e2017-11-25 15:00:50 +01001376
Harald Welte89d42e82017-12-17 16:42:41 +01001377 f_init(1);
Harald Welte28d943e2017-11-25 15:00:50 +01001378
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001379 f_ipa_tx(ts_RSL_CHAN_RQD('23'O, 23));
1380 rsl_unused := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001381 f_shutdown_helper();
Harald Welte28d943e2017-11-25 15:00:50 +01001382}
1383
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001384const CounterNameVals counternames_bts_chreq := {
1385 { "chreq:total", 0 },
1386 { "chreq:attempted_emerg", 0 },
1387 { "chreq:attempted_call", 0 },
1388 { "chreq:attempted_location_upd", 0 },
1389 { "chreq:attempted_pag", 0 },
1390 { "chreq:attempted_pdch", 0 },
1391 { "chreq:attempted_other", 0 },
1392 { "chreq:attempted_unknown", 0 },
1393 { "chreq:successful", 0 },
1394 { "chreq:successful_emerg", 0 },
1395 { "chreq:successful_call", 0 },
1396 { "chreq:successful_location_upd", 0 },
1397 { "chreq:successful_pag", 0 },
1398 { "chreq:successful_pdch", 0 },
1399 { "chreq:successful_other", 0 },
1400 { "chreq:successful_unknown", 0 },
1401 { "chreq:no_channel", 0 },
1402 { "chreq:max_delay_exceeded", 0 }
1403};
1404
1405/* verify the "chreq:*" counters */
1406private function f_chan_act_counter(OCT1 ra, charstring chreq_ctr_suffix) runs on test_CT
1407{
1408 var GsmFrameNumber fn := 23;
1409
1410 f_logp(BSCVTY, "f_chan_act_counter(" & chreq_ctr_suffix & ")");
1411
1412 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001413 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn));
1414 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001415 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1416
1417 f_ctrs_bts_add(0, "chreq:total");
1418 f_ctrs_bts_add(0, "chreq:attempted_" & chreq_ctr_suffix);
1419 f_ctrs_bts_verify();
1420
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001421 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
1422 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001423
1424 f_ctrs_bts_add(0, "chreq:successful");
1425 f_ctrs_bts_add(0, "chreq:successful_" & chreq_ctr_suffix);
1426 f_ctrs_bts_verify();
1427
1428 /* test is done, release RSL Conn Fail Ind to clean up */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001429 f_ipa_tx(ts_RSL_CONN_FAIL_IND(chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1430 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
1431 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001432 f_sleep(1.0);
1433}
1434
Harald Welte4003d112017-12-09 22:35:39 +01001435testcase TC_chan_act_counter() runs on test_CT {
1436 var BSSAP_N_UNITDATA_ind ud_ind;
1437 var integer chreq_total;
Harald Welte930d0a72018-03-22 22:08:40 +01001438 var RSL_Message rsl_unused;
Harald Welte4003d112017-12-09 22:35:39 +01001439
Harald Welte89d42e82017-12-17 16:42:41 +01001440 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001441
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001442 f_vty_allow_emerg_bts(true, 0);
1443
1444 f_ctrs_bts_init(1, counternames_bts_chreq);
1445
1446 /* emergency call: RA & 0xe0 == 0xa0 --> CHREQ_T_EMERG_CALL */
1447 f_chan_act_counter('a3'O, "emerg");
1448
1449 /* voice TCH/H: RA & 0xf0 == 0x40 --> CHREQ_T_VOICE_CALL_TCH_H */
1450 f_chan_act_counter('43'O, "call");
1451
1452 /* LU: RA & 0xf0 == 0x00 --> CHREQ_T_LOCATION_UPD */
1453 f_chan_act_counter('03'O, "location_upd");
1454
1455 /* Paging: RA & 0xf0 == 0x20 --> CHREQ_T_PAG_R_TCH_F */
1456 f_chan_act_counter('23'O, "pag");
1457 /* Paging: RA & 0xf0 == 0x30 --> CHREQ_T_PAG_R_TCH_FH */
1458 f_chan_act_counter('33'O, "pag");
1459
1460 /* LU: RA & 0xfc == 0x78 --> CHREQ_T_PDCH_TWO_PHASE */
1461 /* no PCU, so PDCH not allowed. Skip this test for now. */
1462 /* f_chan_act_counter('7b'O, "pdch"); */
1463
1464 /* LU: RA & 0xf0 == 0x10 --> CHREQ_T_SDCCH */
1465 f_chan_act_counter('13'O, "other");
Harald Welte4003d112017-12-09 22:35:39 +01001466
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001467 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001468}
1469
Harald Welteae026692017-12-09 01:03:01 +01001470/* CHAN RQD -> CHAN ACT -> CHAN ACT ACK -> RF CHAN REL */
Philipp Maier9c60a622020-07-09 15:08:46 +02001471private function f_TC_chan_act_ack_noest(OCT1 ra := '23'O) runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +01001472 var RSL_Message rx_rsl;
1473
Harald Welteae026692017-12-09 01:03:01 +01001474 /* Send CHAN RQD and wait for allocation; acknowledge it */
Philipp Maier9c60a622020-07-09 15:08:46 +02001475 var RslChannelNr chan_nr := f_chreq_act_ack(ra);
Harald Welteae026692017-12-09 01:03:01 +01001476
1477 /* expect BSC to disable the channel again if there's no RLL EST IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001478 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := T3101_MAX);
Harald Welteae026692017-12-09 01:03:01 +01001479
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001480 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001481}
1482
Philipp Maier9c60a622020-07-09 15:08:46 +02001483/* Normal variant */
1484testcase TC_chan_act_ack_noest() runs on test_CT {
Philipp Maieraf58db22020-08-12 17:24:40 +02001485 f_init(1);
Philipp Maier9c60a622020-07-09 15:08:46 +02001486 f_TC_chan_act_ack_noest();
1487}
1488
1489/* Emergency call variant */
1490testcase TC_chan_act_ack_noest_emerg() runs on test_CT {
1491 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
Philipp Maieraf58db22020-08-12 17:24:40 +02001492 f_init(1);
1493 f_vty_allow_emerg_bts(true, 0);
Philipp Maier9c60a622020-07-09 15:08:46 +02001494 f_TC_chan_act_ack_noest(ra := 'A5'O);
1495}
1496
Philipp Maier606f07d2020-08-12 17:21:58 +02001497/* Emergency call variant, but emergency calls are not allowed */
1498testcase TC_chan_rqd_emerg_deny() runs on test_CT {
1499 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
1500
1501 var RSL_Message rx_rsl;
1502 var GsmRrMessage rr;
1503
1504 f_init(1);
1505 f_vty_allow_emerg_bts(false, 0);
1506
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001507 IPA_RSL[0][0].clear;
1508 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier606f07d2020-08-12 17:21:58 +02001509
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001510 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Philipp Maier606f07d2020-08-12 17:21:58 +02001511 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
1512 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1513 setverdict(pass);
1514 } else {
1515 setverdict(fail, "immediate assignment not rejected");
1516 }
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01001517
1518 f_shutdown_helper();
Philipp Maier606f07d2020-08-12 17:21:58 +02001519}
1520
Harald Welteae026692017-12-09 01:03:01 +01001521/* Test behavior if MSC never answers to CR */
1522testcase TC_chan_act_ack_est_ind_noreply() runs on test_CT {
Harald Weltef77aef62018-01-28 15:35:42 +01001523 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
1524 var IpaStreamId sid := IPAC_PROTO_RSL_TRX0;
Harald Welteae026692017-12-09 01:03:01 +01001525 var RSL_Message rx_rsl;
Harald Weltef77aef62018-01-28 15:35:42 +01001526 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001527 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welteae026692017-12-09 01:03:01 +01001528
Harald Welte89d42e82017-12-17 16:42:41 +01001529 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001530
1531 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001532 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001533
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001534 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welteae026692017-12-09 01:03:01 +01001535
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001536 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload)));
Harald Welteae026692017-12-09 01:03:01 +01001537
1538 /* expect BSC to disable the channel again if there's no response from MSC */
Harald Weltef77aef62018-01-28 15:35:42 +01001539 /* MS waits 20s (T3210) at LU; 10s (T3230) at CM SERV REQ and 5s (T3220) AT detach */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001540 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001541 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001542}
1543
1544/* Test behavior if MSC answers with CREF to CR */
1545testcase TC_chan_act_ack_est_ind_refused() runs on test_CT {
1546 var BSSAP_N_CONNECT_ind rx_c_ind;
1547 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001548 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welteae026692017-12-09 01:03:01 +01001549
Harald Welte89d42e82017-12-17 16:42:41 +01001550 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001551
1552 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001553 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001554
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001555 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welteae026692017-12-09 01:03:01 +01001556
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001557 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Harald Welteae026692017-12-09 01:03:01 +01001558 BSSAP.send(ts_BSSAP_DISC_req(rx_c_ind.connectionId, 0));
1559
1560 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001561 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001562 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001563}
1564
Harald Welte618ef642017-12-14 14:58:20 +01001565/* CHAN RQD -> CHAN ACT -> CHAN ACT NACK -> RF CHAN REL */
1566testcase TC_chan_act_nack() runs on test_CT {
1567 var RSL_Message rx_rsl;
1568 var integer chact_nack;
1569
Harald Welte89d42e82017-12-17 16:42:41 +01001570 f_init(1);
Harald Welte618ef642017-12-14 14:58:20 +01001571
1572 chact_nack := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack");
1573
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001574 f_ipa_tx(ts_RSL_CHAN_RQD('33'O, 33));
1575 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Harald Welte618ef642017-12-14 14:58:20 +01001576 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1577
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001578 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte618ef642017-12-14 14:58:20 +01001579
1580 /* wait for some time to hope the NACK arrives before the CTRL GET below */
1581 f_sleep(0.5);
1582
1583 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack", chact_nack+1);
1584
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001585 f_shutdown_helper();
Harald Welte618ef642017-12-14 14:58:20 +01001586}
1587
Harald Welte799c97b2017-12-14 17:50:30 +01001588/* Test for channel exhaustion due to RACH overload */
1589testcase TC_chan_exhaustion() runs on test_CT {
1590 var ASP_RSL_Unitdata rsl_ud;
1591 var integer i;
1592 var integer chreq_total, chreq_nochan;
1593
Harald Welte89d42e82017-12-17 16:42:41 +01001594 f_init(1);
Harald Welte799c97b2017-12-14 17:50:30 +01001595
1596 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
1597 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
1598
Neels Hofmeyr85fa37f2021-10-06 13:50:38 +02001599 /* GSM 44.018 Table 9.1.8.2:
Pau Espin Pedrolfe200d72018-12-10 12:41:04 +01001600 * RA = '33'O -> Establishment cause = 0011xxxx (MS dual rate capable and asks for "TCH/H or TCH/F").
1601 * With current setup, expect 4xSDCCH + 4xTCH/F + 1xTCH/H to succeed */
Philipp Maiercb6cc482018-03-26 13:08:00 +02001602 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 +01001603 var RslChannelNr chan_nr := f_chreq_act_ack('33'O, i);
Harald Welte799c97b2017-12-14 17:50:30 +01001604 }
1605
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001606 IPA_RSL[0][0].clear;
Harald Welte799c97b2017-12-14 17:50:30 +01001607
Harald Weltedd8cbf32018-01-28 12:07:52 +01001608 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001609 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
Harald Welte799c97b2017-12-14 17:50:30 +01001610
1611 /* now expect additional channel activations to fail */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001612 f_ipa_tx(ts_RSL_CHAN_RQD('42'O, 42));
Harald Welte799c97b2017-12-14 17:50:30 +01001613
1614 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001615 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV))) {
Harald Welte799c97b2017-12-14 17:50:30 +01001616 setverdict(fail, "Received CHAN ACT ACK without resources?!?");
1617 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001618 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) -> value rsl_ud {
Harald Welte799c97b2017-12-14 17:50:30 +01001619 var GsmRrMessage rr;
1620 /* match on IMM ASS REJ */
1621 rr := dec_GsmRrMessage(rsl_ud.rsl.ies[1].body.full_imm_ass_info.payload);
1622 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1623 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001624 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS+1);
Harald Welte799c97b2017-12-14 17:50:30 +01001625 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel",
1626 chreq_nochan+1);
1627 setverdict(pass);
1628 } else {
1629 repeat;
1630 }
1631 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001632 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte799c97b2017-12-14 17:50:30 +01001633 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001634 f_shutdown_helper();
Harald Welte799c97b2017-12-14 17:50:30 +01001635}
1636
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001637/* Test channel deactivation due to silence from MS */
1638testcase TC_chan_deact_silence() runs on test_CT {
1639 var RslChannelNr chan_nr;
1640
1641 f_init(1);
1642
1643 /* Request for a dedicated channel */
1644 chan_nr := f_chreq_act_ack('23'O);
1645
1646 /* Wait some time until the channel is released */
1647 f_sleep(2.0);
1648
1649 /* Expect CHANnel RELease */
1650 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001651 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001652 log("Received CHANnel RELease");
1653 setverdict(pass);
1654 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001655 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001656 /* See OS#3709, OsmoBSC should not send Immediate
1657 * Assignment Reject since a dedicated channel was
1658 * already allocated, and Immediate Assignment was
1659 * already sent. */
1660 setverdict(fail, "Unexpected Immediate Assignment!");
1661 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001662 [] IPA_RSL[0][0].receive {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001663 setverdict(fail, "Unexpected RSL message!");
1664 }
1665 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001666 f_shutdown_helper();
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001667}
1668
Harald Weltecfe2c962017-12-15 12:09:32 +01001669/***********************************************************************
1670 * Assignment Testing
1671 ***********************************************************************/
1672
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02001673/* Verify that the BSC refuses any BSSAP connection from the MSC (They are all BSC->MSC direction,
1674 * except for the inter-BSC handover, MT side) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001675testcase TC_outbound_connect(integer bssap_idx := 0) runs on test_CT {
Harald Welte89d42e82017-12-17 16:42:41 +01001676 f_init(1);
Harald Weltecfe2c962017-12-15 12:09:32 +01001677
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001678 BSSAP.send(ts_BSSAP_CONNECT_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
1679 2342, ts_BSSMAP_AssignmentReq));
Harald Weltecfe2c962017-12-15 12:09:32 +01001680 BSSAP.receive(tr_BSSAP_DISC_ind(2342, ?, ?));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001681 f_shutdown_helper();
Harald Weltecfe2c962017-12-15 12:09:32 +01001682}
1683
Harald Welte16a4adf2017-12-14 18:54:01 +01001684/* Test behavior if MSC answers with CREF to CR */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001685testcase TC_assignment_cic_only(integer bssap_idx := 0) runs on test_CT {
Harald Welte16a4adf2017-12-14 18:54:01 +01001686 var BSSAP_N_CONNECT_ind rx_c_ind;
1687 var RSL_Message rx_rsl;
1688 var DchanTuple dt;
1689
Harald Welte89d42e82017-12-17 16:42:41 +01001690 f_init(1);
Harald Welte16a4adf2017-12-14 18:54:01 +01001691
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001692 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001693 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte17b27da2018-05-25 20:33:53 +02001694 /* send assignment without AoIP IEs */
1695 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(ts_BSSMAP_IE_CIC(0, 1))));
1696 } else {
1697 /* Send assignmetn without CIC in IPA case */
1698 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
1699 valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
1700 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(omit, tla)));
1701 }
Harald Welte16a4adf2017-12-14 18:54:01 +01001702 alt {
1703 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1704 setverdict(fail, "AoIP BSC cannot accept ASSIGNMENT without AoIP Transport IE");
1705 }
Harald Welte235ebf12017-12-15 14:18:16 +01001706 /* TODO: Actually expect GSM0808_CAUSE_REQ_A_IF_TYPE_NOT_SUPP */
Harald Welte16a4adf2017-12-14 18:54:01 +01001707 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1708 setverdict(pass);
1709 }
1710 [] BSSAP.receive { repeat; }
1711 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001712 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001713 f_shutdown_helper();
Harald Welte16a4adf2017-12-14 18:54:01 +01001714}
1715
Harald Welteed848512018-05-24 22:27:58 +02001716/* generate an assignment request for either AoIP or SCCPlite */
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001717function 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 +02001718 var PDU_BSSAP ass_cmd;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001719 var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001720 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welteed848512018-05-24 22:27:58 +02001721 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001722 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001723 if (osmux_enabled) {
1724 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla, osmux_cid));
1725 } else {
1726 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla));
1727 }
Harald Welteed848512018-05-24 22:27:58 +02001728 } else {
1729 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrol096d73d2019-06-06 12:49:17 +02001730 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(cic, omit));
Harald Welteed848512018-05-24 22:27:58 +02001731 }
1732 return ass_cmd;
1733}
1734
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02001735function f_gen_handover_req(integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4",
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001736 template (value) BSSMAP_IE_CellIdentifier cell_id_source := ts_CellID_LAC_CI(1, 1),
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001737 template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit,
1738 template (omit) TestHdlrEncrParams enc := omit) return PDU_BSSAP {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001739 var PDU_BSSAP ho_req;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001740
1741 var BSSMAP_IE_EncryptionInformation encryptionInformation :=
1742 valueof(ts_BSSMAP_IE_EncrInfo('0000000000000000'O,'01'O));
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03001743 var template (omit) BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := omit;
1744 var template (omit) BSSMAP_IE_KC128 kc128 := omit;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001745 if (ispresent(enc)) {
1746 var TestHdlrEncrParams v_enc := valueof(enc);
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01001747 encryptionInformation := valueof(ts_BSSMAP_IE_EncrInfo(v_enc.enc_key, v_enc.enc_alg_permitted));
1748 if (ispresent(v_enc.enc_alg_chosen)) {
1749 chosenEncryptionAlgorithm := valueof(
1750 ts_BSSMAP_IE_ChosenEncryptionAlgorithm(int2oct(enum2int(
1751 f_cipher_mode_bssmap_to_rsl(v_enc.enc_alg_chosen)), 1)));
1752 }
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001753 if (ispresent(v_enc.enc_kc128)) {
1754 kc128 := ts_BSSMAP_IE_Kc128(v_enc.enc_kc128);
1755 }
1756 }
1757
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001758 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001759 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001760 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001761 ho_req := valueof(ts_BSSMAP_HandoverRequest(omit, tla,
1762 cell_id_source := cell_id_source,
1763 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001764 encryptionInformation := encryptionInformation,
1765 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
Neels Hofmeyr9fe13202022-03-04 00:05:43 +01001766 kC128 := kc128,
1767 /* on AoIP, allow "all" codecs (until we add more concise
1768 * tests) */
1769 codecList := ts_BSSMAP_IE_CodecList(
1770 {ts_CodecAMR_F, ts_CodecAMR_H,
1771 ts_CodecEFR, ts_CodecFR, ts_CodecHR})));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001772 } else {
1773 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001774 ho_req := valueof(ts_BSSMAP_HandoverRequest(cic, omit,
1775 cell_id_source := cell_id_source,
1776 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001777 encryptionInformation := encryptionInformation,
1778 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
1779 kC128 := kc128));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001780 }
1781 return ho_req;
1782}
1783
Harald Welteed848512018-05-24 22:27:58 +02001784/* generate an assignment complete template for either AoIP or SCCPlite */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001785function f_gen_exp_compl(integer bssap_idx := 0)
1786runs on MSC_ConnHdlr return template PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001787 var template PDU_BSSAP exp_compl;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001788 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001789 var template BSSMAP_IE_Osmo_OsmuxCID exp_osmux_cid := omit;
1790 if (g_pars.use_osmux_cn) {
1791 var template (present) INT1 exp_cid := ?;
1792 if (isbound(g_media.mgcp_conn[0].local_osmux_cid) and isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1793 exp_cid := (g_media.mgcp_conn[0].local_osmux_cid, g_media.mgcp_conn[1].local_osmux_cid);
1794 } else if (isbound(g_media.mgcp_conn[0].local_osmux_cid)) {
1795 exp_cid := g_media.mgcp_conn[0].local_osmux_cid;
1796 } else if (isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1797 exp_cid := g_media.mgcp_conn[1].local_osmux_cid;
1798 }
1799 exp_osmux_cid := tr_OsmuxCID(exp_cid);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001800 }
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001801 exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, exp_osmux_cid);
Harald Welteed848512018-05-24 22:27:58 +02001802 } else {
1803 /* CIC is optional "*" as the MSC allocated it */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001804 exp_compl := tr_BSSMAP_AssignmentComplete(*, omit, omit);
Harald Welteed848512018-05-24 22:27:58 +02001805 }
1806 return exp_compl;
1807}
1808
Harald Welte235ebf12017-12-15 14:18:16 +01001809/* Run everything required up to sending a caller-specified assignment command and expect response */
1810function f_assignment_exp(PDU_BSSAP ass_cmd, template PDU_BSSAP exp, charstring fail_text)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001811runs on test_CT return DchanTuple {
Harald Welte235ebf12017-12-15 14:18:16 +01001812 var BSSAP_N_CONNECT_ind rx_c_ind;
1813 var RSL_Message rx_rsl;
1814 var DchanTuple dt;
1815
Harald Welte89d42e82017-12-17 16:42:41 +01001816 f_init(1);
Harald Welte235ebf12017-12-15 14:18:16 +01001817
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001818 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte235ebf12017-12-15 14:18:16 +01001819 /* send assignment without AoIP IEs */
1820 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
1821 alt {
1822 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1823 if (ischosen(exp.pdu.bssmap.assignmentComplete)) {
1824 setverdict(pass);
1825 } else {
1826 setverdict(fail, fail_text);
1827 }
1828 }
1829 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1830 if (ischosen(exp.pdu.bssmap.assignmentFailure)) {
1831 setverdict(pass);
1832 } else {
1833 setverdict(fail, fail_text);
1834 }
1835 }
1836 [] BSSAP.receive { repeat; }
1837 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001838 return dt;
Harald Welte235ebf12017-12-15 14:18:16 +01001839}
1840testcase TC_assignment_csd() runs on test_CT {
1841 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001842 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001843 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
1844 //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 +01001845 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for CSD");
1846 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001847 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001848}
1849
1850testcase TC_assignment_ctm() runs on test_CT {
1851 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001852 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001853 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
1854 //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 +01001855 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
1856 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001857 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001858}
1859
Harald Welte4003d112017-12-09 22:35:39 +01001860type record DchanTuple {
1861 integer sccp_conn_id,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001862 RslChannelNr rsl_chan_nr,
1863 BtsTrxIdx idx
Harald Weltea5d2ab22017-12-09 14:21:42 +01001864}
1865
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +02001866type record of DchanTuple DchanTuples;
1867
Harald Welted6939652017-12-13 21:02:46 +01001868/* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001869private function f_chreq_act_ack(OCT1 ra := '23'O,
1870 GsmFrameNumber fn := 23,
1871 BtsTrxIdx idx := {0, 0})
Harald Welted6939652017-12-13 21:02:46 +01001872runs on test_CT return RslChannelNr {
1873 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001874 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
1875 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Harald Welted6939652017-12-13 21:02:46 +01001876 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001877 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10), idx);
1878 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Harald Welted6939652017-12-13 21:02:46 +01001879 return chan_nr;
1880}
1881
Harald Welte4003d112017-12-09 22:35:39 +01001882/* helper function to establish a dedicated channel via BTS and MSC */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001883function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1884 BtsTrxIdx idx := {0, 0})
Harald Welte4003d112017-12-09 22:35:39 +01001885runs on test_CT return DchanTuple {
1886 var BSSAP_N_CONNECT_ind rx_c_ind;
Harald Welte4003d112017-12-09 22:35:39 +01001887 var DchanTuple dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001888
Harald Welte4003d112017-12-09 22:35:39 +01001889 /* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001890 dt.rsl_chan_nr := f_chreq_act_ack(ra, fn, idx);
Harald Welte4003d112017-12-09 22:35:39 +01001891
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001892 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 +01001893
1894 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1895 dt.sccp_conn_id := rx_c_ind.connectionId;
1896 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1897
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001898 dt.idx := idx;
Harald Welte4003d112017-12-09 22:35:39 +01001899 return dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001900}
1901
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001902/* 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 +06001903function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1904 BtsTrxIdx idx := {0, 0})
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001905runs on test_CT return DchanTuple {
1906 var BSSAP_N_CONNECT_ind rx_c_ind;
1907 var DchanTuple dt;
1908
1909 /* Send CHAN RQD */
1910 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001911 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001912
1913 /* The dyn TS first deactivates PDCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001914 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 +02001915 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001916 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001917
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001918 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001919 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1920
1921 /* Now activates the signalling channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001922 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10), idx);
1923 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001924
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001925 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 +02001926
1927 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1928 dt.sccp_conn_id := rx_c_ind.connectionId;
1929 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1930
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001931 dt.idx := idx;
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001932 return dt;
1933}
1934
Harald Welte641fcbe2018-06-14 10:58:35 +02001935/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001936private function f_exp_chan_rel_and_clear(DchanTuple dt)
1937runs on test_CT {
Harald Welte641fcbe2018-06-14 10:58:35 +02001938 var RSL_Message rx_rsl;
1939 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001940 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 +02001941 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001942 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), dt.idx);
Harald Welte641fcbe2018-06-14 10:58:35 +02001943
1944 /* expect Clear Complete from BSC */
1945 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
1946
1947 /* MSC disconnects as instructed. */
1948 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
1949}
1950
Harald Welte4003d112017-12-09 22:35:39 +01001951/* Test behavior of channel release after unilateral RLL REL IND (DISC from MS) */
1952testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001953 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01001954 var DchanTuple dt;
Harald Welte96c94412017-12-09 03:12:45 +01001955
Harald Welte89d42e82017-12-17 16:42:41 +01001956 f_init(1);
Harald Welte96c94412017-12-09 03:12:45 +01001957
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001958 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01001959
1960 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001961 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Harald Welte4003d112017-12-09 22:35:39 +01001962
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001963 /* expect Clear Request on MSC side */
1964 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
1965
1966 /* Instruct BSC to clear channel */
1967 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
1968 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
1969
Harald Welte4003d112017-12-09 22:35:39 +01001970 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001971 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001972
1973 /* wait for SCCP emulation to do its job */
1974 f_sleep(1.0);
Harald Welte4003d112017-12-09 22:35:39 +01001975
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001976 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001977}
1978
1979/* Test behavior of channel release after CONN FAIL IND from BTS */
1980testcase TC_chan_rel_conn_fail() runs on test_CT {
1981 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01001982 var DchanTuple dt;
1983
Harald Welte89d42e82017-12-17 16:42:41 +01001984 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001985
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01001986 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01001987
Vadim Yanitskiy01d0a902022-12-14 22:41:42 +07001988 /* Sending CONN FAIL IND immediately may trigger a race condition.
1989 * Give the BSC some time to process a new SCCP connection (OS#5823). */
1990 f_sleep(0.2);
1991
Harald Welte4003d112017-12-09 22:35:39 +01001992 /* simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001993 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte4003d112017-12-09 22:35:39 +01001994 /* TODO: different cause values? */
1995
Harald Welte4003d112017-12-09 22:35:39 +01001996 /* expect Clear Request from BSC */
1997 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
1998
1999 /* Instruct BSC to clear channel */
2000 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
2001 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2002
Harald Welte6ff76ea2018-01-28 13:08:01 +01002003 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002004 f_exp_chan_rel_and_clear(dt);
Harald Welte4003d112017-12-09 22:35:39 +01002005
2006 /* wait for SCCP emulation to do its job */
2007 f_sleep(1.0);
2008
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002009 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002010}
2011
Harald Welte99f3ca02018-06-14 13:40:29 +02002012/* Test behavior of early CONN FAIL IND from BTS (before EST IND!) */
2013/* See also https://www.osmocom.org/issues/3182 */
2014testcase TC_early_conn_fail() runs on test_CT {
2015 var RSL_Message rx_rsl;
2016 var DchanTuple dt;
2017
2018 f_init(1);
2019
2020 /* BTS->BSC: Send CHAN RQD and wait for allocation; acknowledge it */
Harald Weltec46ea3c2020-10-10 18:46:12 +02002021 dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_ra_cs(), 23);
Harald Welte99f3ca02018-06-14 13:40:29 +02002022
2023 /* BTS->BSC: simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002024 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002025
2026 /* BTS->BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002027 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002028
2029 /* BTS<-BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002030 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002031
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002032 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002033}
2034
2035/* Test behavior of late CONN FAIL IND from BTS (ater REL IND!) */
2036/* See also https://www.osmocom.org/issues/3182 */
2037testcase TC_late_conn_fail() runs on test_CT {
2038 var RSL_Message rx_rsl;
2039 var DchanTuple dt;
2040
2041 f_init(1);
2042
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002043 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99f3ca02018-06-14 13:40:29 +02002044
2045 /* BSC<-MSC: Instruct BSC to clear connection */
2046 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(0)));
2047
2048 /* BTS->BSC: expect BSC to deactivate SACCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002049 rx_rsl := f_exp_ipa_rx(tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002050
2051 /* BTS->BSC: simulate a late CONN FAIL IND from BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002052 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002053
2054 /* BTS<-BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002055 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002056 /* BTS->BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002057 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002058
2059 /* BSC->MSC: expect Clear Complete from BSC */
2060 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2061
2062 /* BSC<-MSC: MSC disconnects as requested. */
2063 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2064
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002065 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002066}
2067
Oliver Smithaf03bef2021-08-24 15:34:51 +02002068private function f_TC_stats_conn_fail(charstring id) runs on MSC_ConnHdlr {
2069 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
2070 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2071
2072 f_statsd_reset();
2073
2074 /* Establish SDCCH */
2075 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
2076 f_establish_fully(ass_cmd, exp_fail);
2077
2078 /* Expect stats to be 0 */
2079 var StatsDExpects expect := {
2080 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
2081 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
2082 };
2083 f_statsd_expect(expect);
2084
2085 /* Simulate CONN FAIL IND on SDCCH */
2086 RSL.send(ts_ASP_RSL_UD(
2087 ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
2088 IPAC_PROTO_RSL_TRX0));
2089
Neels Hofmeyr58be48a2021-09-07 18:39:21 +02002090 f_sleep(1.0);
2091
Oliver Smithaf03bef2021-08-24 15:34:51 +02002092 /* Expect stats to be 1 */
2093 expect := {
2094 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
2095 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
2096 };
2097 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002098 BSSAP.receive(tr_BSSMAP_ClearRequest);
2099 f_perform_clear();
Oliver Smithaf03bef2021-08-24 15:34:51 +02002100}
2101testcase TC_stats_conn_fail() runs on test_CT {
2102 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2103 var MSC_ConnHdlr vc_conn;
2104
2105 f_init(1, true);
2106 f_sleep(1.0);
2107
2108 vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
2109 vc_conn.done;
2110
2111 f_shutdown_helper();
2112}
2113
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002114function f_expect_chan_rel(RslChannelNr rsl_chan_nr,
2115 BtsTrxIdx idx := {0, 0},
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002116 boolean expect_deact_sacch := true,
2117 boolean expect_rr_chan_rel := true,
2118 boolean expect_rll_rel_req := true,
Harald Welte99787102019-02-04 10:41:36 +01002119 boolean handle_rll_rel := true,
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002120 template CellSelIndValue expect_cells := omit,
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002121 template (present) RR_Cause expect_rr_cause := ?
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002122 ) runs on test_CT {
Harald Welte91d54a52018-01-28 15:35:07 +01002123
2124 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002125 var boolean got_deact_sacch := false;
2126 var boolean got_rr_chan_rel := false;
2127 var boolean got_rll_rel_req := false;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002128 var ASP_RSL_Unitdata ud;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002129 var RSL_IE_Body l3_ie;
2130 var PDU_ML3_NW_MS l3;
2131 var RR_Cause got_cause;
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002132 log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
2133 " expect_rll_rel_req=", expect_rll_rel_req);
Harald Welte91d54a52018-01-28 15:35:07 +01002134 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002135 [] 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 +01002136 got_deact_sacch := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002137 repeat;
2138 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002139 [] 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 +01002140 got_rr_chan_rel := true;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002141
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002142 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2143 setverdict(fail, "cannot find L3");
2144 mtc.stop;
2145 }
2146 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2147
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002148 if (not istemplatekind(expect_cells, "omit")) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002149 var CellSelIndValue cells := dec_CellSelIndValue(
2150 l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
2151
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002152 log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
2153 if (match(cells, expect_cells)) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002154 setverdict(pass);
2155 } else {
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002156 log("EXPECTED CELLS: ", expect_cells);
2157 setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002158 }
2159 }
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002160
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002161 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2162 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2163 if (match(got_cause, expect_rr_cause)) {
2164 setverdict(pass);
2165 } else {
2166 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2167 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002168 }
Harald Welte99787102019-02-04 10:41:36 +01002169 repeat;
2170 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002171 [] 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 +01002172 got_rll_rel_req := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002173 /* FIXME: Why are we getting this for LinkID SACCH? */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002174 if (handle_rll_rel) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002175 f_ipa_tx(ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002176 }
Harald Welte91d54a52018-01-28 15:35:07 +01002177 repeat;
2178 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002179 [] 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 +01002180 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002181 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
Harald Welte91d54a52018-01-28 15:35:07 +01002182 }
2183 /* ignore any user data */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002184 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002185 repeat;
2186 }
2187 }
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002188
2189 log("f_expect_chan_rel() summary: got_deact_sacch=", got_deact_sacch, " got_rr_chan_rel=", got_rr_chan_rel,
2190 " got_rll_rel_req=", got_rll_rel_req);
2191
2192 if (expect_deact_sacch != got_deact_sacch) {
2193 setverdict(fail, "f_expect_chan_rel(): expect_deact_sacch=", expect_deact_sacch, " got_deact_sacch=", got_deact_sacch);
2194 }
2195 if (expect_rr_chan_rel != got_rr_chan_rel) {
2196 setverdict(fail, "f_expect_chan_rel(): expect_rr_chan_rel=", expect_rr_chan_rel, " got_rr_chan_rel=", got_rr_chan_rel);
2197 }
2198 if (expect_rll_rel_req != got_rll_rel_req) {
2199 setverdict(fail, "f_expect_chan_rel(): expect_rll_rel_req=", expect_rll_rel_req, " got_rll_rel_req=", got_rll_rel_req);
2200 }
Harald Welte91d54a52018-01-28 15:35:07 +01002201}
2202
Harald Welte4003d112017-12-09 22:35:39 +01002203/* Test behavior of channel release after hard Clear Command from MSC */
2204testcase TC_chan_rel_hard_clear() runs on test_CT {
2205 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002206 var DchanTuple dt;
Harald Welte4003d112017-12-09 22:35:39 +01002207
Harald Welte89d42e82017-12-17 16:42:41 +01002208 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002209
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002210 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte4003d112017-12-09 22:35:39 +01002211
2212 /* Instruct BSC to clear channel */
2213 var BssmapCause cause := 0;
2214 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2215
2216 /* expect Clear Complete from BSC on A */
2217 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2218 /* release the SCCP connection */
2219 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2220 }
2221
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002222 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002223 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002224}
2225
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002226function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
2227 var BSSAP_N_DATA_ind rx_di;
2228 var DchanTuple dt;
2229
2230 f_init(1);
2231
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002232 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002233 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2234 /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
2235 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
2236
2237 /* Instruct BSC to clear channel */
2238 var BssmapCause cause := 0;
2239 if (tx_csfb_ind) {
2240 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2241 } else {
2242 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2243 }
2244
2245 /* expect Clear Complete from BSC on A */
2246 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2247 /* release the SCCP connection */
2248 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2249 }
2250
2251 /* 1 neighbor is added by default in osmo-bts.cfg and
2252 SystemInformationConfig_default, use that: */
2253 var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
2254
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002255 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 +02002256 f_shutdown_helper();
2257}
2258
2259/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
2260 from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
2261 PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2262 EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
2263 Indicator or not shouldn't matter at all. */
2264testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
2265 f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
2266}
2267
2268/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
2269 MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
2270 Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2271 EUTRAN neighbor list sent later on by BSC in RR Channel. */
2272testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
2273 f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
2274}
2275
2276/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
2277 MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
2278 Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
2279 CSFB Indicator should not be used anymore, and hence, there should be no
2280 EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
2281 Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
Harald Welte99787102019-02-04 10:41:36 +01002282testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
2283 var BSSAP_N_DATA_ind rx_di;
2284 var DchanTuple dt;
2285
2286 f_init(1);
2287
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002288 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte99787102019-02-04 10:41:36 +01002289
2290 /* Instruct BSC to clear channel */
2291 var BssmapCause cause := 0;
2292 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2293
2294 /* expect Clear Complete from BSC on A */
2295 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2296 /* release the SCCP connection */
2297 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2298 }
2299
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002300 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002301 f_shutdown_helper();
Harald Welte99787102019-02-04 10:41:36 +01002302}
2303
Harald Welted8c36cd2017-12-09 23:05:31 +01002304/* Test behavior of channel release after hard RLSD from MSC */
2305testcase TC_chan_rel_hard_rlsd() runs on test_CT {
Harald Welted8c36cd2017-12-09 23:05:31 +01002306 var DchanTuple dt;
Harald Welted8c36cd2017-12-09 23:05:31 +01002307
Harald Welte89d42e82017-12-17 16:42:41 +01002308 f_init(1);
Harald Welted8c36cd2017-12-09 23:05:31 +01002309
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002310 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welted8c36cd2017-12-09 23:05:31 +01002311
2312 /* release the SCCP connection */
2313 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2314
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002315 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002316 f_shutdown_helper();
Harald Welted8c36cd2017-12-09 23:05:31 +01002317}
2318
Harald Welte550daf92018-06-11 19:22:13 +02002319/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
2320testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
2321 var DchanTuple dt;
2322
2323 f_init(1);
2324
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002325 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte550daf92018-06-11 19:22:13 +02002326
2327 /* release the SCCP connection */
2328 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2329
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002330 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002331 f_shutdown_helper();
Harald Welte550daf92018-06-11 19:22:13 +02002332}
2333
Harald Welte85804d42017-12-10 14:11:58 +01002334/* Test behavior of channel release after BSSMAP RESET from MSC */
2335testcase TC_chan_rel_a_reset() runs on test_CT {
Harald Welte85804d42017-12-10 14:11:58 +01002336 var DchanTuple dt;
Harald Welte85804d42017-12-10 14:11:58 +01002337
Harald Welte89d42e82017-12-17 16:42:41 +01002338 f_init(1);
Harald Welte85804d42017-12-10 14:11:58 +01002339
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002340 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Harald Welte85804d42017-12-10 14:11:58 +01002341
2342 /* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002343 IPA_RSL[0][0].clear;
Harald Welte85804d42017-12-10 14:11:58 +01002344
2345 /* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002346 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 +01002347 interleave {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002348 [] 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 +01002349 [] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
2350 }
2351
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002352 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002353 f_shutdown_helper();
Harald Welte85804d42017-12-10 14:11:58 +01002354}
2355
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002356/* Verify T(iar) triggers and releases the channel */
2357testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
2358 var DchanTuple dt;
2359
2360 /* Set T(iar) in BSC low enough that it will trigger before other side
2361 has time to keep alive with a T(ias). Keep recommended ratio of
2362 T(iar) >= T(ias)*2 */
2363 g_bsc_sccp_timer_ias := 2;
2364 g_bsc_sccp_timer_iar := 5;
2365
2366 f_init(1);
2367
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002368 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002369 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002370 f_shutdown_helper();
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002371}
2372
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002373private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause,
2374 template (present) RR_Cause expect_rr_cause)
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002375runs on test_CT
2376{
2377 var DchanTuple dt;
2378
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002379 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002380 var BssmapCause cause := 0;
2381 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
2382 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2383 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2384 }
2385
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002386 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 +02002387}
2388
2389/* Test that Clear Command cause codes affect the RR Channel Release cause code */
2390testcase TC_chan_rel_rr_cause() runs on test_CT {
2391 f_init(1);
2392
2393 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
2394 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
2395 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
2396 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
2397 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
2398 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
Vadim Yanitskiye18aebb2021-01-03 13:10:43 +01002399
2400 f_shutdown_helper();
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002401}
2402
Harald Welte5cd20ed2017-12-13 21:03:20 +01002403/* Test behavior if RSL EST IND for non-active channel */
2404testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
2405 timer T := 2.0;
2406
Harald Welte89d42e82017-12-17 16:42:41 +01002407 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002408
Harald Welte5cd20ed2017-12-13 21:03:20 +01002409 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002410 var octetstring l3_payload := gen_l3_valid_payload();
2411 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002412
2413 T.start;
2414 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002415 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002416 setverdict(fail, "MSC received COMPL L3 for non-active lchan");
2417 }
2418 [] BSSAP.receive {}
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002419 [] IPA_RSL[0][0].receive {}
Harald Welte5cd20ed2017-12-13 21:03:20 +01002420 [] T.timeout {}
2421 }
2422
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002423 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002424}
2425
2426/* Test behavior if RSL EST IND for invalid SAPI */
2427testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
2428 var RslChannelNr chan_nr;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002429 var octetstring l3_payload;
Harald Welte5cd20ed2017-12-13 21:03:20 +01002430
Harald Welte89d42e82017-12-17 16:42:41 +01002431 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002432
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002433 chan_nr := f_chreq_act_ack();
2434 l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002435
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002436 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002437
2438 timer T := 2.0;
2439 T.start;
2440 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002441 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002442 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
2443 }
2444 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002445 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002446 [] T.timeout {}
2447 }
2448
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002449 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002450}
2451
2452/* Test behavior if RSL EST IND for invalid SAPI */
2453testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
2454 timer T := 2.0;
2455
Harald Welte89d42e82017-12-17 16:42:41 +01002456 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002457
2458 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002459 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002460
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002461 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002462
2463 T.start;
2464 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002465 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002466 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
2467 }
2468 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002469 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002470 [] T.timeout {}
2471 }
2472
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002473 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002474}
2475
2476/* Test behavior if RSL EST IND for invalid SACCH */
2477testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
2478 timer T := 2.0;
2479
Harald Welte89d42e82017-12-17 16:42:41 +01002480 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002481
2482 var RslChannelNr chan_nr := f_chreq_act_ack();
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002483 var octetstring l3_payload := gen_l3_valid_payload();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002484
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002485 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3_payload));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002486
2487 T.start;
2488 alt {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002489 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
Harald Welte5cd20ed2017-12-13 21:03:20 +01002490 setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
2491 }
2492 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002493 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002494 [] T.timeout {}
2495 }
2496
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002497 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002498}
2499
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002500/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
2501private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
2502 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
2503 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2504
2505 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
2506 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
2507
2508 f_establish_fully(ass_cmd, exp_compl);
2509
2510 /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
2511 RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
2512 /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
2513 BSSAP.receive(PDU_BSSAP:{
2514 discriminator := '1'B,
2515 spare := '0000000'B,
2516 dlci := 'C3'O,
2517 lengthIndicator := ?,
2518 pdu := { dtap := '0904'O }
2519 });
2520
2521 /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
2522 for (var integer i := 0; i < 32; i := i + 1) {
2523 var octetstring l3 := '09'O & f_rnd_octstring(14);
2524 var template (value) RslLinkId link_id;
2525 var template (value) OCT1 dlci;
2526
2527 if (i mod 2 == 0) {
2528 /* SAPI0 on FACCH or SDCCH */
2529 link_id := ts_RslLinkID_DCCH(0);
2530 dlci := '80'O;
2531 } else {
2532 /* SAPI3 on SACCH */
2533 link_id := ts_RslLinkID_SACCH(3);
2534 dlci := 'C3'O;
2535 }
2536
2537 /* Send MO message: RSL -> BSSAP */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002538 f_mo_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002539 /* Send MT message: BSSAP -> RSL */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002540 f_mt_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002541 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002542 f_perform_clear();
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002543}
2544testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
2545 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2546 var MSC_ConnHdlr vc_conn;
2547
2548 f_init(1, true);
2549 f_sleep(1.0);
2550
2551 vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
2552 vc_conn.done;
2553
2554 f_shutdown_helper();
2555}
2556
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002557private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002558 template (present) myBSSMAP_Cause cause := ?,
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002559 template (present) BIT2 cc := ?,
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002560 float T_val := 2.0)
2561runs on test_CT {
2562 var BSSAP_N_DATA_ind rx_di;
2563 timer T;
2564
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002565 var template (present) BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
2566 var template (present) PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002567
2568 T.start(T_val);
2569 alt {
2570 [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
2571 var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
2572 if (not match(rx_cause, tr_cause)) {
2573 setverdict(fail, "Rx unexpected Cause IE: ",
2574 rx_cause, " vs expected ", tr_cause);
2575 }
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002576
2577 /* Who ever on the earth decided to define this field as two separate bits?!? */
2578 var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
2579 & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
2580 if (not match(rx_cc, cc)) {
2581 setverdict(fail, "Rx unexpected Control Channel type: ",
2582 rx_cc, " vs expected ", cc);
2583 }
2584
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002585 setverdict(pass);
2586 }
2587 [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
2588 setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
2589 }
2590 [] T.timeout {
2591 setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
2592 }
2593 }
2594}
2595
2596/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
2597testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002598 var RSL_Message rx_rsl;
2599 var DchanTuple dt;
2600
2601 f_init(1);
2602
2603 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002604 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002605
2606 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002607 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 +07002608 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002609 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 +07002610
2611 /* MS sends unexpected RELease INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002612 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002613 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2614 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
2615
2616 /* Clean up the connection */
2617 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002618 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002619
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002620 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002621}
2622
2623/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
2624testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002625 var RSL_Message rx_rsl;
2626 var DchanTuple dt;
2627
2628 f_init(1);
2629
2630 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002631 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002632
2633 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002634 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 +07002635 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002636 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 +07002637
2638 /* BTS sends unexpected ERROR INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002639 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002640 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2641 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
2642
2643 /* Clean up the connection */
2644 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002645 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002646
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002647 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002648}
2649
2650/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
2651testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002652 var RSL_Message rx_rsl;
2653 var DchanTuple dt;
2654
2655 f_init(1);
2656
2657 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002658 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002659
2660 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002661 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 +07002662 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002663 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 +07002664
2665 /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
2666 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
2667
2668 /* Clean up the connection */
2669 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002670 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002671
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002672 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002673}
2674
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002675/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
2676testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002677 var RSL_Message rx_rsl;
2678 var DchanTuple dt;
2679
2680 f_init(1);
2681
2682 /* MS establishes a SAPI=0 link on DCCH */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002683 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002684
2685 /* MSC sends some data on (not yet established) SAPI=3 link */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002686 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 +07002687 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002688 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 +07002689
2690 /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002691 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Pau Espin Pedrol121f27f2022-01-12 12:02:10 +01002692 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, '10'B);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002693
2694 /* Clean up the connection */
2695 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002696 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002697
2698 f_shutdown_helper();
2699}
2700
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002701testcase TC_si_default() runs on test_CT {
2702 f_init(0);
2703 f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002704 f_shutdown_helper();
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002705}
Harald Welte4003d112017-12-09 22:35:39 +01002706
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002707/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
2708 * the entire value range. This function provides the same EARFCN numbers for the same earfcn_index */
2709private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uint16_t
2710{
2711 select (earfcn_index) {
2712 case (0) {
2713 /* E-ARFCN 111 is already added in the osmo-bsc.cfg */
2714 return 111;
2715 }
2716 case (1) {
2717 return 1;
2718 }
2719 case (2) {
2720 return 0;
2721 }
2722 case (3) {
2723 return 65535;
2724 }
2725 case else {
2726 return 23 * (earfcn_index - 3);
2727 }
2728 }
2729}
2730
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002731function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
2732 template CellSelIndValue expect_cells := omit) runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002733
2734 f_init(0);
2735
2736 /* E-ARFCN 111 is already added in the osmo-bsc.cfg, so only add more arfcns if total_earfcns > 1 */
2737 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002738 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2739 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002740 }
2741
2742 f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
2743
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002744 if (not istemplatekind(expect_cells, "omit")) {
2745 /* Also check that RR Channel Release contains these EARFCNs.
2746 * (copied code from TC_chan_rel_hard_clear_csfb) */
2747 var BSSAP_N_DATA_ind rx_di;
2748 var DchanTuple dt;
2749
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01002750 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Pau Espin Pedrold0046312021-04-19 16:35:58 +02002751 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2752 * yet when generating the EUTRAN neigh list in RR CHannel Release) */
2753 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002754
2755 /* Instruct BSC to clear channel */
2756 var BssmapCause cause := 0;
2757 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2758
2759 /* expect Clear Complete from BSC on A */
2760 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2761 /* release the SCCP connection */
2762 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2763 }
2764
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002765 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := expect_cells);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002766 }
2767
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002768 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002769 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 +02002770 }
2771}
2772
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002773private function f_tr_si2quater_earfcns(integer count) return template SI2quaterRestOctetsList
2774{
2775 var template SI2quaterRestOctetsList si2quater := {};
2776 var integer si2quater_count := (count + 2) / 3;
2777
2778 for (var integer i := 0; i < count; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002779 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002780 var integer index := i / 3;
2781 var integer earfcn_index := i mod 3;
2782 if (index >= lengthof(si2quater)) {
2783 si2quater[index] := tr_SI2quaterRestOctets_EUTRAN(index := index, count := si2quater_count - 1);
2784 }
2785 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);
2786 }
2787
2788 return si2quater;
2789}
2790
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002791private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
2792{
2793 var template CellSelIndValue_EUTRAN_Descrs cells := {};
2794
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002795 /* the lte neighbors must match the config & vty to pass this test */
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002796 for (var integer i := 0; i < count; i := i + 1) {
2797 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002798 cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002799 }
2800
2801 return tr_CellSelIndValue_EUTRAN(cells);
2802}
2803
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002804private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
2805{
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002806 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrol8ab62e42020-12-18 16:19:11 +01002807 sic.si2quater := f_tr_si2quater_earfcns(n);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002808 var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
2809 f_test_si2quater(n, sic, cells);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002810}
2811
2812testcase TC_si2quater_2_earfcns() runs on test_CT {
2813 f_tc_si2quater_n_earfcns(2);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002814 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002815}
2816
2817testcase TC_si2quater_3_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002818 f_tc_si2quater_n_earfcns(3);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002819 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002820}
2821
2822testcase TC_si2quater_4_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002823 f_tc_si2quater_n_earfcns(4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002824 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002825}
2826
2827testcase TC_si2quater_5_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002828 f_tc_si2quater_n_earfcns(5);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002829 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002830}
2831
2832testcase TC_si2quater_6_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002833 f_tc_si2quater_n_earfcns(6);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002834 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002835}
2836
2837testcase TC_si2quater_12_earfcns() runs on test_CT {
2838 f_tc_si2quater_n_earfcns(12);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002839 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002840}
2841
2842testcase TC_si2quater_23_earfcns() runs on test_CT {
2843 f_tc_si2quater_n_earfcns(23);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002844 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002845}
2846
2847testcase TC_si2quater_32_earfcns() runs on test_CT {
2848 f_tc_si2quater_n_earfcns(32);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002849 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002850}
2851
2852testcase TC_si2quater_33_earfcns() runs on test_CT {
2853 f_tc_si2quater_n_earfcns(33);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002854 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002855}
2856
2857testcase TC_si2quater_42_earfcns() runs on test_CT {
2858 f_tc_si2quater_n_earfcns(42);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002859 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002860}
2861
2862testcase TC_si2quater_48_earfcns() runs on test_CT {
2863 f_tc_si2quater_n_earfcns(48);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002864 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002865}
2866
2867/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
2868 * 48 EARFCNs. */
2869testcase TC_si2quater_49_earfcns() runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002870 var template SystemInformationConfig sic := SystemInformationConfig_default;
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002871 sic.si2quater := f_tr_si2quater_earfcns(48); /* 48, not 49! */
2872 f_init(0);
2873
2874 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002875 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2876 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002877 }
2878
2879 /* The 49th EARFCN no longer fits, expect VTY error */
2880 f_vty_enter_cfg_bts(BSCVTY, 0);
2881 var charstring vty_error;
2882 vty_error := f_vty_transceive_ret(BSCVTY,
2883 "si2quater neighbor-list add earfcn 70 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3")
2884 f_vty_transceive(BSCVTY, "end");
2885
2886 if (f_strstr(vty_error, "Unable to add ARFCN 70") >= 0) {
2887 log("Got expected VTY error: ", vty_error);
2888 setverdict(pass);
2889 } else {
2890 setverdict(fail, "Expected the 49th EUTRAN ARFCN to be rejected by vty config, got: ", vty_error);
2891 }
2892
2893 f_init_bts_and_check_sysinfo(0, expect_si := sic);
2894
2895 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002896 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 +02002897 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002898 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002899}
2900
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002901private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
2902{
2903 var uint8_t count := 0;
2904 for (var integer i := 5; i < 16; i := i + 1) {
2905 if (acc[i] == '0'B) { /* the list marks barred, we count allowed */
2906 count := count + 1;
2907 }
2908 }
2909 return count;
2910}
2911
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002912private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return SystemInformationType1
2913{
2914 var ASP_RSL_Unitdata rx_rsl_ud;
2915 var SystemInformationType1 last_si1;
2916
2917 timer T := 30.0;
2918 T.start;
2919 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002920 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
2921 tr_RSL_BCCH_INFO,
2922 tr_RSL_NO_SACCH_FILL,
2923 tr_RSL_SACCH_FILL))) -> value rx_rsl_ud {
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002924 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
2925 if (g_system_information[rsl_idx].si1 == omit) {
2926 repeat;
2927 }
2928 last_si1 := g_system_information[rsl_idx].si1;
2929 g_system_information[rsl_idx].si1 := omit;
2930 T.stop;
2931 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002932 [] IPA_RSL[rsl_idx][0].receive { repeat; }
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002933 [] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
2934 }
2935 return last_si1;
2936}
2937
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002938/* verify ACC rotate feature */
2939testcase TC_si_acc_rotate() runs on test_CT {
2940 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002941 var SystemInformationType1 last_si1;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002942 var AccessControlClass acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002943 var uint8_t count;
2944 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2945
2946 f_init(0, guard_timeout := 60.0);
2947
2948 f_bts_0_cfg(BSCVTY, {"rach access-control-class 5 barred",
2949 "access-control-class-rotate 3",
2950 "access-control-class-rotate-quantum 1"});
2951
2952 /* Init and get first sysinfo */
2953 f_init_bts_and_check_sysinfo(0, expect_si := ?);
2954
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002955 for (var integer i:= 0; i < 20; i := i + 1) {
2956 last_si1 := f_recv_next_si1(0);
2957 acc := last_si1.rach_control.acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002958 count := f_acc09_count_allowed(acc);
2959 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
2960
2961 if (count != 3) {
2962 log("RSL: EXPECTED SI ACC len=3");
2963 setverdict(fail, "received SI does not match expectations");
2964 break;
2965 }
2966
2967 for (var integer j := 0; j < 10; j := j + 1) {
2968 if (acc[16 - 1 - j] == '0'B) { /* the list marks barred, we count allowed */
2969 times_allowed[j] := times_allowed[j] + 1;
2970 }
2971 }
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002972 }
2973
2974 for (var integer j := 0; j < 10; j := j + 1) {
2975 log("ACC", j, " allowed ", times_allowed[j], " times" );
2976 if (j != 5 and times_allowed[j] < 3) {
2977 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " < 1 times");
2978 } else if (j == 5 and times_allowed[j] > 0) {
2979 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " > 0 times");
2980 }
2981 }
2982
2983 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
2984 "rach access-control-class 5 allowed"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002985 f_shutdown_helper();
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002986}
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002987
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002988/* verify ACC startup ramp+rotate feature */
2989testcase TC_si_acc_ramp_rotate() runs on test_CT {
2990 var template SystemInformationConfig sic := SystemInformationConfig_default;
2991 var SystemInformationType1 last_si1;
2992 var AccessControlClass acc;
2993 var ASP_RSL_Unitdata rx_rsl_ud;
2994 var uint8_t count;
2995 var uint8_t prev_count;
2996 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2997
2998 f_init(0, guard_timeout := 80.0);
2999
3000 f_bts_0_cfg(BSCVTY, {"rach access-control-class 4 barred",
3001 "access-control-class-rotate 0",
3002 "access-control-class-rotate-quantum 1",
3003 "access-control-class-ramping",
3004 "access-control-class-ramping-step-interval 5",
3005 "access-control-class-ramping-step-size 5"});
3006
3007 /* Init and get first sysinfo */
3008 f_init_bts_and_check_sysinfo(0, expect_si := ?);
3009 last_si1 := g_system_information[0].si1;
3010 acc := last_si1.rach_control.acc;
3011 count := f_acc09_count_allowed(acc);
3012 /* Adm subset size was set to 0 above, so wait until all ACC are barred */
3013 while (count > 0) {
3014 last_si1 := f_recv_next_si1(0);
3015 acc := last_si1.rach_control.acc;
3016 count := f_acc09_count_allowed(acc);
3017 log("RSL: wait len()=0: GOT SI1 ACC len=", count, ": ", acc);
3018 }
3019
3020 /* Increase adm subset size, we should see ramping start up */
3021 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10"});
3022 prev_count := 0;
3023 while (true) {
3024 last_si1 := f_recv_next_si1(0);
3025 acc := last_si1.rach_control.acc;
3026 count := f_acc09_count_allowed(acc);
3027 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3028
3029 if (prev_count > count) {
3030 setverdict(fail, "ACC allowed count dropped while expecting grow: ", prev_count, " -> ", count);
3031 break;
3032 }
3033
3034 if (count == 9) {
3035 break; /* Maximum reached (10 - 1 perm barred), done here */
3036 }
3037
3038 prev_count := count;
3039 }
3040
3041 setverdict(pass);
3042
3043 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3044 "rach access-control-class 4 allowed",
3045 "no access-control-class-ramping"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003046 f_shutdown_helper();
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003047}
3048
Harald Welte4003d112017-12-09 22:35:39 +01003049testcase TC_ctrl_msc_connection_status() runs on test_CT {
3050 var charstring ctrl_resp;
3051
Harald Welte89d42e82017-12-17 16:42:41 +01003052 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003053
3054 /* See https://osmocom.org/issues/2729 */
3055 f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003056 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01003057}
3058
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003059testcase TC_ctrl_msc0_connection_status() runs on test_CT {
3060 var charstring ctrl_resp;
3061
3062 f_init(1);
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003063
3064 f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003065 f_shutdown_helper();
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003066}
3067
Neels Hofmeyr0bc470d2021-08-21 13:37:13 +02003068/* Verify correct stats on the number of configured and connected MSCs */
3069private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
3070 g_pars := f_gen_test_hdlr_pars();
3071 var StatsDExpects expect := {
3072 { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
3073 { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
3074 };
3075 f_statsd_expect(expect);
3076}
3077
3078private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
3079{
3080 var MSC_ConnHdlr vc_conn;
3081
3082 f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
3083 f_sleep(1.0);
3084 vc_conn := f_start_handler(tc_fn);
3085 vc_conn.done;
3086
3087 /* Also verify stat exposed on CTRL interface */
3088 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
3089 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
3090
3091 f_shutdown_helper();
3092}
3093
3094/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
3095private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
3096 f_tc_stat_num_msc_connected_msc_connhdlr(1);
3097}
3098testcase TC_stat_num_msc_connected_1() runs on test_CT {
3099 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
3100}
3101
3102/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
3103private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
3104 f_tc_stat_num_msc_connected_msc_connhdlr(2);
3105}
3106testcase TC_stat_num_msc_connected_2() runs on test_CT {
3107 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
3108}
3109
3110/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
3111private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
3112 f_tc_stat_num_msc_connected_msc_connhdlr(3);
3113}
3114testcase TC_stat_num_msc_connected_3() runs on test_CT {
3115 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
3116}
3117
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003118/* Verify correct stats on the number of configured and connected MSCs */
3119private 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 +06003120 var integer num_trx_connected := 0;
3121 var integer num_trx_total := 0;
3122
3123 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3124 var integer trx_num := c_BtsParams[i].trx_num;
3125 num_trx_total := num_trx_total + trx_num;
3126 if (i < expect_num_bts_connected) {
3127 num_trx_connected := num_trx_connected + trx_num;
3128 }
3129 }
3130
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003131 var StatsDExpects expect := {
3132 { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
3133 { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3134 { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003135 { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := num_trx_connected, max := num_trx_connected },
3136 { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := num_trx_total, max := num_trx_total }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003137 };
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003138
3139 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003140 f_statsd_expect(expect);
3141}
3142
3143private 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 +06003144 var integer num_trx_connected := 0;
3145 var integer num_trx_total := 0;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003146 var MSC_ConnHdlr vc_conn;
3147
3148 f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
3149 f_sleep(1.0);
3150 vc_conn := f_start_handler(tc_fn);
3151 vc_conn.done;
3152
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003153 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3154 var integer trx_num := c_BtsParams[i].trx_num;
3155 num_trx_total := num_trx_total + trx_num;
3156 if (i < nr_bts) {
3157 num_trx_connected := num_trx_connected + trx_num;
3158 }
3159 }
3160
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003161 /* Also verify stat exposed on CTRL interface */
3162 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
3163 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 +06003164 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(num_trx_connected));
3165 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 +02003166
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003167 /* Verify rf_states exposed on CTRL interface */
3168 var charstring expect_net_rf_states := "";
3169 for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003170 var charstring expect_bts_rf_states := "";
3171
3172 for (var integer j := 0; j < c_BtsParams[i].trx_num; j := j + 1) {
3173 expect_bts_rf_states := expect_bts_rf_states &
3174 int2str(i) & "," & int2str(j) & ",";
3175 if (i < NUM_BTS) {
3176 /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
3177 expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
3178 } else {
3179 /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
3180 expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
3181 }
3182 /* The RF policy is still global in osmo-bsc, i.e. always "on" */
3183 expect_bts_rf_states := expect_bts_rf_states & "on,";
3184 if (i < nr_bts) {
3185 /* For BTS where RSL is connected, the RSL state will be "up" */
3186 expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
3187 } else {
3188 expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
3189 }
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003190 }
3191
3192 f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
3193 expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
3194 }
3195 f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
3196
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003197 f_shutdown_helper();
3198}
3199
3200/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
3201private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
3202 f_tc_stat_num_bts_connected_msc_connhdlr(1);
3203}
3204testcase TC_stat_num_bts_connected_1() runs on test_CT {
3205 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
3206}
3207
3208/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
3209private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
3210 f_tc_stat_num_bts_connected_msc_connhdlr(2);
3211}
3212testcase TC_stat_num_bts_connected_2() runs on test_CT {
3213 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
3214}
3215
3216/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
3217private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
3218 f_tc_stat_num_bts_connected_msc_connhdlr(3);
3219}
3220testcase TC_stat_num_bts_connected_3() runs on test_CT {
3221 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
3222}
3223
Harald Welte4003d112017-12-09 22:35:39 +01003224testcase TC_ctrl() runs on test_CT {
3225 var charstring ctrl_resp;
3226
Harald Welte89d42e82017-12-17 16:42:41 +01003227 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003228
3229 /* all below values must match the osmo-bsc.cfg config file used */
3230
Harald Welte6a129692018-03-17 17:30:14 +01003231 f_ctrl_get_exp(IPA_CTRL, "mcc", "001");
3232 f_ctrl_get_exp(IPA_CTRL, "mnc", "01");
Oliver Smith75aa0202019-08-19 14:17:50 +02003233 f_ctrl_get_exp(IPA_CTRL, "number-of-bts", "4");
Harald Welte4003d112017-12-09 22:35:39 +01003234
3235 var integer bts_nr := 0;
3236 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "location-area-code", "1");
3237 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "cell-identity", "0");
3238 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "oml-connection-state", "connected");
3239 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "gprs-mode", "gprs");
3240 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "rf_state", "operational,unlocked,on");
3241 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "arfcn", "871");
3242 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "max-power-reduction", "20");
3243
3244 var integer uptime := str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime"));
3245 f_sleep(2.0);
3246 if (str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime")) < uptime+1) {
3247 setverdict(fail, "oml-uptime not incrementing as expected");
3248 }
3249 /* TODO: Disconnect RSL, imply that OML is disconnected and check for uptime zero? */
3250
3251 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
3252
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003253 f_shutdown_helper();
Harald Welte96c94412017-12-09 03:12:45 +01003254}
3255
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003256/* Verify that Upon receival of SET "location", BSC forwards a TRAP
3257 "location-state" over the SCCPlite IPA conn */
3258testcase TC_ctrl_location() runs on test_CT {
3259 var MSC_ConnHdlr vc_conn;
3260 var integer bts_nr := 0;
3261
3262 f_init(1, true);
3263 f_sleep(1.0);
3264
3265 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234567,fix3d,0.340000,0.560000,0.780000");
3266 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3267 "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
3268
3269 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "1");
3270 f_sleep(2.0);
3271
3272 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234888,fix3d,0.350000,0.570000,0.790000");
3273 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3274 "1234888,fix3d,0.350000,0.570000,0.790000,operational,locked,off,001,01");
3275
3276 /* should match the one from config */
3277 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
3278
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003279 f_shutdown_helper();
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003280}
3281
Harald Welte6f521d82017-12-11 19:52:02 +01003282
3283/***********************************************************************
3284 * Paging Testing
3285 ***********************************************************************/
3286
3287type record Cell_Identity {
3288 GsmMcc mcc,
3289 GsmMnc mnc,
3290 GsmLac lac,
3291 GsmCellId ci
3292};
Harald Welte24135bd2018-03-17 19:27:53 +01003293private const Cell_Identity cid := { '001'H, '01'H, 1, 0 };
Stefan Sperling049a86e2018-03-20 15:51:00 +01003294private const Cell_Identity unknown_cid := { '678'H, 'f90'H, 1, 0 };
Harald Welte6f521d82017-12-11 19:52:02 +01003295
Harald Welte5d1a2202017-12-13 19:51:29 +01003296type set of integer BtsIdList;
3297
3298private function f_bts_in_list(integer bts_id, BtsIdList bts_ids) return boolean {
3299 for (var integer j := 0; j < sizeof(bts_ids); j := j + 1) {
3300 if (bts_id == bts_ids[j]) {
3301 return true;
3302 }
3303 }
3304 return false;
3305}
Harald Welte6f521d82017-12-11 19:52:02 +01003306
3307/* core paging test helper function; used by most paging test cases */
3308private function f_pageing_helper(hexstring imsi,
3309 template BSSMAP_FIELD_CellIdentificationList cid_list,
Harald Welte5d1a2202017-12-13 19:51:29 +01003310 BtsIdList bts_ids := { 0 },
Harald Welte6f521d82017-12-11 19:52:02 +01003311 template RSL_ChanNeeded rsl_chneed := omit,
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003312 template (omit) OCT4 tmsi := omit) runs on test_CT
Harald Welte6f521d82017-12-11 19:52:02 +01003313{
3314 var template BSSMAP_IE_ChannelNeeded bssmap_chneed;
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003315 var template MobileIdentityV mi;
Harald Welte6f521d82017-12-11 19:52:02 +01003316 var RSL_Message rx_rsl;
3317 var integer paging_group := hex2int(imsi[lengthof(imsi)-1]);
Harald Welte5d1a2202017-12-13 19:51:29 +01003318 var integer i;
Harald Welte6f521d82017-12-11 19:52:02 +01003319
3320 f_init();
Harald Welte6f521d82017-12-11 19:52:02 +01003321
3322 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Harald Weltec3068592018-03-17 19:55:31 +01003323 for (i := 0; i < NUM_BTS; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003324 IPA_RSL[i][0].clear;
Harald Welte5d1a2202017-12-13 19:51:29 +01003325 }
Harald Welte6f521d82017-12-11 19:52:02 +01003326
3327 if (isvalue(rsl_chneed)) {
3328 /* The values of 08.08 3.2.2.36 and 08.58 9.3.40 are luckily identical */
3329 bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
3330 } else {
3331 bssmap_chneed := omit;
3332 }
3333
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003334 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
3335 ts_BSSMAP_Paging(imsi, cid_list, tmsi, bssmap_chneed)));
Harald Welte6f521d82017-12-11 19:52:02 +01003336
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003337 if (not istemplatekind(tmsi, "omit")) {
3338 mi := t_MI_TMSI(tmsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003339 } else {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003340 mi := tr_MI_IMSI(imsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003341 }
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003342
Harald Welte5d1a2202017-12-13 19:51:29 +01003343 for (i := 0; i < sizeof(bts_ids); i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003344 rx_rsl := f_exp_ipa_rx(tr_RSL_PAGING_CMD(mi), idx := {bts_ids[i], 0});
Harald Welte5d1a2202017-12-13 19:51:29 +01003345 /* check channel type, paging group */
3346 if (rx_rsl.ies[1].body.paging_group != paging_group) {
3347 setverdict(fail, "Paging for wrong paging group");
3348 }
3349 if (ispresent(rsl_chneed) and
3350 rx_rsl.ies[3].body.chan_needed.chan_needed != valueof(rsl_chneed)) {
3351 setverdict(fail, "RSL Channel Needed != BSSMAP Channel Needed");
3352 }
Harald Welte6f521d82017-12-11 19:52:02 +01003353 }
Harald Welte2fccd982018-01-31 15:48:19 +01003354 f_sleep(2.0);
Harald Welte5d1a2202017-12-13 19:51:29 +01003355 /* do a quick check on all not-included BTSs if they received paging */
3356 for (i := 0; i < NUM_BTS; i := i + 1) {
3357 timer T := 0.1;
3358 if (f_bts_in_list(i, bts_ids)) {
3359 continue;
3360 }
3361 T.start;
3362 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003363 [] IPA_RSL[i][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003364 setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
3365 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003366 [] IPA_RSL[i][0].receive { repeat; }
Harald Welte5d1a2202017-12-13 19:51:29 +01003367 [] T.timeout { }
3368 }
Harald Welte6f521d82017-12-11 19:52:02 +01003369 }
3370
3371 setverdict(pass);
3372}
3373
Harald Welte5d1a2202017-12-13 19:51:29 +01003374const BtsIdList c_BtsId_all := { 0, 1, 2 };
Harald Welte751d3eb2018-01-31 15:51:06 +01003375const BtsIdList c_BtsId_none := { };
Harald Welte5d1a2202017-12-13 19:51:29 +01003376const BtsIdList c_BtsId_LAC1 := { 0, 1 };
3377const BtsIdList c_BtsId_LAC2 := { 2 };
3378
Harald Welte6f521d82017-12-11 19:52:02 +01003379/* PAGING by IMSI + TMSI */
3380testcase TC_paging_imsi_nochan() runs on test_CT {
3381 var BSSMAP_FIELD_CellIdentificationList cid_list;
3382 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Philipp Maier8c04b0a2018-02-23 13:48:48 +01003383 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, omit);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003384 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003385}
3386
3387/* PAGING by IMSI + TMSI */
3388testcase TC_paging_tmsi_nochan() runs on test_CT {
3389 var BSSMAP_FIELD_CellIdentificationList cid_list;
3390 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003391 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, 'A1B2C301'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003392 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003393}
3394
3395/* Paging with different "channel needed' values */
3396testcase TC_paging_tmsi_any() runs on test_CT {
3397 var BSSMAP_FIELD_CellIdentificationList cid_list;
3398 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003399 f_pageing_helper('001010100000002'H, cid_list, c_BtsId_all, RSL_CHANNEED_ANY, 'A1B2C302'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003400 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003401}
3402testcase TC_paging_tmsi_sdcch() runs on test_CT {
3403 var BSSMAP_FIELD_CellIdentificationList cid_list;
3404 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003405 f_pageing_helper('001010100000003'H, cid_list, c_BtsId_all, RSL_CHANNEED_SDCCH, 'A1B2C303'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003406 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003407}
3408testcase TC_paging_tmsi_tch_f() runs on test_CT {
3409 var BSSMAP_FIELD_CellIdentificationList cid_list;
3410 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003411 f_pageing_helper('001010000000004'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_F, 'A1B2C304'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003412 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003413}
3414testcase TC_paging_tmsi_tch_hf() runs on test_CT {
3415 var BSSMAP_FIELD_CellIdentificationList cid_list;
3416 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003417 f_pageing_helper('001010000000005'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_ForH, 'A1B2C305'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003418 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003419}
3420
3421/* Paging by CGI */
3422testcase TC_paging_imsi_nochan_cgi() runs on test_CT {
3423 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3424 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(cid.mcc, cid.mnc, cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003425 f_pageing_helper('001010000000006'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003426 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003427}
3428
3429/* Paging by LAC+CI */
3430testcase TC_paging_imsi_nochan_lac_ci() runs on test_CT {
3431 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3432 cid_list := { cIl_LAC_CI := { ts_BSSMAP_CI_LAC_CI(cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003433 f_pageing_helper('001010000000007'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003434 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003435}
3436
3437/* Paging by CI */
3438testcase TC_paging_imsi_nochan_ci() runs on test_CT {
3439 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3440 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003441 f_pageing_helper('001010000000008'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003442 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003443}
3444
3445/* Paging by LAI */
3446testcase TC_paging_imsi_nochan_lai() runs on test_CT {
3447 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3448 cid_list := { cIl_LAI := { ts_BSSMAP_CI_LAI(cid.mcc, cid.mnc, cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003449 f_pageing_helper('001010000000009'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003450 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003451}
3452
3453/* Paging by LAC */
3454testcase TC_paging_imsi_nochan_lac() runs on test_CT {
3455 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3456 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003457 f_pageing_helper('001010000000010'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003458 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003459}
3460
3461/* Paging by "all in BSS" */
3462testcase TC_paging_imsi_nochan_all() runs on test_CT {
3463 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3464 cid_list := { cIl_allInBSS := ''O };
Harald Welte5d1a2202017-12-13 19:51:29 +01003465 f_pageing_helper('001010000000011'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003466 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003467}
3468
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003469/* Paging by PLMN+LAC+RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003470testcase TC_paging_imsi_nochan_plmn_lac_rnc() runs on test_CT {
3471 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3472 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 +01003473 f_pageing_helper('001010000000012'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003474 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003475}
Harald Welte6f521d82017-12-11 19:52:02 +01003476
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003477/* Paging by RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003478testcase TC_paging_imsi_nochan_rnc() runs on test_CT {
3479 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3480 cid_list := { cIl_RNC := { int2oct(13, 2) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003481 f_pageing_helper('001010000000013'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003482 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003483}
3484
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003485/* Paging by LAC+RNC; We do not implement; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003486testcase TC_paging_imsi_nochan_lac_rnc() runs on test_CT {
3487 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3488 cid_list := { cIl_LAC_RNC := { ts_BSSMAP_CI_LAC_RNC(cid.lac, 14) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003489 f_pageing_helper('001010000000014'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003490 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003491}
3492
Harald Welte6f521d82017-12-11 19:52:02 +01003493/* Paging on multiple cells (multiple entries in list): Verify all of them page */
Harald Welte751d3eb2018-01-31 15:51:06 +01003494testcase TC_paging_imsi_nochan_lacs() runs on test_CT {
3495 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3496 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(1), ts_BSSMAP_CI_LAC(2) } };
3497 f_pageing_helper('001010000000015'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003498 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003499}
3500
3501/* Paging on empty list: Verify none of them page */
3502testcase TC_paging_imsi_nochan_lacs_empty() runs on test_CT {
3503 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3504 cid_list := { cIl_LAC := { } };
3505 f_pageing_helper('001010000000016'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003506 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003507}
3508
Stefan Sperling049a86e2018-03-20 15:51:00 +01003509/* Paging by CGI with unknown MCC/MNC: Verify nothing is paged. */
3510testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
3511 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3512 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(unknown_cid.mcc, unknown_cid.mnc, unknown_cid.lac, unknown_cid.ci) } };
3513 f_pageing_helper('001010000000006'H, cid_list, c_BtsId_none);
3514 f_shutdown_helper();
3515}
3516
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +01003517/* Send paging response containing invalid (wrongly formatted) MobileIdentity IE. */
3518testcase TC_paging_imsi_nochan_ci_resp_invalid_mi() runs on test_CT {
3519 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3520 var BSSAP_N_CONNECT_ind rx_c_ind;
3521 var DchanTuple dt;
3522 var octetstring rr_pag_resp := '06270003535992617965720000'O;
3523 /* { 06 27 } is { GSM48_PDISC_RR, GSM48_MT_RR_PAG_RESP }
3524 * see 3GPP TS 44.018, table 9.1.25.1
3525 * { 00 } or { 01 } is CKSN + Spare Half Octet, not important
3526 * { 03 53 59 92 } is Mobile Station Classmark
3527 * { 61 79 65 72 00 00 } is the invalid Mobile Identity IE (3GPP TS 24.008, 10.5.1.4),
3528 * Length is 0x61 (97 in decimal).
3529 */
3530
3531 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
3532 f_pageing_helper('001010000000008'H, cid_list, { 0 });
3533
3534 /* Send CHAN RQD and wait for allocation; acknowledge it */
3535 dt.rsl_chan_nr := f_chreq_act_ack();
3536 dt.idx := {0, 0};
3537
3538 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
3539 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), rr_pag_resp));
3540
3541 /* Expevct a CR with a matching Paging response on the A-Interface */
3542 timer T := 5.0;
3543 T.start;
3544 alt {
3545 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
3546 setverdict(pass);
3547 dt.sccp_conn_id := rx_c_ind.connectionId;
3548 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
3549 }
3550 [] BSSAP.receive {
3551 setverdict(fail, "Received unexpected message on A-Interface!");
3552 }
3553 [] T.timeout {
3554 setverdict(fail, "Received nothing on A-Interface!");
3555 }
3556 }
3557
3558 f_perform_clear_test_ct(dt);
3559 f_shutdown_helper();
3560}
3561
Harald Welte6f521d82017-12-11 19:52:02 +01003562/* Verify paging retransmission interval + count */
3563/* Verify paging stops after channel establishment */
Harald Welte6f521d82017-12-11 19:52:02 +01003564/* Test behavior under paging overload */
Harald Welteae026692017-12-09 01:03:01 +01003565
Harald Weltee65d40e2017-12-13 00:09:06 +01003566/* Verify PCH load */
3567testcase TC_paging_imsi_load() runs on test_CT {
3568 var BSSMAP_FIELD_CellIdentificationList cid_list;
3569 timer T := 4.0;
Harald Welte2caa1062018-03-17 18:19:05 +01003570 timer T_retrans := 1.0;
Harald Weltee65d40e2017-12-13 00:09:06 +01003571 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003572 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Weltee65d40e2017-12-13 00:09:06 +01003573
3574 /* tell BSC there is no paging space anymore */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003575 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte3b57ab52018-03-17 18:01:10 +01003576 f_sleep(0.2);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003577 IPA_RSL[0][0].clear;
Harald Weltee65d40e2017-12-13 00:09:06 +01003578
3579 /* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
3580 * there would be 8 retransmissions during 4 seconds */
3581 T.start;
Harald Welte2caa1062018-03-17 18:19:05 +01003582 T_retrans.start;
Harald Weltee65d40e2017-12-13 00:09:06 +01003583 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003584 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Weltee65d40e2017-12-13 00:09:06 +01003585 setverdict(fail, "Received PAGING after LOAD_IND(0)");
Daniel Willmannafce8662018-07-06 23:11:32 +02003586 mtc.stop;
Harald Weltee65d40e2017-12-13 00:09:06 +01003587 }
Harald Welte2caa1062018-03-17 18:19:05 +01003588 [] T_retrans.timeout {
3589 /* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003590 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte2caa1062018-03-17 18:19:05 +01003591 T_retrans.start;
3592 repeat;
3593 }
Harald Weltee65d40e2017-12-13 00:09:06 +01003594 [] T.timeout {
3595 setverdict(pass);
3596 }
3597 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003598
3599 f_shutdown_helper();
Harald Weltee65d40e2017-12-13 00:09:06 +01003600}
3601
Harald Welte235ebf12017-12-15 14:18:16 +01003602/* Verify Paging Counter */
Harald Welte1ff69992017-12-14 12:31:17 +01003603testcase TC_paging_counter() runs on test_CT {
3604 var BSSMAP_FIELD_CellIdentificationList cid_list;
3605 timer T := 4.0;
3606 var integer i;
3607 var integer paging_attempted_bsc;
3608 var integer paging_attempted_bts[NUM_BTS];
Oliver Smith8b343d32021-11-26 13:01:42 +01003609 var integer paging_expired_bsc;
Harald Welte1ff69992017-12-14 12:31:17 +01003610 var integer paging_expired_bts[NUM_BTS];
3611 cid_list := valueof(ts_BSSMAP_CIL_noCell);
3612
3613 f_init();
3614
3615 /* read counters before paging */
3616 paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
Oliver Smith8b343d32021-11-26 13:01:42 +01003617 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.8.0 */
3618 paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
3619 }
Harald Welte1ff69992017-12-14 12:31:17 +01003620 for (i := 0; i < NUM_BTS; i := i+1) {
3621 paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
3622 paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
3623 }
3624
3625 f_pageing_helper('001230000000001'H, cid_list, c_BtsId_all);
3626
3627 /* expect the attempted pages on BSC and each BTSs to have incremented by one */
3628 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", paging_attempted_bsc+1);
3629 for (i := 0; i < NUM_BTS; i := i+1) {
3630 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted",
3631 paging_attempted_bts[i]+1);
3632 }
3633
3634 /* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
3635 f_sleep(12.0);
Oliver Smith8b343d32021-11-26 13:01:42 +01003636 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.8.0 */
3637 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
3638 }
Harald Welte1ff69992017-12-14 12:31:17 +01003639 for (i := 0; i < NUM_BTS; i := i+1) {
3640 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
3641 paging_expired_bts[i]+1);
3642 }
Harald Welte1ff69992017-12-14 12:31:17 +01003643
Philipp Maier282ca4b2018-02-27 17:17:00 +01003644 f_shutdown_helper();
Harald Welte1ff69992017-12-14 12:31:17 +01003645}
3646
3647
Harald Welte10985002017-12-12 09:29:15 +01003648/* Verify paging stops after A-RESET */
3649testcase TC_paging_imsi_a_reset() runs on test_CT {
3650 var BSSMAP_FIELD_CellIdentificationList cid_list;
3651 timer T := 3.0;
3652 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003653 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Welte10985002017-12-12 09:29:15 +01003654
3655 /* Perform a BSSMAP Reset and wait for ACK */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003656 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 +01003657 alt {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003658 [] 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 +01003659 [] BSSAP.receive { repeat; }
3660 }
3661
Daniel Willmanncbef3982018-07-30 09:22:40 +02003662 /* Wait to avoid a possible race condition if a paging message is
3663 * received right before the reset ACK. */
3664 f_sleep(0.2);
3665
Harald Welte10985002017-12-12 09:29:15 +01003666 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Philipp Maier1e6b4422018-02-23 14:02:13 +01003667 for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003668 IPA_RSL[i][0].clear;
Philipp Maier1e6b4422018-02-23 14:02:13 +01003669 }
Harald Welte10985002017-12-12 09:29:15 +01003670
3671 /* Wait for 3 seconds if any more PAGING CMD are received on RSL */
3672 T.start;
3673 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003674 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte10985002017-12-12 09:29:15 +01003675 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003676 mtc.stop;
Harald Welte10985002017-12-12 09:29:15 +01003677 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003678 [] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003679 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003680 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003681 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003682 [] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003683 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003684 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003685 }
Harald Welte10985002017-12-12 09:29:15 +01003686 [] T.timeout {
3687 setverdict(pass);
3688 }
3689 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003690
3691 f_shutdown_helper();
Harald Welte10985002017-12-12 09:29:15 +01003692}
Harald Welteae026692017-12-09 01:03:01 +01003693
Philipp Maierf45824a2019-08-14 14:44:10 +02003694/* Verify how we handle unsolicited Paging Response. In case of an unsolicit
3695 * paging response we can not know which MSC is in charge, so we will blindly
3696 * pick the first configured MSC. This behavior is required in order to make
3697 * MT-CSFB calls working because in those cases the BSC can not know that the
3698 * MSC has already paged the subscriver via SGs. So any MT-CSFB call will look
3699 * like an unsolicited Paging Response to the MSC.
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003700 */
3701testcase TC_paging_resp_unsol() runs on test_CT {
3702
3703 f_init(1);
Philipp Maierf45824a2019-08-14 14:44:10 +02003704 timer T := 5.0;
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003705
3706 var BSSAP_N_CONNECT_ind rx_c_ind;
3707 var DchanTuple dt;
3708 var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010008880018'H))));
Philipp Maierf45824a2019-08-14 14:44:10 +02003709 var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003710
3711 /* Send CHAN RQD and wait for allocation; acknowledge it */
3712 dt.rsl_chan_nr := f_chreq_act_ack();
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003713 dt.idx := {0, 0};
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003714
3715 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
Pau Espin Pedrole8a51012023-01-03 11:59:59 +01003716 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 +01003717
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003718
Philipp Maierf45824a2019-08-14 14:44:10 +02003719 /* Expevct a CR with a matching Paging response on the A-Interface */
3720 T.start;
3721 alt {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003722 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
Philipp Maierf45824a2019-08-14 14:44:10 +02003723 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003724 dt.sccp_conn_id := rx_c_ind.connectionId;
3725 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
Philipp Maierf45824a2019-08-14 14:44:10 +02003726 }
3727 [] BSSAP.receive {
3728 setverdict(fail, "Received unexpected message on A-Interface!");
3729 }
3730 [] T.timeout {
3731 setverdict(fail, "Received nothing on A-Interface!");
3732 }
3733 }
3734
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003735 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003736 f_shutdown_helper();
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003737}
3738
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003739/* Verify BSC can schedule N paging requests under one minute if BTS buffer is good enough */
3740function f_TC_paging_Nreq(integer num_subscribers, boolean send_pag_load_ind) runs on test_CT {
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003741 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003742 var Hexstrings imsis := {};
3743 var Booleans rx_paging_done := {};
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003744 var integer rx_paging_num := 0;
3745 var integer i;
3746 timer T_rx := 60.0;
3747 timer T_load_ind := 1.0;
3748
3749 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003750 imsis := imsis & {f_gen_imsi(i)};
3751 rx_paging_done := rx_paging_done & { false };
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003752 }
3753
3754 f_init(1, guard_timeout := 100.0);
3755
3756 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003757 IPA_RSL[0][0].clear;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003758 if (send_pag_load_ind) {
3759 /* Tell there's plenty of space at the BTS (UINT16_MAX): */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003760 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(65535));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003761 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003762
3763 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003764 /* Page on LAC-CI of BTS0: */
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003765 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 +02003766 ts_BSSMAP_Paging(imsis[i], valueof(ts_BSSMAP_CIL_LAC_CI({ts_BSSMAP_CI_LAC_CI(1, 0)})),
3767 omit, omit)));
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003768 }
3769
3770 T_rx.start;
3771 T_load_ind.start;
3772 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003773 [] 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 +02003774 var hexstring imsi := rx_rsl_ud.rsl.ies[2].body.ms_identity.mobileIdentityV.oddEvenInd_identity.imsi.digits;
3775 var hexstring imsi_suffix := substr(imsi, lengthof(imsi)-6, 6);
3776 var charstring imsi_str := hex2str(imsi_suffix);
3777 var integer imsi_idx := str2int(imsi_str);
3778 if (rx_paging_done[imsi_idx] == false) {
3779 rx_paging_done[imsi_idx] := true;
3780 rx_paging_num := rx_paging_num + 1;
Pau Espin Pedrolef7ef632022-04-25 13:34:57 +02003781 } else {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003782 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 +02003783 mtc.stop;
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003784 }
3785 if (rx_paging_num < num_subscribers) {
3786 repeat;
3787 }
3788 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003789 [] IPA_RSL[0][0].receive { repeat; }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003790 [] T_load_ind.timeout {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003791 log("[CCH Load Ind timer] received paging requests so far: ", rx_paging_num);
3792 if (send_pag_load_ind) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003793 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(40));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003794 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003795 T_load_ind.start;
3796 repeat;
3797 }
3798 [] T_rx.timeout {
3799 setverdict(fail, "Timeout expecting paging requests, so far ", rx_paging_num);
3800 mtc.stop;
3801 }
3802 }
3803
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003804 /* Drop OML connection to have all paging requests flushed: */
3805 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
3806
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003807 f_shutdown_helper();
3808}
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003809/* Verify BSC can schedule 500 paging requests under one minute if BTS buffer is good enough */
3810testcase TC_paging_500req() runs on test_CT {
3811 f_TC_paging_Nreq(500, true);
3812}
3813/* Same as TC_paging_500req, but without sending CCCH Load Indication, which
3814 * means BTS is always under CCH Load Threshold, aka capable of sending tons of requests.
3815 * Since No CCCH Load Ind, BSC uses a conservative estimation of BTS load, which
3816 * for current config yields ~8req/sec, so 480req/min maximum. */
3817testcase TC_paging_450req_no_paging_load_ind() runs on test_CT {
3818 f_TC_paging_Nreq(450, false);
3819}
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003820
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003821/* Test RSL link drop causes counter increment */
3822testcase TC_rsl_drop_counter() runs on test_CT {
3823 var integer rsl_fail;
3824
Harald Welte89d42e82017-12-17 16:42:41 +01003825 f_init(1);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003826
3827 rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
3828
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003829 f_ipa_rsl_stop(bts[0][0].rsl);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003830
3831 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
3832
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003833 f_shutdown_helper();
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003834}
3835
3836/* TODO: Test OML link drop causes counter increment */
3837
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003838/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
3839function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003840 var IPA_Client client;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003841 timer T := 10.0;
3842
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003843 client.id := "IPA-BTS0-TRX0-RSL";
3844 client.vc_IPA := IPA_Emulation_CT.create(client.id & "-IPA") alive;
3845 client.ccm_pars := c_IPA_default_ccm_pars;
3846 client.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
3847 client.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003848
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01003849 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003850
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003851 f_init_mgcp(0, "VirtMGW");
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003852
3853 /* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003854 map(client.vc_IPA:IPA_PORT, system:IPA);
3855 connect(client.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0][0]);
3856 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 +01003857
3858 /* wait for IPA OML link to connect and then disconnect */
3859 T.start;
3860 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003861 [] IPA_RSL[0][0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003862 T.stop;
3863 return true;
3864 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003865 [] IPA_RSL[0][0].receive { repeat }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003866 [] T.timeout {
Daniel Willmannafce8662018-07-06 23:11:32 +02003867 return false;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003868 }
3869 }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003870 return false;
3871}
3872
3873/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3874testcase TC_rsl_unknown_unit_id() runs on test_CT {
3875 if (f_ipa_unknown_unit_id(mp_bsc_rsl_port)) {
3876 setverdict(pass);
3877 } else {
3878 setverdict(fail, "Timeout RSL waiting for connection to close");
3879 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003880 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003881}
3882
3883
3884/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3885testcase TC_oml_unknown_unit_id() runs on test_CT {
3886 if (f_ipa_unknown_unit_id(mp_bsc_oml_port)) {
3887 setverdict(pass);
3888 } else {
3889 setverdict(fail, "Timeout OML waiting for connection to close");
3890 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003891 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003892}
3893
3894
Harald Weltec1a2fff2017-12-17 11:06:19 +01003895/***********************************************************************
Harald Welte6811d102019-04-14 22:23:14 +02003896 * "New world" test cases using RSL_Emulation + RAN_Emulation
Harald Weltec1a2fff2017-12-17 11:06:19 +01003897 ***********************************************************************/
3898
Harald Welte6811d102019-04-14 22:23:14 +02003899import from RAN_Emulation all;
Harald Welte47cd0e32020-08-21 12:39:11 +02003900import from BSSAP_LE_Emulation all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01003901import from RSL_Emulation all;
3902import from MSC_ConnectionHandler all;
3903
3904type function void_fn(charstring id) runs on MSC_ConnHdlr;
3905
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003906/* helper function to create and connect a MSC_ConnHdlr component
3907 * TODO: allow connecting to TRX1..N, not only TRX0 */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003908private 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 +02003909 connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003910 connect(vc_conn:RSL, bts[0][0].rsl.vc_RSL:CLIENT_PT);
3911 connect(vc_conn:RSL_PROC, bts[0][0].rsl.vc_RSL:RSL_PROC);
3912 if (isvalue(bts[1][0])) {
3913 connect(vc_conn:RSL1, bts[1][0].rsl.vc_RSL:CLIENT_PT);
3914 connect(vc_conn:RSL1_PROC, bts[1][0].rsl.vc_RSL:RSL_PROC);
Philipp Maier956a92f2018-02-16 10:58:07 +01003915 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003916 if (isvalue(bts[2][0])) {
3917 connect(vc_conn:RSL2, bts[2][0].rsl.vc_RSL:CLIENT_PT);
3918 connect(vc_conn:RSL2_PROC, bts[2][0].rsl.vc_RSL:RSL_PROC);
Neels Hofmeyr91401012019-07-11 00:42:35 +02003919 }
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003920 connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02003921 if (mp_enable_lcs_tests) {
3922 connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
3923 connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
3924 }
Daniel Willmannebdecc02020-08-12 15:30:17 +02003925 connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003926 connect(vc_conn:MGCP_PROC, vc_MGCP[mgwpool_idx]:MGCP_PROC);
3927 connect(vc_conn:MGCP, vc_MGCP[mgwpool_idx]:MGCP_CLIENT);
3928 connect(vc_conn:MGCP_MULTI, vc_MGCP[mgwpool_idx]:MGCP_CLIENT_MULTI);
Harald Welte336820c2018-05-31 20:34:52 +02003929}
3930
Neels Hofmeyrda436782021-07-20 22:09:06 +02003931function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
Harald Welte336820c2018-05-31 20:34:52 +02003932runs on test_CT return MSC_ConnHdlr {
3933 var charstring id := testcasename();
3934 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003935 var integer bssap_idx := 0;
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003936 var integer mgwpool_idx := 0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003937 if (isvalue(pars)) {
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003938 var TestHdlrParams pars_val := valueof(pars);
3939 bssap_idx := pars_val.mscpool.bssap_idx;
3940 mgwpool_idx := pars_val.mgwpool_idx;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003941 }
Harald Welte336820c2018-05-31 20:34:52 +02003942 vc_conn := MSC_ConnHdlr.create(id);
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02003943 f_connect_handler(vc_conn, bssap_idx, mgwpool_idx);
Neels Hofmeyrda436782021-07-20 22:09:06 +02003944 return vc_conn;
3945}
3946
3947function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
3948runs on test_CT return MSC_ConnHdlr {
3949 var charstring id := testcasename();
Harald Weltea0630032018-03-20 21:09:55 +01003950 vc_conn.start(f_handler_init(fn, id, pars));
Harald Weltec1a2fff2017-12-17 11:06:19 +01003951 return vc_conn;
3952}
3953
Neels Hofmeyrda436782021-07-20 22:09:06 +02003954function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
3955runs on test_CT return MSC_ConnHdlr {
3956 return f_start_handler_run(f_start_handler_create(pars), fn, pars);
3957}
3958
Harald Weltea0630032018-03-20 21:09:55 +01003959/* first function inside ConnHdlr component; sets g_pars + starts function */
3960private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
3961runs on MSC_ConnHdlr {
3962 if (isvalue(pars)) {
3963 g_pars := valueof(pars);
3964 }
3965 fn.apply(id);
3966}
3967
Oliver Smith26a3db72021-07-09 13:51:29 +02003968private function f_vty_encryption_a5(charstring options) runs on test_CT {
3969 f_vty_transceive(BSCVTY, "configure terminal");
3970 f_vty_transceive(BSCVTY, "network");
3971 f_vty_transceive(BSCVTY, "encryption a5 " & options);
3972 f_vty_transceive(BSCVTY, "exit");
3973 f_vty_transceive(BSCVTY, "exit");
3974}
3975
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01003976const charstring VTY_A5_DEFAULT := "0 1 3";
3977
Oliver Smith26a3db72021-07-09 13:51:29 +02003978private function f_vty_encryption_a5_reset() runs on test_CT {
3979 /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01003980 f_vty_encryption_a5(VTY_A5_DEFAULT);
Oliver Smith26a3db72021-07-09 13:51:29 +02003981}
3982
Harald Welte3c86ea02018-05-10 22:28:05 +02003983/* Establish signalling channel (non-assignment case) followed by cipher mode */
3984private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02003985 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
3986 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte3c86ea02018-05-10 22:28:05 +02003987 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Philipp Maier23000732018-05-18 11:25:37 +02003988 ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode := omit;
3989 ass_cmd.pdu.bssmap.assignmentRequest.aoIPTransportLayer := omit;
3990 exp_compl.pdu.bssmap.assignmentComplete.circuitIdentityCode := omit;
3991 exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
Harald Welte3c86ea02018-05-10 22:28:05 +02003992
Philipp Maier23000732018-05-18 11:25:37 +02003993 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003994 f_perform_clear();
Harald Welte3c86ea02018-05-10 22:28:05 +02003995}
3996testcase TC_ciph_mode_a5_0() runs on test_CT {
3997 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003998 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02003999 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
4000
4001 f_init(1, true);
4002 f_sleep(1.0);
4003 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4004 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004005 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004006}
4007testcase TC_ciph_mode_a5_1() runs on test_CT {
4008 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004009 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004010 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
4011
4012 f_init(1, true);
4013 f_sleep(1.0);
4014 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4015 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004016 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004017}
Oliver Smith50b98122021-07-09 15:00:28 +02004018/* OS#4975: verify that A5/2 is preferred over A5/0 */
4019testcase TC_ciph_mode_a5_2_0() runs on test_CT {
4020 var MSC_ConnHdlr vc_conn;
4021 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4022
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004023 pars.encr := f_encr_params('05'O, '04'O); /* A5/0 and A5/2 (0x01|0x04)*/
Oliver Smith50b98122021-07-09 15:00:28 +02004024
4025 f_init(1, true);
4026 f_vty_encryption_a5("0 1 2 3");
4027 f_sleep(1.0);
4028 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4029 vc_conn.done;
4030 f_vty_encryption_a5_reset();
4031 f_shutdown_helper();
4032}
Oliver Smith1dff88d2021-07-09 08:45:51 +02004033/* OS#4975: verify that A5/1 is preferred over A5/2 */
4034testcase TC_ciph_mode_a5_2_1() runs on test_CT {
4035 var MSC_ConnHdlr vc_conn;
4036 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4037
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01004038 pars.encr := f_encr_params('06'O, '02'O); /* A5/1 and A5/2 (0x02|0x04)*/
Oliver Smith1dff88d2021-07-09 08:45:51 +02004039
4040 f_init(1, true);
4041 f_vty_encryption_a5("1 2");
4042 f_sleep(1.0);
4043 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4044 vc_conn.done;
4045 f_vty_encryption_a5_reset();
4046 f_shutdown_helper();
4047}
Harald Welte3c86ea02018-05-10 22:28:05 +02004048testcase TC_ciph_mode_a5_3() runs on test_CT {
4049 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004050 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02004051 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
4052
4053 f_init(1, true);
4054 f_sleep(1.0);
4055 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4056 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004057 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02004058}
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004059/* Establish a Signalling channel with A5/4 encryption. */
4060testcase TC_ciph_mode_a5_4() runs on test_CT {
4061 var MSC_ConnHdlr vc_conn;
4062 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4063 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Harald Welte3c86ea02018-05-10 22:28:05 +02004064
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004065 f_init(1, true);
Oliver Smith26a3db72021-07-09 13:51:29 +02004066 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004067 f_sleep(1.0);
4068 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
4069 vc_conn.done;
Oliver Smith26a3db72021-07-09 13:51:29 +02004070 f_vty_encryption_a5_reset();
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02004071 f_shutdown_helper();
4072}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004073/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
4074private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
4075 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4076 var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
4077 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4078 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4079
4080 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004081 f_perform_clear();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004082}
4083testcase TC_assignment_aoip_tla_v6() runs on test_CT {
4084 var MSC_ConnHdlr vc_conn;
4085 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4086
4087 f_init(1, true);
4088 f_sleep(1.0);
4089 vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
4090 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004091 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004092}
4093
Harald Welte3c86ea02018-05-10 22:28:05 +02004094
4095/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
Harald Welte651fcdc2018-05-10 20:23:16 +02004096private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004097 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4098 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004099
Harald Welte552620d2017-12-16 23:21:36 +01004100 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4101 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte73cd2712017-12-17 00:44:52 +01004102
Harald Weltea0630032018-03-20 21:09:55 +01004103 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004104 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004105}
Harald Welte552620d2017-12-16 23:21:36 +01004106testcase TC_assignment_fr_a5_0() runs on test_CT {
4107 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004108 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004109 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
Harald Welte552620d2017-12-16 23:21:36 +01004110
Harald Welte89d42e82017-12-17 16:42:41 +01004111 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004112 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004113 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004114 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004115 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004116}
Harald Welte552620d2017-12-16 23:21:36 +01004117testcase TC_assignment_fr_a5_1() runs on test_CT {
Harald Weltec1a2fff2017-12-17 11:06:19 +01004118 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004119 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004120 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004121
Harald Welte89d42e82017-12-17 16:42:41 +01004122 f_init(1, true);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004123 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004124 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4125 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004126 f_shutdown_helper();
Harald Welte651fcdc2018-05-10 20:23:16 +02004127}
4128testcase TC_assignment_fr_a5_3() runs on test_CT {
4129 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004130 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004131 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004132
Harald Welte651fcdc2018-05-10 20:23:16 +02004133 f_init(1, true);
4134 f_sleep(1.0);
4135 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004136 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004137 f_shutdown_helper();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004138}
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004139/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
4140testcase TC_assignment_fr_a5_4() runs on test_CT {
4141 var MSC_ConnHdlr vc_conn;
4142 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4143 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
4144
4145 f_init(1, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02004146 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004147 f_sleep(1.0);
4148 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4149 vc_conn.done;
Oliver Smith7eabd312021-07-12 14:18:56 +02004150 f_vty_encryption_a5_reset();
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004151 f_shutdown_helper();
4152}
Harald Weltec1a2fff2017-12-17 11:06:19 +01004153
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +02004154/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
4155testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
4156 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4157 var MSC_ConnHdlr vc_conn;
4158
4159 f_init(1, true);
4160 f_sleep(1.0);
4161
4162 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
4163 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
4164 vc_conn.done;
4165 f_shutdown_helper();
4166}
4167
Harald Welte552620d2017-12-16 23:21:36 +01004168/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
4169private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004170 g_pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004171 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02004172 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004173
4174 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02004175 /* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
4176
Harald Weltea0630032018-03-20 21:09:55 +01004177 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004178 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004179}
Harald Welte552620d2017-12-16 23:21:36 +01004180testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
4181 var MSC_ConnHdlr vc_conn;
4182
Harald Welte89d42e82017-12-17 16:42:41 +01004183 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004184 f_sleep(1.0);
4185
Harald Welte8863fa12018-05-10 20:15:27 +02004186 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
Harald Welte552620d2017-12-16 23:21:36 +01004187 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004188 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004189}
4190
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004191private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
4192 var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
4193 var PDU_BSSAP exp_ass_req := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004194
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004195 exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4196 exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4197
4198 /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
4199
4200 var BSSMAP_FIELD_CodecType codecType;
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004201
4202 codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
4203 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
4204
4205 f_create_chan_and_exp();
4206 /* we should now have a COMPL_L3 at the MSC */
4207
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004208 /* Start ciphering, expect Cipher Mode Reject */
Neels Hofmeyr6c388f22021-06-11 02:36:56 +02004209 f_cipher_mode(g_pars.encr, exp_fail := true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004210 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004211}
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004212testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
4213 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004214 var MSC_ConnHdlr vc_conn;
4215
Harald Welte89d42e82017-12-17 16:42:41 +01004216 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004217 f_sleep(1.0);
4218
Neels Hofmeyr0588cad2021-06-11 01:38:18 +02004219 pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004220 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004221 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004222 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004223}
4224
4225
Harald Welte4532e0a2017-12-23 02:05:44 +01004226private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004227 g_pars := f_gen_test_hdlr_pars();
Harald Welte4532e0a2017-12-23 02:05:44 +01004228 var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
Philipp Maier48604732018-10-09 15:00:37 +02004229 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte4532e0a2017-12-23 02:05:44 +01004230 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004231
4232 f_statsd_reset();
Harald Weltea0630032018-03-20 21:09:55 +01004233 f_establish_fully(ass_cmd, exp_compl);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004234
4235 var StatsDExpects expect := {
Daniel Willmannc5398f72020-09-21 10:41:35 +02004236 { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
4237 { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
Daniel Willmannebdecc02020-08-12 15:30:17 +02004238 { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
4239 { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
4240 };
4241 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004242 f_perform_clear();
Harald Welte4532e0a2017-12-23 02:05:44 +01004243}
4244
4245testcase TC_assignment_sign() runs on test_CT {
4246 var MSC_ConnHdlr vc_conn;
4247
4248 f_init(1, true);
4249 f_sleep(1.0);
4250
Harald Welte8863fa12018-05-10 20:15:27 +02004251 vc_conn := f_start_handler(refers(f_tc_assignment_sign));
Harald Welte4532e0a2017-12-23 02:05:44 +01004252 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004253 f_shutdown_helper();
Harald Welte4532e0a2017-12-23 02:05:44 +01004254}
4255
Harald Welte60aa5762018-03-21 19:33:13 +01004256/***********************************************************************
4257 * Codec (list) testing
4258 ***********************************************************************/
4259
4260/* check if the given rsl_mode is compatible with the a_elem */
4261private function f_match_codec(BSSMAP_FIELD_CodecElement a_elem, RSL_IE_ChannelMode rsl_mode)
4262return boolean {
4263 select (a_elem.codecType) {
4264 case (GSM_FR) {
4265 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1))) {
4266 return true;
4267 }
4268 }
4269 case (GSM_HR) {
4270 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1))) {
4271 return true;
4272 }
4273 }
4274 case (GSM_EFR) {
4275 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2))) {
4276 return true;
4277 }
4278 }
4279 case (FR_AMR) {
4280 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3))) {
4281 return true;
4282 }
4283 }
4284 case (HR_AMR) {
4285 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3))) {
4286 return true;
4287 }
4288 }
4289 case else { }
4290 }
4291 return false;
4292}
4293
4294/* check if the given rsl_mode is compatible with the a_list */
4295private function f_match_codecs(BSSMAP_IE_SpeechCodecList a_list, RSL_IE_ChannelMode rsl_mode)
4296return boolean {
4297 for (var integer i := 0; i < sizeof(a_list); i := i+1) {
4298 if (f_match_codec(a_list.codecElements[i], rsl_mode)) {
4299 return true;
4300 }
4301 }
4302 return false;
4303}
4304
4305/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
Philipp Maier61f6b572018-07-06 14:03:38 +02004306function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
Harald Welte60aa5762018-03-21 19:33:13 +01004307return BSSMAP_IE_ChannelType {
4308 /* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
4309 var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
4310 select (a_elem.codecType) {
4311 case (GSM_FR) {
4312 ret.channelRateAndType := ChRate_TCHF;
4313 ret.speechId_DataIndicator := Spdi_TCHF_FR;
4314 }
4315 case (GSM_HR) {
4316 ret.channelRateAndType := ChRate_TCHH;
4317 ret.speechId_DataIndicator := Spdi_TCHH_HR;
4318 }
4319 case (GSM_EFR) {
4320 ret.channelRateAndType := ChRate_TCHF;
4321 ret.speechId_DataIndicator := Spdi_TCHF_EFR;
4322 }
4323 case (FR_AMR) {
4324 ret.channelRateAndType := ChRate_TCHF;
4325 ret.speechId_DataIndicator := Spdi_TCHF_AMR;
4326 }
4327 case (HR_AMR) {
4328 ret.channelRateAndType := ChRate_TCHH;
4329 ret.speechId_DataIndicator := Spdi_TCHH_AMR;
4330 }
4331 case else {
4332 setverdict(fail, "Unsupported codec ", a_elem);
Daniel Willmannafce8662018-07-06 23:11:32 +02004333 mtc.stop;
Harald Welte60aa5762018-03-21 19:33:13 +01004334 }
4335 }
4336 return ret;
4337}
4338
Harald Weltea63b9102018-03-22 20:36:16 +01004339private function f_rsl_chmod_tmpl_from_codec(BSSMAP_FIELD_CodecElement a_elem)
4340return template RSL_IE_Body {
4341 var template RSL_IE_Body mode_ie := {
4342 chan_mode := {
4343 len := ?,
4344 reserved := ?,
4345 dtx_d := ?,
4346 dtx_u := ?,
4347 spd_ind := RSL_SPDI_SPEECH,
4348 ch_rate_type := -,
4349 coding_alg_rate := -
4350 }
4351 }
4352
4353 select (a_elem.codecType) {
4354 case (GSM_FR) {
4355 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
4356 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM1;
4357 }
4358 case (GSM_HR) {
4359 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
4360 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM1;
4361 }
4362 case (GSM_EFR) {
4363 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
4364 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM2;
4365 }
4366 case (FR_AMR) {
4367 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
4368 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM3;
4369 }
4370 case (HR_AMR) {
4371 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
4372 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM3;
4373 }
4374 }
4375 return mode_ie;
4376}
4377
Harald Welte60aa5762018-03-21 19:33:13 +01004378type record CodecListTest {
4379 BSSMAP_IE_SpeechCodecList codec_list,
4380 charstring id
4381}
4382type record of CodecListTest CodecListTests
4383
4384private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004385 f_assignment_codec(id);
4386}
4387
4388private function f_assignment_codec(charstring id, boolean do_perform_clear := true) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02004389 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02004390 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welte60aa5762018-03-21 19:33:13 +01004391
4392 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004393 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte79f3f542018-05-25 20:02:37 +02004394 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4395 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
4396 g_pars.ass_codec_list.codecElements[0];
Philipp Maierd0e64b02019-03-13 14:15:23 +01004397 if (isvalue(g_pars.expect_mr_s0_s7)) {
4398 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
4399 g_pars.expect_mr_s0_s7;
4400 }
Harald Welte79f3f542018-05-25 20:02:37 +02004401 }
Harald Welte60aa5762018-03-21 19:33:13 +01004402 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4403 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
Harald Welte60aa5762018-03-21 19:33:13 +01004404 log("expecting ASS COMPL like this: ", exp_compl);
4405
4406 f_establish_fully(ass_cmd, exp_compl);
Harald Weltea63b9102018-03-22 20:36:16 +01004407
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004408 if (not g_pars.expect_channel_mode_modify) {
4409 /* Verify that the RSL-side activation actually matches our expectations */
4410 var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
Harald Weltea63b9102018-03-22 20:36:16 +01004411
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004412 var RSL_IE_Body mode_ie;
4413 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
4414 setverdict(fail, "Couldn't find CHAN_MODE IE");
Daniel Willmannafce8662018-07-06 23:11:32 +02004415 mtc.stop;
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004416 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004417 var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
4418 if (not match(mode_ie, t_mode_ie)) {
4419 log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
4420 setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004421 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004422
4423 var RSL_IE_Body mr_conf;
4424 if (g_pars.expect_mr_conf_ie != omit) {
4425 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
4426 setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
4427 mtc.stop;
4428 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004429 log("found RSL MR CONFIG IE: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004430
4431 if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
Vadim Yanitskiy8b189372022-09-14 17:31:17 +07004432 setverdict(fail, "RSL MR CONFIG IE does not match expectation. ",
4433 "Expected: ", g_pars.expect_mr_conf_ie, ", got: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004434 }
4435 } else {
4436 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
4437 log("found RSL MR CONFIG IE: ", mr_conf);
4438 setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
4439 mtc.stop;
4440 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004441 }
4442 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004443
4444 if (do_perform_clear) {
4445 f_perform_clear();
4446 }
Harald Welte60aa5762018-03-21 19:33:13 +01004447}
4448
Philipp Maierd0e64b02019-03-13 14:15:23 +01004449private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
4450
4451 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4452 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4453
4454 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004455 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maierd0e64b02019-03-13 14:15:23 +01004456 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4457 }
4458 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4459 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
4460 log("expecting ASS FAIL like this: ", exp_fail);
4461
4462 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004463 f_perform_clear();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004464}
4465
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004466const CounterNameVals counternames_bsc_bts_assignment := {
4467 { "assignment:attempted", 0 },
4468 { "assignment:completed", 0 },
4469 { "assignment:stopped", 0 },
4470 { "assignment:no_channel", 0 },
4471 { "assignment:timeout", 0 },
4472 { "assignment:failed", 0 },
4473 { "assignment:error", 0 }
4474};
4475
4476const CounterNameVals counternames_bts_assignment := {
4477 { "assignment:attempted_sign", 0 },
4478 { "assignment:attempted_speech", 0 },
4479 { "assignment:completed_sign", 0 },
4480 { "assignment:completed_speech", 0 },
4481 { "assignment:stopped_sign", 0 },
4482 { "assignment:stopped_speech", 0 },
4483 { "assignment:no_channel_sign", 0 },
4484 { "assignment:no_channel_speech", 0 },
4485 { "assignment:timeout_sign", 0 },
4486 { "assignment:timeout_speech", 0 },
4487 { "assignment:failed_sign", 0 },
4488 { "assignment:failed_speech", 0 },
4489 { "assignment:error_sign", 0 },
4490 { "assignment:error_speech", 0 }
4491};
4492
4493function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
4494 var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
4495 f_ctrs_bts_init(bts_count, bts_names);
4496 f_ctrs_bsc_init(counternames_bsc_bts_assignment);
4497}
4498
Harald Welte60aa5762018-03-21 19:33:13 +01004499testcase TC_assignment_codec_fr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004500 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004501 var MSC_ConnHdlr vc_conn;
4502
4503 f_init(1, true);
4504 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004505 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004506
4507 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004508 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004509 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004510
4511 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4512 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4513 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4514 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4515 f_ctrs_bts_verify();
4516
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004517 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004518}
4519
4520testcase TC_assignment_codec_hr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004521 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004522 var MSC_ConnHdlr vc_conn;
4523
4524 f_init(1, true);
4525 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004526 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004527
4528 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004529 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004530 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004531
4532 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4533 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4534 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4535 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4536 f_ctrs_bts_verify();
4537
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004538 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004539}
4540
4541testcase TC_assignment_codec_efr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004542 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004543 var MSC_ConnHdlr vc_conn;
4544
4545 f_init(1, true);
4546 f_sleep(1.0);
4547
4548 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004549 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004550 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004551 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004552}
4553
Philipp Maierd0e64b02019-03-13 14:15:23 +01004554/* Allow 5,90k only (current default config) */
4555private function f_allow_amr_rate_5_90k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004556 f_vty_cfg_msc(BSCVTY, 0, {
4557 "amr-config 12_2k forbidden",
4558 "amr-config 10_2k forbidden",
4559 "amr-config 7_95k forbidden",
4560 "amr-config 7_40k forbidden",
4561 "amr-config 6_70k forbidden",
4562 "amr-config 5_90k allowed",
4563 "amr-config 5_15k forbidden",
4564 "amr-config 4_75k forbidden"
4565 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004566}
4567
4568/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
4569 * ("Config-NB-Code = 1") */
4570private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004571 f_vty_cfg_msc(BSCVTY, 0, {
4572 "amr-config 12_2k allowed",
4573 "amr-config 10_2k forbidden",
4574 "amr-config 7_95k forbidden",
4575 "amr-config 7_40k allowed",
4576 "amr-config 6_70k forbidden",
4577 "amr-config 5_90k allowed",
4578 "amr-config 5_15k forbidden",
4579 "amr-config 4_75k allowed"
4580 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004581}
4582
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004583private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
4584 var charstring tch;
4585 if (fr) {
4586 tch := "tch-f";
4587 } else {
4588 tch := "tch-h";
4589 }
4590 f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
4591}
4592
4593/* Set the AMR start-mode for this TCH back to the default configuration. */
4594private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
4595 f_vty_amr_start_mode_set(fr, "auto");
4596}
4597
Harald Welte60aa5762018-03-21 19:33:13 +01004598testcase TC_assignment_codec_amr_f() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004599 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004600 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004601
4602 /* Note: This setups the codec configuration. The parameter payload in
4603 * mr_conf must be consistant with the parameter codecElements in pars
4604 * and also must match the amr-config in osmo-bsc.cfg! */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004605 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004606 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004607 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004608 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004609
Harald Welte60aa5762018-03-21 19:33:13 +01004610 f_init(1, true);
4611 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004612 f_vty_amr_start_mode_set(true, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004613 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004614
Harald Welte8863fa12018-05-10 20:15:27 +02004615 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004616 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004617
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004618 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4619 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4620 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4621 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4622 f_ctrs_bts_verify();
4623
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004624 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004625 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004626}
4627
4628testcase TC_assignment_codec_amr_h() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004629 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004630 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004631
4632 /* See note above */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004633 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004634 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004635 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004636 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004637
Harald Welte60aa5762018-03-21 19:33:13 +01004638 f_init(1, true);
4639 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004640 f_vty_amr_start_mode_set(false, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004641 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004642
Harald Welte8863fa12018-05-10 20:15:27 +02004643 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004644 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004645
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004646 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4647 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4648 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4649 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4650 f_ctrs_bts_verify();
4651
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004652 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004653 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004654}
4655
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004656/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
4657testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
4658 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4659 var MSC_ConnHdlr vc_conn;
4660
4661 f_init(1, true);
4662 f_sleep(1.0);
4663
4664 /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
4665 * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
4666 * expecting a Channel Mode Modify if the channel type is compatible. */
4667 f_disable_all_sdcch();
4668 f_disable_all_tch_h();
4669
4670 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4671 pars.expect_channel_mode_modify := true;
4672 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4673 vc_conn.done;
4674
4675 f_enable_all_sdcch();
4676 f_enable_all_tch();
4677 f_shutdown_helper();
4678}
4679
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004680/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
4681testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
4682 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4683 var MSC_ConnHdlr vc_conn;
4684
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004685 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4686 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
4687 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy36fe9582022-09-14 15:25:04 +07004688 pars.expect_mr_conf_ie := c_mr_conf_5_90;
4689 pars.expect_mr_conf_ie.multirate_cfg.icmi := false; /* expect ICMI=0, smod=00: */
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004690
4691 f_init(1, true);
4692 f_sleep(1.0);
4693
4694 /* First set nonzero start mode bits */
4695 f_vty_amr_start_mode_set(true, "4");
4696 /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
4697 * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
4698 * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
4699 f_vty_amr_start_mode_set(true, "auto");
4700
4701 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4702 vc_conn.done;
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004703
4704 /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
4705 f_vty_amr_start_mode_set(true, "1");
4706 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004707 f_shutdown_helper();
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004708}
4709
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004710function f_TC_assignment_codec_amr(boolean fr, RSL_IE_MultirateCfg mr_cfg,
4711 bitstring s8_s0, bitstring exp_s8_s0,
4712 charstring start_mode := "1")
Philipp Maierd0e64b02019-03-13 14:15:23 +01004713runs on test_CT {
4714
4715 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4716 var MSC_ConnHdlr vc_conn;
4717
Philipp Maierd0e64b02019-03-13 14:15:23 +01004718 if (fr) {
4719 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4720 } else {
4721 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4722 }
4723 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4724 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004725 pars.expect_mr_conf_ie := { multirate_cfg := mr_cfg };
Philipp Maierd0e64b02019-03-13 14:15:23 +01004726 pars.expect_mr_s0_s7 := exp_s8_s0;
4727
4728 f_init(1, true);
4729 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004730 f_vty_amr_start_mode_set(fr, start_mode);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004731 f_sleep(1.0);
4732
4733 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4734 vc_conn.done;
4735 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004736 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004737}
4738
4739function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
4740runs on test_CT {
4741
4742 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4743 var MSC_ConnHdlr vc_conn;
4744
4745 if (fr) {
4746 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4747 } else {
4748 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4749 }
4750 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4751 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4752
4753 f_init(1, true);
4754 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004755 f_vty_amr_start_mode_set(fr, "1");
Philipp Maierd0e64b02019-03-13 14:15:23 +01004756 f_sleep(1.0);
4757
4758 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
4759 vc_conn.done;
4760 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004761 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004762}
4763
Philipp Maierd0e64b02019-03-13 14:15:23 +01004764/* Set S1, we expect an AMR multirate configuration IE with all four rates
4765 * set. */
4766testcase TC_assignment_codec_amr_f_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004767 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4768 params := '20882208'O));
4769 f_TC_assignment_codec_amr(true, mr_cfg, '00000011'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004770 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004771}
4772
4773/* Set S1, we expect an AMR multirate configuration IE with the lower three
4774 * rates set. */
4775testcase TC_assignment_codec_amr_h_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004776 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4777 params := '208820'O));
4778 f_TC_assignment_codec_amr(false, mr_cfg, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004779 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004780}
4781
4782/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4783 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4784testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004785 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4786 params := '20882208'O));
4787 f_TC_assignment_codec_amr(true, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004788 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004789}
4790
4791/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4792 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4793testcase TC_assignment_codec_amr_h_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004794 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4795 params := '208820'O));
4796 f_TC_assignment_codec_amr(false, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004797 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004798}
4799
4800/* The following block of tests selects more and more rates until all four
4801 * possible rates are in the active set (full rate) */
4802testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004803 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4804 f_TC_assignment_codec_amr(true, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004805 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004806}
4807
4808testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004809 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4810 params := '2080'O));
4811 f_TC_assignment_codec_amr(true, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004812 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004813}
4814
4815testcase TC_assignment_codec_amr_f_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004816 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4817 params := '208820'O));
4818 f_TC_assignment_codec_amr(true, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004819 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004820}
4821
4822testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004823 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4824 params := '20882208'O));
4825 f_TC_assignment_codec_amr(true, mr_cfg, '10010101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004826 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004827}
4828
4829/* The following block of tests selects more and more rates until all three
4830 * possible rates are in the active set (half rate) */
4831testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004832 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4833 f_TC_assignment_codec_amr(false, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004834 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004835}
4836
4837testcase TC_assignment_codec_amr_h_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004838 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4839 params := '2080'O));
4840 f_TC_assignment_codec_amr(false, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004841 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004842}
4843
4844testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004845 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4846 params := '208820'O));
4847 f_TC_assignment_codec_amr(false, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004848 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004849}
4850
4851/* The following block tests what happens when the MSC does offer rate
4852 * configurations that are not supported by the BSC. Normally such situations
4853 * should not happen because the MSC gets informed by the BSC in advance via
4854 * the L3 COMPLETE message which rates are applicable. The MSC should not try
4855 * to offer rates that are not applicable anyway. */
4856
4857testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004858 /* Try to include 12,2k in into the active set even though the channel
4859 * is half rate only. The BSC is expected to remove the 12,0k */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004860 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4861 params := '208820'O));
4862 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004863 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004864}
4865
4866testcase TC_assignment_codec_amr_f_S01234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004867 /* See what happens when all rates are selected at once. Since then
4868 * Also S1 is selected, this setting will be prefered and we should
4869 * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004870 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4871 params := '20882208'O));
4872 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004873 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004874}
4875
4876testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004877 /* Same as above, but with S1 missing, the MSC is then expected to
4878 * select the currently supported rates, which are also 12.2k, 7,40k,
4879 * 5,90k, and 4,75k, into the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004880 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4881 params := '20882208'O));
4882 f_TC_assignment_codec_amr(true, mr_cfg, '11111101'B, '10010101'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_zero() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004887 /* Try to select no rates at all */
4888 f_TC_assignment_codec_amr_fail(true, '00000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004889 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004890}
4891
4892testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004893 /* Try to select only unsupported rates */
4894 f_TC_assignment_codec_amr_fail(true, '01101000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004895 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004896}
4897
4898testcase TC_assignment_codec_amr_h_S7() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004899 /* Try to select 12,2k for half rate */
4900 f_TC_assignment_codec_amr_fail(false, '10000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004901 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004902}
4903
Neels Hofmeyr21863562020-11-26 00:34:33 +00004904testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004905 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4906 codec_modes := '10010101'B,
4907 params := '20882208'O));
4908 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004909 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004910}
4911
4912testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004913 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4914 codec_modes := '00010101'B,
4915 params := '208820'O));
4916 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B,
Neels Hofmeyr21863562020-11-26 00:34:33 +00004917 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004918 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004919}
4920
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004921testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004922 /* "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 +07004923 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 3,
4924 codec_modes := '10010101'B,
4925 params := '20882208'O));
4926 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004927 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004928}
4929
4930testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004931 /* "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 +07004932 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 2,
4933 codec_modes := '00010101'B,
4934 params := '208820'O));
4935 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004936 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004937}
4938
Philipp Maierac09bfc2019-01-08 13:41:39 +01004939private function f_disable_all_tch_f() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004940 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 borken");
4941 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 borken");
4942 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 borken");
4943 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004944}
4945
4946private function f_disable_all_tch_h() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004947 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 borken");
4948 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004949}
4950
4951private function f_enable_all_tch() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004952 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 unused");
4953 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 unused");
4954 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 unused");
4955 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 unused");
4956 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 unused");
4957 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004958}
4959
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004960private function f_disable_all_sdcch() runs on test_CT {
4961 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
4962 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
4963 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
4964 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
4965}
4966
4967private function f_enable_all_sdcch() runs on test_CT {
4968 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
4969 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
4970 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
4971 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
4972}
4973
Philipp Maierac09bfc2019-01-08 13:41:39 +01004974/* Allow HR only */
4975private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs on MSC_ConnHdlr {
4976 g_pars := f_gen_test_hdlr_pars();
4977 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4978 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4979 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4980 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
4981 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
4982 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
4983 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004984 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004985}
4986
4987/* Allow FR only */
4988private function f_TC_assignment_codec_xr_exhausted_req_fr(charstring id) runs on MSC_ConnHdlr {
4989 g_pars := f_gen_test_hdlr_pars();
4990 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4991 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4992 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4993 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
4994 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
4995 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4996 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004997 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004998}
4999
5000/* Allow HR only (expect assignment failure) */
5001private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) runs on MSC_ConnHdlr {
5002 g_pars := f_gen_test_hdlr_pars();
5003 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5004 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5005 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5006 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
5007 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
5008 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5009 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005010 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005011}
5012
5013/* Allow FR only (expect assignment failure) */
5014private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) runs on MSC_ConnHdlr {
5015 g_pars := f_gen_test_hdlr_pars();
5016 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5017 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
5018 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5019 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
5020 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
5021 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5022 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005023 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005024}
5025
5026/* Allow FR and HR, but prefer FR */
5027private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5028 g_pars := f_gen_test_hdlr_pars();
5029 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5030 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5031 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5032 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5033 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5034 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5035 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5036 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005037 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005038}
5039
5040/* Allow FR and HR, but prefer HR */
5041private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5042 g_pars := f_gen_test_hdlr_pars();
5043 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5044 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5045 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5046 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5047 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5048 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5049 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5050 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005051 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005052}
5053
5054/* Allow FR and HR, but prefer FR */
5055private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5056 g_pars := f_gen_test_hdlr_pars();
5057 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5058 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5059 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5060 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5061 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5062 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5063 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5064 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005065 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005066}
5067
5068/* Allow FR and HR, but prefer HR */
5069private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5070 g_pars := f_gen_test_hdlr_pars();
5071 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5072 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5073 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5074 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5075 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5076 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5077 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5078 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005079 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005080}
5081
5082/* Request a HR channel while all FR channels are exhausted, this is expected
5083 * to work without conflicts */
5084testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
5085 var MSC_ConnHdlr vc_conn;
5086 f_init(1, true);
5087 f_sleep(1.0);
5088 f_enable_all_tch();
5089 f_disable_all_tch_f();
5090 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
5091 vc_conn.done;
5092 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005093 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005094}
5095
5096/* Request a FR channel while all FR channels are exhausted, this is expected
5097 * to fail. */
5098testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
5099 var MSC_ConnHdlr vc_conn;
5100 f_init(1, true);
5101 f_sleep(1.0);
5102 f_enable_all_tch();
5103 f_disable_all_tch_f();
5104 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
5105 vc_conn.done;
5106 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005107 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005108}
5109
5110/* Request a FR (prefered) or alternatively a HR channel while all FR channels
5111 * are exhausted, this is expected to be resolved by selecting a HR channel. */
5112testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
5113 var MSC_ConnHdlr vc_conn;
5114 f_init(1, true);
5115 f_sleep(1.0);
5116 f_enable_all_tch();
5117 f_disable_all_tch_f();
5118 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
5119 vc_conn.done;
5120 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005121 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005122}
5123
5124/* Request a HR (prefered) or alternatively a FR channel while all FR channels
5125 * are exhausted, this is expected to work without conflicts. */
5126testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
5127 var MSC_ConnHdlr vc_conn;
5128 f_init(1, true);
5129 f_sleep(1.0);
5130 f_enable_all_tch();
5131 f_disable_all_tch_f();
5132 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
5133 vc_conn.done;
5134 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005135 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005136}
5137
5138/* Request a FR channel while all HR channels are exhausted, this is expected
5139 * to work without conflicts */
5140testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
5141 var MSC_ConnHdlr vc_conn;
5142 f_init(1, true);
5143 f_sleep(1.0);
5144 f_enable_all_tch();
5145 f_disable_all_tch_h();
5146 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
5147 vc_conn.done;
5148 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005149 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005150}
5151
5152/* Request a HR channel while all HR channels are exhausted, this is expected
5153 * to fail. */
5154testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
5155 var MSC_ConnHdlr vc_conn;
5156 f_init(1, true);
5157 f_sleep(1.0);
5158 f_enable_all_tch();
5159 f_disable_all_tch_h();
5160 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
5161 vc_conn.done;
5162 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005163 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005164}
5165
5166/* Request a HR (prefered) or alternatively a FR channel while all HR channels
5167 * are exhausted, this is expected to be resolved by selecting a FR channel. */
5168testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
5169 var MSC_ConnHdlr vc_conn;
5170 f_init(1, true);
5171 f_sleep(1.0);
5172 f_enable_all_tch();
5173 f_disable_all_tch_h();
5174 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
5175 vc_conn.done;
5176 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005177 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005178}
5179
5180/* Request a FR (prefered) or alternatively a HR channel while all HR channels
5181 * are exhausted, this is expected to work without conflicts. */
5182testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
5183 var MSC_ConnHdlr vc_conn;
5184 f_init(1, true);
5185 f_sleep(1.0);
5186 f_enable_all_tch();
5187 f_disable_all_tch_h();
5188 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
5189 vc_conn.done;
5190 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005191 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005192}
5193
5194/* Allow FR and HR, but prefer HR */
5195private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5196 g_pars := f_gen_test_hdlr_pars();
5197 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5198 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5199 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5200 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5201 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5202 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5203 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5204 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005205 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005206}
5207
5208/* Allow FR and HR, but prefer FR */
5209private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5210 g_pars := f_gen_test_hdlr_pars();
5211 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5212 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5213 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5214 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5215 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5216 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5217 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5218 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005219 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005220}
5221
5222/* Request a HR (prefered) or alternatively a FR channel, it is expected that
5223 * HR, which is the prefered type, is selected. */
5224testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
5225 var MSC_ConnHdlr vc_conn;
5226 f_init(1, true);
5227 f_sleep(1.0);
5228 f_enable_all_tch();
5229 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
5230 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005231 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005232}
5233
5234/* Request a FR (prefered) or alternatively a HR channel, it is expected that
5235 * FR, which is the prefered type, is selected. */
5236testcase TC_assignment_codec_req_fr_hr() runs on test_CT {
5237 var MSC_ConnHdlr vc_conn;
5238 f_init(1, true);
5239 f_sleep(1.0);
5240 f_enable_all_tch();
5241 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_fr_hr));
5242 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005243 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005244}
5245
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005246/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
5247private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
5248 g_pars := f_gen_test_hdlr_pars();
5249 g_pars.ra := '02'O; /* RA containing reason=LU */
5250
5251 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5252 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5253 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5254 var template uint3_t tsc := ?;
5255
5256 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5257 f_create_bssmap_exp(l3_enc);
5258 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5259 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5260
5261 /* we should now have a COMPL_L3 at the MSC */
5262 timer T := 10.0;
5263 T.start;
5264 alt {
5265 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5266 [] T.timeout {
5267 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5268 }
5269 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005270
5271 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005272}
5273testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
5274 var MSC_ConnHdlr vc_conn;
5275 f_init(1, true);
5276 f_sleep(1.0);
5277 f_disable_all_sdcch();
5278 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
5279 vc_conn.done;
5280 f_enable_all_sdcch();
5281 f_shutdown_helper();
5282}
5283
5284/* Request a signalling channel with all SDCCH exhausted, it is
5285 expected that no TCH will be selected for signalling and assigment will fail
5286 because it's dictated by VTY config */
5287testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
5288 var RSL_Message rsl_unused, rsl_msg;
5289 var GsmRrMessage rr;
5290 f_init(1, false);
5291 f_sleep(1.0);
5292 f_vty_allow_tch_for_signalling(false, 0);
5293 f_disable_all_sdcch();
5294
5295 /* RA containing reason=LU */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005296 f_ipa_tx(ts_RSL_CHAN_RQD('02'O, 2342));
5297 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005298 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
5299 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
5300 setverdict(fail, "Expected reject");
5301 }
5302
5303 f_vty_allow_tch_for_signalling(true, 0);
5304 f_enable_all_sdcch();
5305 f_shutdown_helper();
5306}
5307
5308/* Request a voice channel with all SDCCH exhausted, it is
5309 * expected that TCH channel will be allocated since the VTY option is only
5310 * aimed at signalling requests */
5311private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
5312 g_pars := f_gen_test_hdlr_pars();
5313 g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
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 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005335}
5336testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
5337 var MSC_ConnHdlr vc_conn;
5338 f_init(1, true);
5339 f_sleep(1.0);
5340 f_vty_allow_tch_for_signalling(false, 0);
5341 f_disable_all_sdcch();
5342
5343 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
5344 vc_conn.done;
5345
5346 f_vty_allow_tch_for_signalling(true, 0);
5347 f_enable_all_sdcch();
5348 f_shutdown_helper();
5349}
5350
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005351/* Test Osmux setup BSC<->MSC */
5352testcase TC_assignment_osmux_cn() runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005353 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5354 var MSC_ConnHdlr vc_conn;
5355
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005356 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5357 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5358 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiyb9bf00f2022-09-14 15:35:37 +07005359 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02005360 pars.use_osmux_cn := true;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005361
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02005362 g_osmux_enabled_cn := true;
5363 f_init(1, true);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005364 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005365 f_vty_amr_start_mode_set(false, "1");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005366
5367 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5368 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005369
5370 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01005371 f_shutdown_helper();
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005372}
5373
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005374/* Test Osmux setup BTS<->BSC */
5375testcase TC_assignment_osmux_bts() runs on test_CT {
5376 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5377 var MSC_ConnHdlr vc_conn;
5378
5379 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5380 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5381 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005382 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005383 pars.use_osmux_bts := true;
5384
5385 g_osmux_enabled_bts := true;
5386 f_init(1, true);
5387 f_sleep(1.0);
5388 f_vty_amr_start_mode_set(false, "1");
5389
5390 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5391 vc_conn.done;
5392
5393 f_vty_amr_start_mode_restore(false);
5394 f_shutdown_helper();
5395}
5396
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +02005397/* Test non-AMR codecs still work fine as RTP when Osmux is enabled BTS<->BSC<->MSC */
5398testcase TC_assignment_codec_hr_osmux_on() runs on test_CT {
5399 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5400 var MSC_ConnHdlr vc_conn;
5401
5402 g_osmux_enabled_cn := true;
5403 g_osmux_enabled_bts := true;
5404 f_init(1, true);
5405 f_sleep(1.0);
5406 f_ctrs_bsc_and_bts_assignment_init(1);
5407
5408 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5409 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5410 vc_conn.done;
5411
5412 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
5413 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
5414 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
5415 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
5416 f_ctrs_bts_verify();
5417
5418 f_shutdown_helper();
5419}
5420
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005421/* Test Osmux setup BTS<->BSC<->MSC */
5422testcase TC_assignment_osmux() runs on test_CT {
5423 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5424 var MSC_ConnHdlr vc_conn;
5425
5426 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5427 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5428 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005429 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005430 pars.use_osmux_cn := true;
5431 pars.use_osmux_bts := true;
5432
5433 g_osmux_enabled_cn := true;
5434 g_osmux_enabled_bts := true;
5435 f_init(1, true);
5436 f_sleep(1.0);
5437 f_vty_amr_start_mode_set(false, "1");
5438
5439 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5440 vc_conn.done;
5441
5442 f_vty_amr_start_mode_restore(false);
5443 f_shutdown_helper();
5444}
5445
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005446/* test the procedure of the MSC requesting a Classmark Update:
5447 * a) BSSMAP Classmark Request should result in RR CLASSMARK ENQUIRY,
5448 * b) L3 RR CLASSMARK CHANGE should result in BSSMAP CLASSMARK UPDATE */
Harald Welte898113b2018-01-31 18:32:21 +01005449private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005450 g_pars := f_gen_test_hdlr_pars();
5451
Harald Weltea0630032018-03-20 21:09:55 +01005452 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005453 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005454
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005455 BSSAP.send(ts_BSSMAP_ClassmarkRequest);
5456 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
5457
Harald Welte898113b2018-01-31 18:32:21 +01005458 f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
5459 BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
5460 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005461
5462 f_perform_clear();
Harald Welte898113b2018-01-31 18:32:21 +01005463}
5464testcase TC_classmark() runs on test_CT {
5465 var MSC_ConnHdlr vc_conn;
5466 f_init(1, true);
5467 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005468 vc_conn := f_start_handler(refers(f_tc_classmark));
Harald Welte898113b2018-01-31 18:32:21 +01005469 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005470 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005471}
5472
Harald Welteeddf0e92020-06-21 19:42:15 +02005473/* Send a CommonID from the simulated MSC and verify that the information is used to
5474 * fill BSC-internal data structures (specifically, bsc_subscr associated with subscr_conn) */
5475private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
5476 g_pars := f_gen_test_hdlr_pars();
5477 f_MscConnHdlr_init_vty();
5478
5479 f_create_chan_and_exp();
5480 /* we should now have a COMPL_L3 at the MSC */
Harald Welteeddf0e92020-06-21 19:42:15 +02005481
5482 /* Send CommonID */
5483 BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
5484
5485 /* Use VTY to verify that the IMSI of the subscr_conn is set */
5486 var charstring regex := "*(IMSI: " & hex2str(g_pars.imsi) & ")*";
5487 f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
5488
5489 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005490
5491 f_perform_clear();
Harald Welteeddf0e92020-06-21 19:42:15 +02005492}
5493testcase TC_common_id() runs on test_CT {
5494 var MSC_ConnHdlr vc_conn;
5495 f_init(1, true);
5496 f_sleep(1.0);
5497 vc_conn := f_start_handler(refers(f_tc_common_id));
5498 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005499 f_shutdown_helper();
Harald Welteeddf0e92020-06-21 19:42:15 +02005500}
5501
Harald Weltee3bd6582018-01-31 22:51:25 +01005502private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005503 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005504 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005505 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005506
Harald Weltee3bd6582018-01-31 22:51:25 +01005507 /* send the single message we want to send */
5508 f_rsl_send_l3(l3);
5509}
5510
5511private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr {
5512 timer T := sec;
5513 var PDU_BSSAP bssap;
Harald Welte898113b2018-01-31 18:32:21 +01005514 T.start;
5515 alt {
Harald Weltee3bd6582018-01-31 22:51:25 +01005516 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap {
5517 setverdict(fail, "Unexpected BSSMAP ", bssap);
Daniel Willmannafce8662018-07-06 23:11:32 +02005518 mtc.stop;
Harald Welte898113b2018-01-31 18:32:21 +01005519 }
5520 [] T.timeout {
5521 setverdict(pass);
5522 }
5523 }
5524}
5525
Harald Weltee3bd6582018-01-31 22:51:25 +01005526/* unsolicited ASSIGNMENT FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5527private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
5528 f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
5529 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005530 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005531}
Harald Welte898113b2018-01-31 18:32:21 +01005532testcase TC_unsol_ass_fail() runs on test_CT {
5533 var MSC_ConnHdlr vc_conn;
5534 f_init(1, true);
5535 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005536 vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
Harald Welte898113b2018-01-31 18:32:21 +01005537 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005538 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005539}
Harald Welte552620d2017-12-16 23:21:36 +01005540
Harald Welteea99a002018-01-31 20:46:43 +01005541
5542/* unsolicited ASSIGNMENT COMPLETE (without ASSIGN) from MS shouldn't bring BSC down */
5543private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005544 f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
5545 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005546 f_perform_clear();
Harald Welteea99a002018-01-31 20:46:43 +01005547}
5548testcase TC_unsol_ass_compl() runs on test_CT {
5549 var MSC_ConnHdlr vc_conn;
5550 f_init(1, true);
5551 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005552 vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
Harald Welteea99a002018-01-31 20:46:43 +01005553 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005554 f_shutdown_helper();
Harald Welteea99a002018-01-31 20:46:43 +01005555}
5556
5557
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005558/* unsolicited HANDOVER FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5559private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005560 f_est_single_l3(ts_RRM_HandoverFailure('00'O));
5561 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005562 f_perform_clear();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005563}
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005564testcase TC_unsol_ho_fail() runs on test_CT {
5565 var MSC_ConnHdlr vc_conn;
5566 f_init(1, true);
5567 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005568 vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005569 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005570 f_shutdown_helper();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005571}
5572
5573
Harald Weltee3bd6582018-01-31 22:51:25 +01005574/* short message from MS should be ignored */
5575private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005576 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005577 f_create_chan_and_exp();
Harald Weltee3bd6582018-01-31 22:51:25 +01005578 /* we should now have a COMPL_L3 at the MSC */
Harald Weltee3bd6582018-01-31 22:51:25 +01005579
5580 /* send short message */
5581 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
5582 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005583 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005584}
5585testcase TC_err_82_short_msg() runs on test_CT {
5586 var MSC_ConnHdlr vc_conn;
5587 f_init(1, true);
5588 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005589 vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
Harald Weltee3bd6582018-01-31 22:51:25 +01005590 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005591 f_shutdown_helper();
Harald Weltee3bd6582018-01-31 22:51:25 +01005592}
5593
5594
Harald Weltee9e02e42018-01-31 23:36:25 +01005595/* 24.008 8.4 Unknown message must trigger RR STATUS */
5596private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
5597 f_est_single_l3(ts_RRM_UL_REL('00'O));
5598 timer T := 3.0
5599 alt {
5600 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
5601 setverdict(pass);
5602 }
5603 [] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
Harald Welte458fd372018-03-21 11:26:23 +01005604 [] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
Harald Weltee9e02e42018-01-31 23:36:25 +01005605 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005606 f_perform_clear();
Harald Weltee9e02e42018-01-31 23:36:25 +01005607}
5608testcase TC_err_84_unknown_msg() runs on test_CT {
5609 var MSC_ConnHdlr vc_conn;
5610 f_init(1, true);
5611 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005612 vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
Harald Weltee9e02e42018-01-31 23:36:25 +01005613 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005614 f_shutdown_helper();
Harald Weltee9e02e42018-01-31 23:36:25 +01005615}
5616
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005617/***********************************************************************
5618 * Handover
5619 ***********************************************************************/
5620
Harald Welte94e0c342018-04-07 11:33:23 +02005621/* execute a "bts <0-255> trx <0-255> timeslot <0-7> " command on given Dchan */
5622private function f_vty_ts_action(charstring suffix, integer bts_nr, integer trx_nr, integer ts_nr)
5623runs on test_CT {
5624 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5625 " timeslot "&int2str(ts_nr)&" ";
5626 f_vty_transceive(BSCVTY, cmd & suffix);
5627}
5628
Harald Welte261af4b2018-02-12 21:20:39 +01005629/* 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 +07005630private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
5631 uint8_t bts_nr, uint8_t trx_nr,
5632 in RslChannelNr chan_nr)
5633{
Harald Welte261af4b2018-02-12 21:20:39 +01005634 /* FIXME: resolve those from component-global state */
5635 var integer ts_nr := chan_nr.tn;
5636 var integer ss_nr;
5637 if (ischosen(chan_nr.u.ch0)) {
5638 ss_nr := 0;
5639 } else if (ischosen(chan_nr.u.lm)) {
5640 ss_nr := chan_nr.u.lm.sub_chan;
5641 } else if (ischosen(chan_nr.u.sdcch4)) {
5642 ss_nr := chan_nr.u.sdcch4.sub_chan;
5643 } else if (ischosen(chan_nr.u.sdcch8)) {
5644 ss_nr := chan_nr.u.sdcch8.sub_chan;
5645 } else {
5646 setverdict(fail, "Invalid ChanNr ", chan_nr);
Daniel Willmannafce8662018-07-06 23:11:32 +02005647 mtc.stop;
Harald Welte261af4b2018-02-12 21:20:39 +01005648 }
5649
5650 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5651 " timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005652 f_vty_transceive(pt, cmd & suffix);
Harald Welte261af4b2018-02-12 21:20:39 +01005653}
5654
Neels Hofmeyr91401012019-07-11 00:42:35 +02005655/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
5656 * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor
5657 * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
5658 * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
5659 * pair, not really to a specific BTS number. */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005660private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
5661 in RslChannelNr chan_nr, uint8_t new_bts_nr)
5662{
5663 f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
Harald Welte261af4b2018-02-12 21:20:39 +01005664}
5665
5666/* intra-BSC hand-over between BTS0 and BTS1 */
5667private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02005668 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5669 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte261af4b2018-02-12 21:20:39 +01005670
5671 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5672 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5673
Harald Weltea0630032018-03-20 21:09:55 +01005674 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005675 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Harald Welte261af4b2018-02-12 21:20:39 +01005676
5677 var HandoverState hs := {
5678 rr_ho_cmpl_seen := false,
5679 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005680 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005681 expect_target_tsc := c_BtsParams[1].tsc
Harald Welte261af4b2018-02-12 21:20:39 +01005682 };
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005683 /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005684 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
Harald Welte261af4b2018-02-12 21:20:39 +01005685 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5686 f_rslem_suspend(RSL1_PROC);
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005687
5688 /* From the MGW perspective, a handover is is characterized by
5689 * performing one MDCX operation with the MGW. So we expect to see
5690 * one more MDCX during handover. */
5691 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5692
Harald Welte261af4b2018-02-12 21:20:39 +01005693 alt {
5694 [] as_handover(hs);
Harald Welte261af4b2018-02-12 21:20:39 +01005695 }
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005696
Philipp Maier4dae0652018-11-12 12:03:26 +01005697 /* Since this is an internal handover we expect the BSC to inform the
5698 * MSC about the event */
5699 BSSAP.receive(tr_BSSMAP_HandoverPerformed);
5700
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005701 /* Check the amount of MGCP transactions is still consistant with the
5702 * test expectation */
5703 f_check_mgcp_expectations()
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005704
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005705 var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
5706
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005707 /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
5708 * 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 +02005709 f_verify_encr_info(chan_act);
5710
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005711 f_chan_act_verify_tsc(chan_act, c_BtsParams[1].tsc);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005712
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005713 f_perform_clear(RSL1, RSL1_PROC);
5714
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005715 f_sleep(0.5);
Harald Welte261af4b2018-02-12 21:20:39 +01005716}
5717
5718testcase TC_ho_int() runs on test_CT {
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005719 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte261af4b2018-02-12 21:20:39 +01005720 var MSC_ConnHdlr vc_conn;
5721 f_init(2, true);
5722 f_sleep(1.0);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005723
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005724 pars.expect_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005725
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005726 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005727
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005728 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
Harald Welte261af4b2018-02-12 21:20:39 +01005729 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005730
5731 /* from f_establish_fully() */
5732 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5733 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5734 /* from handover */
5735 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5736 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5737 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5738 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005739 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5740 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005741 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005742 f_shutdown_helper(ho := true);
Harald Welte261af4b2018-02-12 21:20:39 +01005743}
Harald Weltee9e02e42018-01-31 23:36:25 +01005744
Oliver Smith7eabd312021-07-12 14:18:56 +02005745function 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 +02005746 var MSC_ConnHdlr vc_conn;
5747 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5748 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
5749
5750 f_init(2, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02005751 f_vty_encryption_a5(enc_a5);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005752 f_sleep(1.0);
5753
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005754 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005755
5756 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
5757 vc_conn.done;
5758
5759 /* from f_establish_fully() */
5760 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5761 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5762 /* from handover */
5763 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5764 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5765 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5766 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005767 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5768 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005769 f_ctrs_bsc_and_bts_verify();
Oliver Smith7eabd312021-07-12 14:18:56 +02005770 f_vty_encryption_a5_reset();
Oliver Smith39f53072022-10-27 14:44:04 +02005771 f_shutdown_helper(ho := true);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005772}
5773
5774testcase TC_ho_int_a5_0() runs on test_CT {
5775 f_tc_ho_int_a5('01'O);
5776}
5777
5778testcase TC_ho_int_a5_1() runs on test_CT {
5779 f_tc_ho_int_a5('02'O);
5780}
5781
5782testcase TC_ho_int_a5_3() runs on test_CT {
5783 f_tc_ho_int_a5('08'O);
5784}
5785
5786testcase TC_ho_int_a5_4() runs on test_CT {
Oliver Smith7eabd312021-07-12 14:18:56 +02005787 f_tc_ho_int_a5('10'O, "0 1 3 4");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005788}
5789
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005790/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
5791private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
5792 g_pars := f_gen_test_hdlr_pars();
5793 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5794 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005795
5796 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5797 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5798
5799 f_establish_fully(ass_cmd, exp_compl);
5800 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
5801
5802 var HandoverState hs := {
5803 rr_ho_cmpl_seen := false,
5804 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005805 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005806 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005807 };
5808 /* issue hand-over command on VTY */
5809 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
5810 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5811 f_rslem_suspend(RSL1_PROC);
5812
5813 /* From the MGW perspective, a handover is is characterized by
5814 * performing one MDCX operation with the MGW. So we expect to see
5815 * one more MDCX during handover. */
5816 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5817
5818 var RSL_Message rsl;
5819 var PDU_ML3_NW_MS l3;
5820 var RslChannelNr new_chan_nr;
5821 var GsmArfcn arfcn;
5822 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
5823 l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
5824 if (not ischosen(l3.msgs.rrm.handoverCommand)) {
5825 setverdict(fail, "Expected handoverCommand");
5826 mtc.stop;
5827 }
5828 }
5829 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
5830 new_chan_nr, arfcn);
5831
5832 f_rslem_register(0, new_chan_nr, RSL1_PROC);
5833
5834 /* resume processing of RSL DChan messages, which was temporarily suspended
5835 * before performing a hand-over */
5836 f_rslem_resume(RSL1_PROC);
5837 RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
5838
5839 f_sleep(1.0);
5840
5841 /* Handover fails because no HANDO DET appears on the new lchan,
5842 * and the old lchan reports a Radio Link Failure. */
5843 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
5844
5845 var PDU_BSSAP rx_clear_request;
5846 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5847 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5848 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5849
5850 var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
5851
5852 var MgcpCommand mgcp;
5853 interleave {
5854 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
5855 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005856 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005857 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005858 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005859 }
5860 [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005861 [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005862 RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005863 f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005864 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005865 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5866 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5867 }
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005868 }
5869
5870 f_sleep(0.5);
5871 setverdict(pass);
5872}
5873testcase TC_ho_int_radio_link_failure() runs on test_CT {
5874 var MSC_ConnHdlr vc_conn;
5875 f_init(2, true);
5876 f_sleep(1.0);
5877
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005878 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005879
5880 vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
5881 vc_conn.done;
5882
5883 /* from f_establish_fully() */
5884 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5885 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5886 /* from handover */
5887 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5888 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
5889 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5890 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005891 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5892 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005893 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02005894 f_shutdown_helper(ho := true);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005895}
5896
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005897/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005898private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005899 var MgcpCommand mgcp;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005900 var template MgcpResponse mgcp_resp;
5901 var MGCP_RecvFrom mrf;
5902 var template MgcpMessage msg_resp;
5903 var template MgcpMessage msg_dlcx := {
5904 command := tr_DLCX()
5905 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005906
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005907 if (g_pars.aoip) {
5908 MGCP.receive(tr_DLCX()) -> value mgcp {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005909 log("Got first DLCX: ", mgcp);
5910 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005911 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005912
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005913 MGCP.receive(tr_DLCX()) -> value mgcp {
5914 log("Got second DLCX: ", mgcp);
5915 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
5916 };
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005917 } else {
5918 /* For SCCPLite, BSC doesn't handle the MSC-side */
5919 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
5920 log("Got first DLCX: ", mrf.msg.command);
5921 msg_resp := {
5922 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
5923 }
5924 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
5925 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005926 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005927}
5928
Oliver Smithc9a5f532022-10-21 11:32:23 +02005929private function f_ho_out_of_this_bsc(template (omit) BSSMAP_oldToNewBSSIEs exp_oldToNewBSSIEs := omit,
5930 boolean skip_meas_rep := false) runs on MSC_ConnHdlr {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005931
Oliver Smithc9a5f532022-10-21 11:32:23 +02005932 if (not skip_meas_rep) {
5933 var NcellReports neighbor_rep := {
5934 { rxlev := 20, bcch_freq := 0, bsic := 11 }
5935 };
5936 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
5937 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
5938 l3_mr, 0));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005939
Oliver Smithc9a5f532022-10-21 11:32:23 +02005940 BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
5941 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005942
5943 f_sleep(0.5);
5944 /* The MSC negotiates Handover Request and Handover Request Ack with
5945 * the other BSS and comes back with a BSSMAP Handover Command
5946 * containing an RR Handover Command coming from the target BSS... */
5947
5948 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5949 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
5950 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5951 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
5952 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
5953
5954 /* expect the Handover Command to go out on RR */
5955 var RSL_Message rsl_ho_cmd
5956 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
5957 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
5958 var RSL_IE_Body rsl_ho_cmd_l3;
5959 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
5960 log("RSL message contains no L3 Info IE, expected RR Handover Command");
5961 setverdict(fail);
5962 } else {
5963 log("Found L3 Info: ", rsl_ho_cmd_l3);
5964 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
5965 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
5966 setverdict(fail);
5967 } else {
5968 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
5969 setverdict(pass);
5970 }
5971 }
5972
5973 /* When the other BSS has reported a completed handover, this side is
5974 * torn down. */
5975
5976 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_HANDOVER_SUCCESSFUL;
5977 var BssmapCause cause := enum2int(cause_val);
5978 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5979
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005980 f_expect_dlcx_conns();
Pau Espin Pedrol06199952021-06-15 11:30:00 +02005981
5982 interleave {
5983 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
5984 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
5985 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005986 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5987 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5988 }
Pau Espin Pedrol06199952021-06-15 11:30:00 +02005989 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005990 setverdict(pass);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005991}
5992
5993private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
5994 g_pars := f_gen_test_hdlr_pars();
5995 var PDU_BSSAP ass_req := f_gen_ass_req();
5996 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5997 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5998 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5999 f_establish_fully(ass_req, exp_compl);
6000
6001 f_ho_out_of_this_bsc();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006002}
6003testcase TC_ho_out_of_this_bsc() runs on test_CT {
6004 var MSC_ConnHdlr vc_conn;
6005
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006006 f_init_vty();
6007 f_bts_0_cfg(BSCVTY,
6008 {"neighbor-list mode automatic",
6009 "handover 1",
6010 "handover algorithm 2",
6011 "handover2 window rxlev averaging 1",
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006012 "no neighbors",
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01006013 "neighbor lac 99 arfcn 123 bsic any"});
6014 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6015
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006016 f_init(1, true);
6017 f_sleep(1.0);
6018
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006019 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006020
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006021 vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
6022 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006023
6024 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6025 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6026 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6027 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6028 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6029 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
6030 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006031 f_shutdown_helper(ho := true);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006032}
6033
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006034private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6035 template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
Vadim Yanitskiy2ef6a2f2020-10-08 23:17:32 +07006036 template (present) OCT1 dlci := ?,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006037 octetstring l3 := '0123456789'O)
6038runs on MSC_ConnHdlr {
Neels Hofmeyr43654812020-09-25 01:35:35 +02006039 /* The old lchan and conn should still be active. See that arbitrary L3
6040 * is still going through. */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006041 rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
Neels Hofmeyr43654812020-09-25 01:35:35 +02006042 var template PDU_BSSAP exp_data := {
6043 discriminator := '1'B,
6044 spare := '0000000'B,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07006045 dlci := dlci,
6046 lengthIndicator := lengthof(l3),
Neels Hofmeyr43654812020-09-25 01:35:35 +02006047 pdu := {
6048 dtap := l3
6049 }
6050 };
6051 BSSAP.receive(exp_data);
6052 setverdict(pass);
6053}
6054
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006055private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
6056 template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006057 template (value) OCT1 dlci := '00'O,
6058 octetstring l3 := '0123456789'O)
6059runs on MSC_ConnHdlr {
6060 BSSAP.send(PDU_BSSAP:{
6061 discriminator := '1'B,
6062 spare := '0000000'B,
6063 dlci := dlci,
6064 lengthIndicator := lengthof(l3),
6065 pdu := {
6066 dtap := l3
6067 }
6068 });
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00006069 rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07006070 setverdict(pass);
6071}
6072
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006073/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
6074 * simply never sends a BSSMAP Handover Command. */
6075private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006076 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006077
6078 var PDU_BSSAP ass_req := f_gen_ass_req();
6079 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6080 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6081 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6082 f_establish_fully(ass_req, exp_compl);
6083
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006084 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006085 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6086
6087 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6088
6089 /* osmo-bsc should time out 10 seconds after the handover started.
6090 * Let's give it a bit extra. */
6091 f_sleep(15.0);
6092
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006093 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006094 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006095 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006096}
6097testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
6098 var MSC_ConnHdlr vc_conn;
6099
6100 f_init(1, true);
6101 f_sleep(1.0);
6102
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006103 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006104
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006105 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
6106 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006107
6108 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6109 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6110 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6111 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6112 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6113 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6114 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006115 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006116}
6117
6118/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
6119 * RR Handover Failure. */
6120private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006121 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006122
6123 var PDU_BSSAP ass_req := f_gen_ass_req();
6124 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6125 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6126 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6127 f_establish_fully(ass_req, exp_compl);
6128
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006129 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006130 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6131
6132 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6133
6134 f_sleep(0.5);
6135 /* The MSC negotiates Handover Request and Handover Request Ack with
6136 * the other BSS and comes back with a BSSMAP Handover Command
6137 * containing an RR Handover Command coming from the target BSS... */
6138
6139 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6140 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6141 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6142 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6143 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6144
6145 /* expect the Handover Command to go out on RR */
6146 var RSL_Message rsl_ho_cmd
6147 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6148 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6149 var RSL_IE_Body rsl_ho_cmd_l3;
6150 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6151 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6152 setverdict(fail);
6153 } else {
6154 log("Found L3 Info: ", rsl_ho_cmd_l3);
6155 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6156 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6157 setverdict(fail);
6158 } else {
6159 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6160 setverdict(pass);
6161 }
6162 }
6163
6164 f_sleep(0.2);
6165 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
6166
6167 /* Should tell the MSC about the failure */
6168 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6169
6170 f_sleep(1.0);
6171
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006172 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006173 f_sleep(1.0);
6174
6175 setverdict(pass);
6176 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006177 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006178}
6179testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
6180 var MSC_ConnHdlr vc_conn;
6181
6182 f_init(1, true);
6183 f_sleep(1.0);
6184
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006185 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006186
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006187 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
6188 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006189
6190 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6191 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6192 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6193 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6194 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6195 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
6196 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006197 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006198}
6199
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006200/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
6201 * (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 +02006202 * and the lchan is released. */
6203private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006204 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006205
6206 var PDU_BSSAP ass_req := f_gen_ass_req();
6207 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6208 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6209 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6210 f_establish_fully(ass_req, exp_compl);
6211
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006212 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006213 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6214
6215 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6216
6217 f_sleep(0.5);
6218 /* The MSC negotiates Handover Request and Handover Request Ack with
6219 * the other BSS and comes back with a BSSMAP Handover Command
6220 * containing an RR Handover Command coming from the target BSS... */
6221
6222 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6223 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6224 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6225 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6226 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6227
6228 /* expect the Handover Command to go out on RR */
6229 var RSL_Message rsl_ho_cmd
6230 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6231 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6232 var RSL_IE_Body rsl_ho_cmd_l3;
6233 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6234 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6235 setverdict(fail);
6236 } else {
6237 log("Found L3 Info: ", rsl_ho_cmd_l3);
6238 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6239 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6240 setverdict(fail);
6241 } else {
6242 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6243 setverdict(pass);
6244 }
6245 }
6246
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006247 /* We get neither success nor failure report from the remote BSS. Eventually T8 times out and we run into 3GPP
6248 * TS 48.008 3.1.5.3.3 "Abnormal Conditions": Clear Request should go to the MSC, and RR should be released
6249 * after Clear Command */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006250
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006251 var PDU_BSSAP rx_clear_request;
Neels Hofmeyre1797aa2019-07-09 19:34:04 +02006252 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
6253 log("Got BSSMAP Clear Request");
6254 /* Instruct BSC to clear channel */
6255 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6256 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6257
6258 var MgcpCommand mgcp;
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006259 interleave {
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01006260 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
6261 log("Got Deact SACCH");
6262 }
Harald Welte924b6ea2019-02-04 01:05:34 +01006263 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
Neels Hofmeyr211169d2018-11-07 00:37:29 +01006264 log("Got RR Release");
6265 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02006266 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006267 log("Got RF Chan Rel");
6268 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02006269 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006270 }
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006271 }
6272
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006273 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006274 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006275 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006276
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006277 setverdict(pass);
6278 f_sleep(1.0);
6279}
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006280testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006281 var MSC_ConnHdlr vc_conn;
6282
6283 f_init(1, true);
6284 f_sleep(1.0);
6285
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006286 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006287
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006288 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006289 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006290
6291 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6292 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6293 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6294 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6295 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6296 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6297 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006298 f_shutdown_helper(ho := true);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006299}
6300
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006301private 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 +01006302 var PDU_BSSAP rx_bssap;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006303 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6304 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6305 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6306 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6307 * before we get started. */
6308 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6309 f_rslem_register(0, new_chan_nr);
6310 g_chan_nr := new_chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06006311 var uint3_t expect_target_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006312 f_sleep(1.0);
6313
6314 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6315 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006316 var default as_media := activate(as_Media());
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006317
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01006318 var PDU_BSSAP ho_req := f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
6319 cell_id_source := g_pars.cell_id_source,
6320 oldToNewBSSIEs := oldToNewBSSIEs,
6321 enc := g_pars.encr);
6322 if (g_pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr) {
6323 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, ho_req));
6324 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6325 } else {
6326 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, omit));
6327 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6328 BSSAP.send(ho_req);
6329 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006330
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006331 alt {
6332 [] BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap {
6333 if (g_pars.expect_ho_fail) {
6334 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6335 "Expected Handover Request to fail, but got Handover Request Ack")
6336 }
6337 }
6338 [] BSSAP.receive(tr_BSSMAP_HandoverFailure) -> value rx_bssap {
6339 if (not g_pars.expect_ho_fail) {
6340 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6341 "Expected Handover Request to succeed, but got Handover Failure")
6342 }
6343 // TODO: evaluate correct cause value. But osmo-bsc doesn't seem to send meaningful causes yet!
6344 // For now just accept any cause.
6345 BSSAP.receive(tr_BSSMAP_ClearRequest);
6346 setverdict(pass);
6347 return;
6348 }
6349 }
6350
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006351 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6352
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006353 /* we're sure that the channel activation is done now, verify the parameters in it */
6354 var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
6355 f_verify_encr_info(chan_act);
6356 f_chan_act_verify_tsc(chan_act, expect_target_tsc);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006357
Neels Hofmeyr46e16e52022-02-23 17:04:00 +01006358 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.codecList)) {
6359 if (not g_pars.aoip) {
6360 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6361 "handoverRequestAck: Expected no Speech Codec List (BSS Supported), because this is not AoIP");
6362 }
6363 /* TODO: check actual codecs? */
6364 } else {
6365 if (g_pars.aoip) {
6366 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6367 "handoverRequestAck: Expected Speech Codec List (BSS Supported), but none found");
6368 }
6369 }
6370
6371 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.speechCodec)) {
6372 if (not g_pars.aoip) {
6373 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6374 "handoverRequestAck: Expected no Speech Codec (Chosen), because this is not AoIP");
6375 }
6376 /* TODO: check actual codec? */
6377 } else {
6378 if (g_pars.aoip) {
6379 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6380 "handoverRequestAck: Expected Speech Codec (Chosen), but none found");
6381 }
6382 }
6383
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006384 var octetstring ho_command_str;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006385 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6386 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6387 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6388 log("L3 Info in HO Request Ack is ", ho_command);
6389
6390 var GsmArfcn arfcn;
6391 var RslChannelNr actual_new_chan_nr;
6392 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6393 actual_new_chan_nr, arfcn);
6394
6395 if (actual_new_chan_nr != new_chan_nr) {
6396 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6397 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6398 setverdict(fail);
6399 return;
6400 }
6401 log("Handover Command chan_nr is", actual_new_chan_nr);
6402
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006403 var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
6404 if (not match(got_tsc, expect_target_tsc)) {
6405 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6406 expect_target_tsc, " got ", got_tsc);
6407 mtc.stop;
6408 } else {
6409 log("handoverCommand: verified TSC = ", got_tsc);
6410 }
6411
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006412 /* Check the Cipher Mode Setting IE (shall be present during inter-RAT handover) */
6413 if (ispresent(ho_command.msgs.rrm.handoverCommand.cipherModeSetting)) {
6414 var CipherModeSetting_TV cms := ho_command.msgs.rrm.handoverCommand.cipherModeSetting;
6415 var template (present) CipherModeSetting_TV tr_cms := {
6416 sC := '0'B, /* no ciphering by default */
6417 algorithmIdentifier := '000'B,
6418 elementIdentifier := ?
6419 };
6420 if (ispresent(g_pars.encr) and g_pars.encr.enc_alg_expect != '01'O) { /* A5/N */
6421 tr_cms.algorithmIdentifier := f_cipher_mode_bssmap_to_rr(g_pars.encr.enc_alg_expect);
6422 tr_cms.sC := '1'B;
6423 }
6424 if (not match(cms, tr_cms)) {
6425 setverdict(fail, "RR Handover Command: unexpected Cipher Mode Setting IE: ",
6426 cms, ", expected: ", tr_cms);
6427 }
6428 } else {
6429 setverdict(fail, "RR Handover Command: Cipher Mode Setting IE is not present");
6430 }
6431
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006432 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6433 * tells the MS to handover to the new lchan. Here comes the new MS on
6434 * the new lchan with a Handover RACH: */
6435
6436 /* send handover detect */
6437
6438 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6439
6440 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6441
6442 /* send handover complete over the new channel */
6443
6444 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_HandoverComplete('00'O));
6445 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
6446 enc_PDU_ML3_MS_NW(l3_tx)));
6447
6448 BSSAP.receive(tr_BSSMAP_HandoverComplete);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006449 deactivate(as_media);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006450 setverdict(pass);
6451}
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006452
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006453private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006454 var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006455 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
6456 if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
6457 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006458 }
6459 if (g_pars.exp_fast_return) {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006460 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006461 } else {
6462 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006463 }
6464 f_ho_into_this_bsc(id, oldToNewBSSIEs);
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006465 if (g_pars.expect_ho_fail) {
6466 f_perform_clear_no_lchan();
6467 } else {
6468 f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
6469 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006470 setverdict(pass);
6471}
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006472function 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 +01006473 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006474
6475 f_init(1, true);
6476 f_sleep(1.0);
6477
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006478 f_vty_encryption_a5(vty_a5_cfg);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006479 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006480
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006481 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6482 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006483
6484 vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
6485 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006486
6487 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006488 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006489 if (pars.expect_ho_fail) {
6490 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6491 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:failed");
6492 } else {
6493 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6494 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
6495 }
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006496 f_ctrs_bsc_and_bts_verify();
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006497
6498 f_vty_encryption_a5_reset();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006499}
6500
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006501testcase TC_ho_into_this_bsc() runs on test_CT {
6502 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6503 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006504 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006505}
6506
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006507function f_tc_ho_into_this_bsc_a5(TestHdlrEncrParams encr, charstring vty_a5_cfg := VTY_A5_DEFAULT,
6508 boolean expect_fail := false) runs on test_CT {
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006509 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006510 pars.encr := encr;
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006511 pars.expect_ho_fail := expect_fail;
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006512 f_tc_ho_into_this_bsc_main(pars, vty_a5_cfg);
Oliver Smith39f53072022-10-27 14:44:04 +02006513 f_shutdown_helper(ho := true);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006514}
6515
6516testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006517 f_tc_ho_into_this_bsc_a5(f_encr_params('01'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006518}
6519
6520testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006521 f_tc_ho_into_this_bsc_a5(f_encr_params('02'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006522}
6523
6524testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006525 f_tc_ho_into_this_bsc_a5(f_encr_params('08'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006526}
6527
6528testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006529 f_tc_ho_into_this_bsc_a5(f_encr_params('10'O, kc128 := true), "3 4");
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006530}
6531
Neels Hofmeyr1951be22022-02-16 16:21:07 +01006532/* Report: in inter-BSC incoming handover, when the MSC omits the Chosen Encryption Algorithm IE in the Handover Request
6533 * message, then osmo-bsc starts an unencrypted lchan even if A5/0 is not permitted.
6534 *
6535 * This test verifies that the Encryption Information is present in the Channel Activation when the Chosen Enc Alg is
6536 * omitted.
6537 *
6538 * Related: SYS#5839
6539 */
6540testcase TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() runs on test_CT {
6541 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O, alg_chosen := omit));
6542}
6543
6544testcase TC_ho_into_this_bsc_a5_1_3() runs on test_CT {
6545 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O));
6546}
6547
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006548/* Send a permitted algo mask that does not intersect with osmo-bsc.cfg */
6549testcase TC_ho_into_this_bsc_a5_mismatch() runs on test_CT {
6550 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '18'O, alg_expect := '10'O), "0 1",
6551 expect_fail := true); // 0x18 = A5/3 and A5/4
6552}
6553
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006554testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
6555 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6556 pars.host_aoip_tla := "::6";
6557 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02006558 f_shutdown_helper(ho := true);
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006559}
6560
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006561/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006562 to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006563 channel is later released (RR CHannel Release), should trigger inclusion of
6564 IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
6565 neighbors. */
6566testcase TC_srvcc_eutran_to_geran() runs on test_CT {
6567 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6568 pars.last_used_eutran_plmn := '323454'O;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006569 pars.exp_fast_return := true;
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006570 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006571
6572 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6573 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6574 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006575 f_shutdown_helper(ho := true);
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006576}
6577
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006578/* Same as TC_srvcc_eutran_to_geran, but enables ciphering on the target channel. */
6579testcase TC_srvcc_eutran_to_geran_a5_3() runs on test_CT {
6580 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6581 pars.encr := f_encr_params('08'O); /* only A5/3 */
6582 pars.last_used_eutran_plmn := '323454'O;
6583 pars.exp_fast_return := true;
6584 f_tc_ho_into_this_bsc_main(pars);
6585
6586 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6587 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6588 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006589 f_shutdown_helper(ho := true);
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006590}
6591
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006592/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
6593 on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
6594 list when the channel is released. */
6595testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
6596 f_init_vty();
6597 f_vty_allow_srvcc_fast_return(true, 0)
6598
6599 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6600 pars.last_used_eutran_plmn := '323454'O;
6601 pars.exp_fast_return := false;
6602 f_tc_ho_into_this_bsc_main(pars);
6603 f_vty_allow_srvcc_fast_return(false, 0);
6604 f_shutdown_helper();
6605}
6606
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01006607/* Same as TC_srvcc_eutran_to_geran, but using SAI as serving Cell Identifier. SYS#5838 */
6608testcase TC_srvcc_eutran_to_geran_src_sai() runs on test_CT {
6609 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6610 pars.last_used_eutran_plmn := '323454'O;
6611 pars.cell_id_source := valueof(ts_CellID_SAI('123456'O, 300, 444));
6612 f_tc_ho_into_this_bsc_main(pars);
6613
6614 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6615 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6616 f_ctrs_bsc_and_bts_verify();
6617 f_shutdown_helper();
6618}
6619
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006620private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
6621 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
6622 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
6623 f_ho_into_this_bsc(id, oldToNewBSSIEs);
6624 f_ho_out_of_this_bsc(oldToNewBSSIEs);
6625 setverdict(pass);
6626}
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006627
6628private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
6629 runs on test_CT {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006630 var MSC_ConnHdlr vc_conn;
6631 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6632
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006633 f_init_vty();
6634 f_bts_0_cfg(BSCVTY,
6635 {"neighbor-list mode automatic",
6636 "handover 1",
6637 "handover algorithm 2",
6638 "handover2 window rxlev averaging 1",
6639 "no neighbors",
6640 "neighbor lac 99 arfcn 123 bsic any"});
6641 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6642
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006643 f_init(1, true);
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006644 if (disable_fast_return) {
6645 f_vty_allow_srvcc_fast_return(true, 0);
6646 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006647 f_sleep(1.0);
6648
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006649 f_ctrs_bsc_and_bts_handover_init();
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006650
6651 pars.last_used_eutran_plmn := '323454'O;
6652 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6653 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
6654
6655 vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
6656 vc_conn.done;
6657
6658 f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
6659 f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
6660 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
6661 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
6662 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
6663 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006664
6665 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
6666 f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006667 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006668
6669 if (disable_fast_return) {
6670 f_vty_allow_srvcc_fast_return(false, 0);
6671 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006672 f_shutdown_helper();
6673}
6674
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006675/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
6676 BSS Information" IE with "Last Used E-UTRAN PLMN Id".
6677 Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
6678 IE with "Last Used E-UTRAN PLMN Id" from first step. */
6679testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
6680 f_tc_srvcc_eutran_to_geran_ho_out_main(false);
6681}
6682/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
6683 * independently of fast-reture allowed/forbidden in local BTS */
6684testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
6685 f_tc_srvcc_eutran_to_geran_ho_out_main(true);
6686}
6687
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006688private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
6689 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6690 f_rslem_register(0, new_chan_nr);
6691 g_chan_nr := new_chan_nr;
6692 f_sleep(1.0);
6693
6694 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6695 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6696 activate(as_Media());
6697
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006698 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006699 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006700 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006701
6702 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6703
6704 var PDU_BSSAP rx_bssap;
6705 var octetstring ho_command_str;
6706
6707 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6708
6709 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6710 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6711 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6712 log("L3 Info in HO Request Ack is ", ho_command);
6713
6714 var GsmArfcn arfcn;
6715 var RslChannelNr actual_new_chan_nr;
6716 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6717 actual_new_chan_nr, arfcn);
6718
6719 if (actual_new_chan_nr != new_chan_nr) {
6720 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6721 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6722 setverdict(fail);
6723 return;
6724 }
6725 log("Handover Command chan_nr is", actual_new_chan_nr);
6726
Neels Hofmeyr61ca08d2019-05-06 23:52:22 +02006727 /* For deterministic test results, give some time for the MGW endpoint to be configured */
6728 f_sleep(1.0);
6729
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006730 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6731 * tells the MS to handover to the new lchan. In this case, the MS
6732 * reports a Handover Failure to the old BSS, which forwards a BSSMAP
6733 * Handover Failure to the MSC. The procedure according to 3GPP TS
6734 * 48.008 3.1.5.3.2 "Handover Failure" is then that the MSC sends a
6735 * BSSMAP Clear Command: */
6736
6737 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6738 var BssmapCause cause := enum2int(cause_val);
6739 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6740
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006741 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006742 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006743 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006744
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006745 setverdict(pass);
6746 f_sleep(1.0);
6747
6748 setverdict(pass);
6749}
6750testcase TC_ho_in_fail_msc_clears() runs on test_CT {
6751 var MSC_ConnHdlr vc_conn;
6752 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6753
6754 f_init(1, true);
6755 f_sleep(1.0);
6756
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006757 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006758
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006759 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6760 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006761
6762 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
6763 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006764
6765 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6766 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6767 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6768 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6769 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006770 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006771}
6772
6773private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
6774 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6775 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6776 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6777 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6778 * before we get started. */
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
6817 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6818 * tells the MS to handover to the new lchan. Here comes the new MS on
6819 * the new lchan with a Handover RACH: */
6820
6821 /* send handover detect */
6822
6823 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6824
6825 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6826
6827 /* The MSC chooses to clear the connection now, maybe we got the
6828 * Handover RACH on the new cell but the MS still signaled Handover
6829 * Failure to the old BSS? */
6830
6831 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6832 var BssmapCause cause := enum2int(cause_val);
6833 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6834
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006835 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006836 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006837 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006838
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006839 f_sleep(1.0);
6840}
6841testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
6842 var MSC_ConnHdlr vc_conn;
6843 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6844
6845 f_init(1, true);
6846 f_sleep(1.0);
6847
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006848 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006849
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006850 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6851 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006852
6853 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
6854 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006855
6856 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6857 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6858 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6859 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6860 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02006861 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006862}
6863
6864/* The new BSS's lchan times out before the MSC decides that handover failed. */
6865private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
6866 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6867 f_rslem_register(0, new_chan_nr);
6868 g_chan_nr := new_chan_nr;
6869 f_sleep(1.0);
6870
6871 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6872 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr9b320c12022-04-07 00:19:01 +02006873 activate(as_Media(fail_on_dlcx := false));
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006874
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006875 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006876 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006877 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006878
6879 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6880
6881 var PDU_BSSAP rx_bssap;
6882 var octetstring ho_command_str;
6883
6884 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6885
6886 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6887 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6888 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6889 log("L3 Info in HO Request Ack is ", ho_command);
6890
6891 var GsmArfcn arfcn;
6892 var RslChannelNr actual_new_chan_nr;
6893 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6894 actual_new_chan_nr, arfcn);
6895
6896 if (actual_new_chan_nr != new_chan_nr) {
6897 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6898 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6899 setverdict(fail);
6900 return;
6901 }
6902 log("Handover Command chan_nr is", actual_new_chan_nr);
6903
6904 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6905 * tells the MS to handover to the new lchan. But the MS never shows up
6906 * on the new lchan. */
6907
6908 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6909
6910 /* Did osmo-bsc also send a Clear Request? */
6911 timer T := 0.5;
6912 T.start;
6913 alt {
6914 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
6915 [] T.timeout { }
6916 }
6917
6918 /* MSC plays along with a Clear Command (no matter whether osmo-bsc
6919 * asked for it, this is a Handover Failure after all). */
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);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006930}
6931testcase TC_ho_in_fail_no_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_no_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:error");
6948 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6949 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
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/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
6955private function f_tc_ho_in_fail_no_detect2(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);
Neels Hofmeyr9b320c12022-04-07 00:19:01 +02006963 activate(as_Media(fail_on_dlcx := false));
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 /* MSC plays dumb and sends no Clear Command */
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007001 var PDU_BSSAP rx_clear_request;
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02007002
7003 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request {
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007004 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
7005 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
7006 };
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02007007 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007008 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007009 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02007010
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007011 f_sleep(1.0);
7012}
7013testcase TC_ho_in_fail_no_detect2() runs on test_CT {
7014 var MSC_ConnHdlr vc_conn;
7015 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7016
7017 f_init(1, true);
7018 f_sleep(1.0);
7019
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007020 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007021
Neels Hofmeyr90f80962020-06-12 16:16:55 +02007022 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
7023 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007024
7025 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
7026 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007027
7028 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7029 f_ctrs_bsc_and_bts_add(0, "handover:error");
7030 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
7031 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
7032 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007033 f_shutdown_helper(ho := true);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01007034}
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01007035
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007036/* An incoming inter-BSC HO can either issue the Handover Request message attached to the initial SCCP N-Connect (as in
7037 * the other tests we have so far), or the first CR can be "empty" with the BSSAP request following later. Test the
7038 * empty N-Connect case. */
7039testcase TC_ho_into_this_bsc_sccp_cr_without_bssap() runs on test_CT {
7040 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7041 pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr := false;
7042 f_tc_ho_into_this_bsc_main(pars);
Oliver Smith39f53072022-10-27 14:44:04 +02007043 f_shutdown_helper(ho := true);
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01007044}
7045
Neels Hofmeyr91401012019-07-11 00:42:35 +02007046type record of charstring Commands;
7047
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007048private function f_bts_0_cfg(TELNETasp_PT pt, Commands cmds := {})
Neels Hofmeyr91401012019-07-11 00:42:35 +02007049{
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007050 f_vty_enter_cfg_bts(pt, 0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007051 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007052 f_vty_transceive(pt, cmds[i]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007053 }
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007054 f_vty_transceive(pt, "end");
Neels Hofmeyr91401012019-07-11 00:42:35 +02007055}
7056
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01007057private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
7058{
7059 f_vty_enter_cfg_cs7_inst(pt, 0);
7060 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
7061 f_vty_transceive(pt, cmds[i]);
7062 }
7063 f_vty_transceive(pt, "end");
7064}
7065
Neels Hofmeyr91401012019-07-11 00:42:35 +02007066private function f_probe_for_handover(charstring log_label,
7067 charstring log_descr,
7068 charstring handover_vty_cmd,
7069 boolean expect_handover,
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007070 boolean is_inter_bsc_handover := false,
7071 template uint3_t expect_target_tsc := ?)
Neels Hofmeyr91401012019-07-11 00:42:35 +02007072runs on MSC_ConnHdlr
7073{
Neels Hofmeyrb3fc8982020-05-11 00:16:42 +02007074 /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
7075 * lchans to be established on bts 1 or bts 2. */
7076 f_rslem_suspend(RSL1_PROC);
7077 f_rslem_suspend(RSL2_PROC);
7078
Neels Hofmeyr91401012019-07-11 00:42:35 +02007079 var RSL_Message rsl;
7080
7081 var charstring log_msg := " (expecting handover)"
7082 if (not expect_handover) {
7083 log_msg := " (expecting NO handover)";
7084 }
7085 log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg);
7086 f_vty_transceive(BSCVTY, handover_vty_cmd);
7087
Neels Hofmeyr91401012019-07-11 00:42:35 +02007088 timer T := 2.0;
7089 T.start;
7090
7091 alt {
7092 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
7093 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
7094 log("Rx L3 from net: ", l3);
7095 if (ischosen(l3.msgs.rrm.handoverCommand)) {
7096 var RslChannelNr new_chan_nr;
7097 var GsmArfcn arfcn;
7098 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
7099 new_chan_nr, arfcn);
7100 log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
7101 log(l3.msgs.rrm.handoverCommand);
7102
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007103 /* Verify correct TSC in handoverCommand */
7104 var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
7105 if (not match(got_tsc, expect_target_tsc)) {
7106 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
7107 expect_target_tsc, " got ", got_tsc);
7108 mtc.stop;
7109 } else {
7110 log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
7111 expect_target_tsc, ")");
7112 }
7113
Neels Hofmeyr91401012019-07-11 00:42:35 +02007114 /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
7115 * matter on which BTS it really is, we're not going to follow through an entire handover
7116 * anyway. */
7117 f_rslem_register(0, new_chan_nr, RSL1_PROC);
7118 f_rslem_resume(RSL1_PROC);
7119 f_rslem_register(0, new_chan_nr, RSL2_PROC);
7120 f_rslem_resume(RSL2_PROC);
7121
7122 if (expect_handover and not is_inter_bsc_handover) {
7123 setverdict(pass);
7124 log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected.");
7125 } else {
7126 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. "
7127 & log_label & ": " & log_descr);
7128 }
7129
7130 log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
7131 /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with
7132 * Handover Failure. */
7133 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
7134
7135 /* target BTS is told to release lchan again; don't care which BTS nor what messages. */
7136 f_sleep(0.5);
7137 RSL1.clear;
7138 RSL2.clear;
7139 log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)");
7140 break;
7141 } else {
7142 repeat;
7143 }
7144 }
7145 [] BSSAP.receive(tr_BSSMAP_HandoverRequired) {
7146 if (expect_handover and is_inter_bsc_handover) {
7147 setverdict(pass);
7148 log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected.");
7149 } else {
7150 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. "
7151 & log_label & ": " & log_descr);
7152 }
7153
7154 log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)");
7155
7156 /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to
7157 * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required,
7158 * setting a short timeout and waiting is the only way. */
7159 log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out...");
7160 f_sleep(1.5);
7161 log("f_probe_for_handover(" & log_label & "): ...done");
7162
7163 break;
7164 }
7165 [] T.timeout {
7166 if (expect_handover) {
7167 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. "
7168 & log_label & ": " & log_descr);
7169 } else {
7170 setverdict(pass);
7171 log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected.");
7172 }
7173 log("f_probe_for_handover(" & log_label & "): done (got no Handover)");
7174 break;
7175 }
7176 }
7177
7178 f_rslem_resume(RSL1_PROC);
7179 f_rslem_resume(RSL2_PROC);
7180 f_sleep(3.0);
7181 RSL.clear;
7182
7183 log("f_probe_for_handover(" & log_label & "): done clearing");
7184}
7185
7186/* Test the effect of various neighbor configuration scenarios:
7187 *
7188 * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0.
7189 * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO.
7190 */
7191private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
7192 g_pars := f_gen_test_hdlr_pars();
7193 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
7194 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007195
7196 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
7197 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
7198
7199 /* Establish lchan at bts 0 */
7200 f_establish_fully(ass_cmd, exp_compl);
7201
7202 /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */
7203 f_vty_enter_cfg_network(BSCVTY);
7204 f_vty_transceive(BSCVTY, "timer T7 1");
7205 f_vty_transceive(BSCVTY, "end");
7206}
7207
7208private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
7209 f_tc_ho_neighbor_config_start();
7210
7211 /*
7212 * bts 0 ARFCN 871 BSIC 10
7213 * bts 1 ARFCN 871 BSIC 11
7214 * bts 2 ARFCN 871 BSIC 12
7215 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7216 */
7217
7218 log("f_tc_ho_neighbor_config: 1. No 'neighbor' config");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007219 f_bts_0_cfg(BSCVTY, {"no neighbors"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007220 f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
7221 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007222 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007223
7224 f_probe_for_handover("1.b", "HO to unknown cell does not start",
7225 "handover any to arfcn 13 bsic 39",
7226 false);
7227
7228 f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error",
7229 "handover any to arfcn 871 bsic 12",
7230 false);
7231
7232 f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
7233 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007234 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007235
7236 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007237}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007238testcase TC_ho_neighbor_config_1() runs on test_CT {
7239 var MSC_ConnHdlr vc_conn;
7240 f_init(3, true, guard_timeout := 60.0);
7241 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007242 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007243 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
7244 vc_conn.done;
7245
7246 /* f_tc_ho_neighbor_config_start() */
7247 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7248 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7249
7250 /* 1.a */
7251 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7252 * handover quickly by sending a Handover Failure message. */
7253 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7254 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7255 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7256 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007257 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7258 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007259
7260 /* 1.b */
7261 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7262 f_ctrs_bsc_and_bts_add(0, "handover:error");
7263
7264 /* 1.c */
7265 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7266 f_ctrs_bsc_and_bts_add(0, "handover:error");
7267
7268 /* 1.d */
7269 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7270 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7271 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7272 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007273 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7274 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007275
7276 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007277 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007278}
7279
Neels Hofmeyr91401012019-07-11 00:42:35 +02007280private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
7281 f_tc_ho_neighbor_config_start();
7282
7283 /*
7284 * bts 0 ARFCN 871 BSIC 10
7285 * bts 1 ARFCN 871 BSIC 11
7286 * bts 2 ARFCN 871 BSIC 12
7287 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7288 */
7289
7290 log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007291 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007292 f_sleep(0.5);
7293
7294 f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
7295 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007296 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007297
7298 f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
7299 "handover any to arfcn 871 bsic 12",
7300 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007301 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007302}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007303testcase TC_ho_neighbor_config_2() runs on test_CT {
7304 var MSC_ConnHdlr vc_conn;
7305 f_init(3, true, guard_timeout := 50.0);
7306 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007307 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007308 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
7309 vc_conn.done;
7310
7311 /* f_tc_ho_neighbor_config_start() */
7312 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7313 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7314
7315 /* 2.a */
7316 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7317 * handover quickly by sending a Handover Failure message. */
7318 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7319 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7320 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7321 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007322 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7323 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007324
7325 /* 2.b */
7326 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7327 f_ctrs_bsc_and_bts_add(0, "handover:error");
7328
7329 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007330 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007331}
7332
Neels Hofmeyr91401012019-07-11 00:42:35 +02007333private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
7334 f_tc_ho_neighbor_config_start();
7335
7336 /*
7337 * bts 0 ARFCN 871 BSIC 10
7338 * bts 1 ARFCN 871 BSIC 11
7339 * bts 2 ARFCN 871 BSIC 12
7340 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7341 */
7342
7343 log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007344 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007345 f_sleep(0.5);
7346
7347 f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor",
7348 "handover any to arfcn 871 bsic 11",
7349 false);
7350 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",
7351 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007352 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007353 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007354}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007355testcase TC_ho_neighbor_config_3() runs on test_CT {
7356 var MSC_ConnHdlr vc_conn;
7357 f_init(3, true, guard_timeout := 50.0);
7358 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007359 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007360 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
7361 vc_conn.done;
7362
7363 /* f_tc_ho_neighbor_config_start() */
7364 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7365 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7366
7367 /* 3.a */
7368 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7369 f_ctrs_bsc_and_bts_add(0, "handover:error");
7370
7371 /* 3.b */
7372 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7373 * handover quickly by sending a Handover Failure message. */
7374 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7375 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7376 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7377 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007378 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7379 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007380
7381 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007382 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007383}
7384
Neels Hofmeyr91401012019-07-11 00:42:35 +02007385private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
7386 f_tc_ho_neighbor_config_start();
7387
7388 /*
7389 * bts 0 ARFCN 871 BSIC 10
7390 * bts 1 ARFCN 871 BSIC 11
7391 * bts 2 ARFCN 871 BSIC 12
7392 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7393 */
7394
7395 log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007396 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007397 f_sleep(0.5);
7398
7399 f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor",
7400 "handover any to arfcn 871 bsic 11",
7401 false);
7402 f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor",
7403 "handover any to arfcn 871 bsic 12",
7404 false);
7405 f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
7406 "handover any to arfcn 123 bsic 45",
7407 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007408 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007409}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007410testcase TC_ho_neighbor_config_4() runs on test_CT {
7411 var MSC_ConnHdlr vc_conn;
7412 f_init(3, true, guard_timeout := 50.0);
7413 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007414 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007415 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
7416 vc_conn.done;
7417
7418 /* f_tc_ho_neighbor_config_start() */
7419 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7420 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7421
7422 /* 4.a */
7423 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7424 f_ctrs_bsc_and_bts_add(0, "handover:error");
7425
7426 /* 4.b */
7427 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7428 f_ctrs_bsc_and_bts_add(0, "handover:error");
7429
7430 /* 4.c */
7431 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7432 * handover quickly by timing out after the Handover Required message */
7433 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7434 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7435 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7436 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7437
7438 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007439 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007440}
7441
Neels Hofmeyr91401012019-07-11 00:42:35 +02007442private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
7443 f_tc_ho_neighbor_config_start();
7444
7445 /*
7446 * bts 0 ARFCN 871 BSIC 10
7447 * bts 1 ARFCN 871 BSIC 11
7448 * bts 2 ARFCN 871 BSIC 12
7449 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7450 */
7451
7452 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 +02007453 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007454 f_sleep(0.5);
7455
7456 f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
7457 "handover any to arfcn 871 bsic 12",
7458 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007459 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007460}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007461testcase TC_ho_neighbor_config_5() runs on test_CT {
7462 var MSC_ConnHdlr vc_conn;
7463 f_init(3, true);
7464 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007465 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007466 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
7467 vc_conn.done;
7468
7469 /* f_tc_ho_neighbor_config_start() */
7470 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7471 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7472
7473 /* 5 */
7474 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7475 * handover quickly by timing out after the Handover Required message */
7476 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7477 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7478 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7479 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7480
7481 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007482 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007483}
7484
Neels Hofmeyr91401012019-07-11 00:42:35 +02007485private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
7486 f_tc_ho_neighbor_config_start();
7487
7488 /*
7489 * bts 0 ARFCN 871 BSIC 10
7490 * bts 1 ARFCN 871 BSIC 11
7491 * bts 2 ARFCN 871 BSIC 12
7492 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7493 */
7494
7495 log("f_tc_ho_neighbor_config: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:"
7496 & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007497 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007498 f_sleep(0.5);
7499
7500 f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
7501 "handover any to arfcn 871 bsic 12",
7502 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007503 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007504}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007505testcase TC_ho_neighbor_config_6() runs on test_CT {
7506 var MSC_ConnHdlr vc_conn;
7507 f_init(3, true);
7508 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007509 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007510 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
7511 vc_conn.done;
7512
7513 /* f_tc_ho_neighbor_config_start() */
7514 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7515 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7516
7517 /* 6.a */
7518 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7519 * handover quickly by timing out after the Handover Required message */
7520 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7521 f_ctrs_bsc_and_bts_add(0, "handover:error");
7522
7523 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007524 f_shutdown_helper(ho := true);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007525}
7526
Neels Hofmeyr91401012019-07-11 00:42:35 +02007527private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
7528 f_tc_ho_neighbor_config_start();
7529
7530 /*
7531 * bts 0 ARFCN 871 BSIC 10
7532 * bts 1 ARFCN 871 BSIC 11
7533 * bts 2 ARFCN 871 BSIC 12
7534 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7535 */
7536
7537 log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:"
7538 & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007539 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007540 f_sleep(0.5);
7541
7542 f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
7543 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007544 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007545 f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
7546 "handover any to arfcn 123 bsic 45",
7547 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007548 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007549}
Neels Hofmeyr91401012019-07-11 00:42:35 +02007550testcase TC_ho_neighbor_config_7() runs on test_CT {
7551 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf2b88032020-06-16 00:35:04 +02007552 f_init(3, true, guard_timeout := 50.0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007553 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007554 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007555 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
7556 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007557
7558 /* f_tc_ho_neighbor_config_start() */
7559 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7560 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7561
7562 /* 7.a */
7563 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7564 * handover quickly by sending a Handover Failure message. */
7565 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7566 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7567 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7568 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007569 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7570 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007571
7572 /* 7.b */
7573 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7574 * handover quickly by timing out after the Handover Required message */
7575 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7576 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7577 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7578 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7579
7580 f_ctrs_bsc_and_bts_verify();
Oliver Smith39f53072022-10-27 14:44:04 +02007581 f_shutdown_helper(ho := true);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007582}
7583
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007584/* OS#3041: Open and close N connections in a normal fashion, and expect no
7585 * BSSMAP Reset just because of that. */
7586testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
7587 var default d;
7588 var integer i;
7589 var DchanTuple dt;
7590
7591 f_init();
7592
7593 /* Wait for initial BSSMAP Reset to pass */
7594 f_sleep(4.0);
7595
7596 d := activate(no_bssmap_reset());
7597
7598 /* Setup up a number of connections and RLSD them again from the MSC
7599 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7600 * Let's do it some more times for good measure. */
Harald Weltec3260d92018-06-11 17:48:16 +02007601 for (i := 0; i < 4; i := i+1) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007602 /* Since we're doing a lot of runs, give each one a fresh
7603 * T_guard from the top. */
7604 T_guard.start;
7605
7606 /* Setup a BSSAP connection and clear it right away. This is
7607 * the MSC telling the BSC about a planned release, it's not an
7608 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007609 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007610
7611 /* MSC disconnects (RLSD). */
7612 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
7613 }
7614
7615 /* In the buggy behavior, a timeout of 2 seconds happens between above
7616 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7617 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7618 f_sleep(4.0);
7619
7620 deactivate(d);
7621 f_shutdown_helper();
7622}
Harald Welte552620d2017-12-16 23:21:36 +01007623
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007624/* OS#3041: Open and close N connections in a normal fashion, and expect no
7625 * BSSMAP Reset just because of that. Invoke the release by a BSSMAP Clear from
7626 * the MSC. */
7627testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
7628 var default d;
7629 var integer i;
7630 var DchanTuple dt;
7631 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007632 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
7633 var BssmapCause cause := enum2int(cause_val);
7634
7635 f_init();
7636
7637 /* Wait for initial BSSMAP Reset to pass */
7638 f_sleep(4.0);
7639
7640 d := activate(no_bssmap_reset());
7641
7642 /* Setup up a number of connections and RLSD them again from the MSC
7643 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7644 * Let's do it some more times for good measure. */
7645 for (i := 0; i < 8; i := i+1) {
7646 /* Since we're doing a lot of runs, give each one a fresh
7647 * T_guard from the top. */
7648 T_guard.start;
7649
7650 /* Setup a BSSAP connection and clear it right away. This is
7651 * the MSC telling the BSC about a planned release, it's not an
7652 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007653 dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007654
7655 /* Instruct BSC to clear channel */
7656 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7657
7658 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007659 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007660 }
7661
7662 /* In the buggy behavior, a timeout of 2 seconds happens between above
7663 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7664 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7665 f_sleep(4.0);
7666
7667 deactivate(d);
7668 f_shutdown_helper();
7669}
7670
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007671/* OS#3041: Open and close N connections in a normal fashion, and expect no
7672 * BSSMAP Reset just because of that. Close connections from the MS side with a
7673 * Release Ind on RSL. */
7674testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
7675 var default d;
7676 var integer i;
7677 var DchanTuple dt;
7678 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007679 var integer j;
7680
7681 f_init();
7682
7683 /* Wait for initial BSSMAP Reset to pass */
7684 f_sleep(4.0);
7685
7686 d := activate(no_bssmap_reset());
7687
7688 /* Setup up a number of connections and RLSD them again from the MSC
7689 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7690 * Let's do it some more times for good measure. */
7691 for (i := 0; i < 8; i := i+1) {
7692 /* Since we're doing a lot of runs, give each one a fresh
7693 * T_guard from the top. */
7694 T_guard.start;
7695
7696 /* Setup a BSSAP connection and clear it right away. This is
7697 * the MSC telling the BSC about a planned release, it's not an
7698 * erratic loss of a connection. */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01007699 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007700
7701 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007702 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007703
7704 /* expect Clear Request on MSC side */
7705 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
7706
7707 /* Instruct BSC to clear channel */
7708 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
7709 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7710
7711 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007712 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007713 }
7714
7715 /* In the buggy behavior, a timeout of 2 seconds happens between above
7716 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7717 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7718 f_sleep(4.0);
7719
7720 deactivate(d);
7721 f_shutdown_helper();
7722}
7723
Harald Welte94e0c342018-04-07 11:33:23 +02007724/***********************************************************************
7725 * IPA style dynamic PDCH
7726 ***********************************************************************/
7727
7728private function f_dyn_ipa_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7729 template (omit) RSL_Cause nack := omit)
7730runs on test_CT {
7731 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7732 var RSL_Message rsl_unused;
7733 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7734 f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
7735 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007736 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007737 if (istemplatekind(nack, "omit")) {
7738 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007739 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007740 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007741 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007742 }
7743}
7744
7745private function f_dyn_ipa_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7746 template (omit) RSL_Cause nack := omit)
7747runs on test_CT {
7748 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7749 var RSL_Message rsl_unused;
7750 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7751 f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
7752 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007753 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_DEACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007754 if (istemplatekind(nack, "omit")) {
7755 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007756 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007757 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007758 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007759 }
7760}
7761
7762private function f_ts_dyn_mode_get(integer bts_nr, integer trx_nr, integer ts_nr)
7763runs on test_CT return charstring {
7764 var charstring cmd, resp;
7765 cmd := "show timeslot "&int2str(bts_nr)&" "&int2str(trx_nr)&" "&int2str(ts_nr);
Stefan Sperlingcff13562018-11-13 15:24:06 +01007766 return f_vty_transceive_match_regexp_retry(BSCVTY, cmd, "*\((*)\)*", 0, 4, 1.0);
Harald Welte94e0c342018-04-07 11:33:23 +02007767}
7768
7769private function f_ts_dyn_mode_assert(integer bts_nr, integer trx_nr, integer ts_nr,
7770 template charstring exp)
7771runs on test_CT {
7772 var charstring mode := f_ts_dyn_mode_get(bts_nr, trx_nr, ts_nr);
7773 if (not match(mode, exp)) {
7774 setverdict(fail, "Unexpected TS Mode: ", mode);
Daniel Willmannafce8662018-07-06 23:11:32 +02007775 mtc.stop;
Harald Welte94e0c342018-04-07 11:33:23 +02007776 }
7777}
7778
7779private function f_ts_set_chcomb(integer bts_nr, integer trx_nr, integer ts_nr, charstring chcomb)
7780runs on test_CT {
7781 f_vty_enter_cfg_ts(BSCVTY, bts_nr, trx_nr, ts_nr);
7782 f_vty_transceive(BSCVTY, "phys_chan_config " & chcomb);
7783 f_vty_transceive(BSCVTY, "end");
7784}
7785
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007786
7787private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
7788 var integer i;
7789 for (i := 0; i < 8; i := i + 1) {
7790 f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
7791 }
7792}
7793
Harald Welte94e0c342018-04-07 11:33:23 +02007794private const charstring TCHF_MODE := "TCH/F mode";
7795private const charstring TCHH_MODE := "TCH/H mode";
7796private const charstring PDCH_MODE := "PDCH mode";
7797private const charstring NONE_MODE := "NONE mode";
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007798private const charstring SDCCH8_MODE := "SDCCH8 mode";
Harald Welte94e0c342018-04-07 11:33:23 +02007799
7800/* Test IPA PDCH activation / deactivation triggered by VTY */
7801testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
7802 var RSL_Message rsl_unused;
7803
7804 /* change Timeslot 6 before f_init() starts RSL */
7805 f_init_vty();
7806 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7807 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7808
7809 f_init(1, false);
7810 f_sleep(1.0);
7811
7812 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7813
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007814 log("TCH/F_PDCH pchan starts out in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007815 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7816 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007817 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7818 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007819 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007820 log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007821 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7822
7823 /* De-activate it via VTY */
7824 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7825 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007826 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007827 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7828
7829 /* re-activate it via VTY */
7830 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn);
7831 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007832 log("TCH/F_PDCH pchan, PDCH ACT via VTY, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007833 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7834
7835 /* and finally de-activate it again */
7836 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7837 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007838 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007839 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7840
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007841 /* clean up config */
7842 f_ts_set_chcomb(0, 0, 6, "PDCH");
7843
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007844 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007845}
7846
7847/* Test IPA PDCH activation NACK */
7848testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
7849 var RSL_Message rsl_unused;
7850
7851 /* change Timeslot 6 before f_init() starts RSL */
7852 f_init_vty();
7853 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7854 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7855
7856 f_init(1, false);
7857 f_sleep(1.0);
7858
7859 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7860
7861 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7862 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007863 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7864 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007865 f_sleep(1.0);
7866 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7867
7868 /* De-activate it via VTY */
7869 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7870 f_sleep(1.0);
7871 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7872
7873 /* re-activate it via VTY, but fail that; check BSC still assumes TCH/F mode */
7874 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn, RSL_ERR_EQUIPMENT_FAIL);
7875 f_sleep(1.0);
7876 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7877
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007878 /* clean up config */
7879 f_ts_set_chcomb(0, 0, 6, "PDCH");
7880
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007881 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007882}
7883
7884
7885/***********************************************************************
7886 * Osmocom style dynamic PDCH
7887 ***********************************************************************/
7888
7889private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7890 template (omit) RSL_Cause nack := omit)
7891runs on test_CT {
7892 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7893 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007894 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007895 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7896 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007897 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT(chan_nr, ?));
Harald Welte94e0c342018-04-07 11:33:23 +02007898 if (istemplatekind(nack, "omit")) {
7899 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007900 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02007901 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007902 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007903 }
7904}
7905
7906private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7907 template (omit) RSL_Cause nack := omit)
7908runs on test_CT {
7909 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7910 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007911 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007912 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7913 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007914 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007915 if (istemplatekind(nack, "omit")) {
7916 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007917 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007918 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007919 //f_ipa_tx(ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007920 }
7921}
7922
7923/* Test Osmocom dyn PDCH activation / deactivation triggered by VTY */
7924testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
7925 var RSL_Message rsl_unused;
7926
7927 /* change Timeslot 6 before f_init() starts RSL */
7928 f_init_vty();
7929 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
7930 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7931
7932 f_init(1, false);
7933 f_sleep(1.0);
7934
7935 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
7936
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007937 log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007938 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
7939 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007940 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007941
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007942 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02007943 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007944 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 +02007945 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7946
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007947 /* clean up config */
7948 f_ts_set_chcomb(0, 0, 6, "PDCH");
7949
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007950 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007951}
7952
7953/* Test Osmocom dyn PDCH activation NACK behavior */
7954testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
7955 var RSL_Message rsl_unused;
7956
7957 /* change Timeslot 6 before f_init() starts RSL */
7958 f_init_vty();
7959 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
7960 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7961
7962 f_init(1, false);
7963 f_sleep(1.0);
7964
7965 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
7966
7967 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
7968 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007969 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007970
7971 /* NACK this activation and expect the "show timeslot" mode still to be NONE */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007972 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte94e0c342018-04-07 11:33:23 +02007973 f_sleep(1.0);
7974 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
7975
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007976 /* clean up config */
7977 f_ts_set_chcomb(0, 0, 6, "PDCH");
7978
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007979 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007980}
7981
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007982/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
7983testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
7984 var RSL_Message rsl_unused, rsl_msg;
7985 var DchanTuple dt;
7986 var BSSAP_N_CONNECT_ind rx_c_ind;
7987
7988 /* change Timeslot 6 before f_init() starts RSL */
7989 f_init_vty();
7990 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
7991 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7992
7993 f_init(1, false);
7994 f_sleep(1.0);
7995
7996 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
7997
7998 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
7999 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8000 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008001 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008002
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008003 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008004 f_sleep(1.0);
8005 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8006 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8007
8008 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8009 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008010 var DchanTuples sdcch_cleanup := {};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008011 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008012 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008013 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008014 sdcch_cleanup := sdcch_cleanup & { dt };
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008015 }
8016
8017 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008018 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8019 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8020 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008021
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008022 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008023 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008024 dt.idx := {0, 0};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008025
8026 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008027 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8028 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008029 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
8030
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008031 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 +02008032 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8033 dt.sccp_conn_id := rx_c_ind.connectionId;
8034 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8035
8036 /* Instruct BSC to clear channel */
8037 var BssmapCause cause := 0;
8038 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008039 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008040
8041 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008042 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8043 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008044 f_sleep(1.0);
8045 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8046
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008047 /* Clean up SDCCH lchans */
8048 for (i := 0; i < lengthof(sdcch_cleanup); i := i + 1) {
8049 f_perform_clear_test_ct(sdcch_cleanup[i]);
8050 }
8051
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02008052 /* clean up config */
8053 f_ts_set_chcomb(0, 0, 6, "PDCH");
8054
8055 f_shutdown_helper();
8056}
8057
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008058/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
8059testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
8060 var ASP_RSL_Unitdata rsl_ud;
8061 var integer i;
8062 var integer chreq_total, chreq_nochan;
8063
8064 f_init_vty();
8065 for (i := 1; i < 8; i := i + 1) {
8066 if (i == 2) {
8067 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8068 } else {
8069 f_ts_set_chcomb(0, 0, i, "PDCH");
8070 }
8071 }
8072 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8073
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008074 f_init(1, guard_timeout := 60.0);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008075
8076 /* The dyn TS want to activate PDCH mode, ACK that. */
8077 var RslChannelNr chan_nr;
8078 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008079 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
8080 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008081
8082 f_sleep(1.0);
8083
8084 /* Exhaust all dedicated SDCCH lchans.
8085 /* GSM 44.018 Table 9.1.8.2:
8086 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
8087 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008088 var DchanTuples chan_cleanup := {};
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008089 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008090 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 +02008091 }
8092
8093 /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008094 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 +02008095 /* Also occupy the seven other SDCCH of the dyn TS */
8096 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008097 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 +01008098 }
8099
8100 /* Clean up SDCCH lchans */
8101 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8102 f_perform_clear_test_ct(chan_cleanup[i]);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008103 }
8104
8105 /* clean up config */
8106 f_ts_reset_chcomb(0);
8107
8108 f_shutdown_helper();
8109}
8110
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008111/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
8112 SDCCH8 would end up in having no free TCH, then BSC should decide to activate
8113 it as TCH directly instead. SYS#5309. */
8114testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
8115 var RSL_Message rsl_unused, rsl_msg;
8116 var DchanTuple dt;
8117 var BSSAP_N_CONNECT_ind rx_c_ind;
8118 var integer i;
8119
8120 /* change Timeslot 6 before f_init() starts RSL */
8121 f_init_vty();
8122 for (i := 1; i < 8; i := i + 1) {
8123 if (i == 6) {
8124 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8125 } else {
8126 f_ts_set_chcomb(0, 0, i, "PDCH");
8127 }
8128 }
8129 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8130
8131 f_init(1, false);
8132 f_sleep(1.0);
8133
8134 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8135
8136 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8137 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8138 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008139 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008140
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008141 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008142 f_sleep(1.0);
8143 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8144 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8145
8146 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8147 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008148 var DchanTuples chan_cleanup := {};
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02008149 var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008150 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008151 dt := f_est_dchan(ra, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008152 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008153 }
8154
8155 /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008156 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
8157 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8158 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008159
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008160 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008161 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008162 dt.idx := {0, 0};
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008163
8164 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008165 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8166 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008167 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
8168
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008169 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 +02008170 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8171 dt.sccp_conn_id := rx_c_ind.connectionId;
8172 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8173
8174 /* Instruct BSC to clear channel */
8175 var BssmapCause cause := 0;
8176 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008177 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008178
8179 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008180 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8181 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008182 f_sleep(1.0);
8183 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8184
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008185 /* Clean up SDCCH lchans */
8186 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8187 f_perform_clear_test_ct(chan_cleanup[i]);
8188 }
8189
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008190 /* clean up config */
8191 f_ts_reset_chcomb(0);
8192 /* TODO: clean up other channels? */
8193
8194 f_shutdown_helper();
8195}
8196
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008197/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
8198testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
8199 var RSL_Message rsl_unused, rsl_msg;
8200 var DchanTuple dt;
8201 var BSSAP_N_CONNECT_ind rx_c_ind;
8202 var GsmRrMessage rr;
8203
8204 /* change Timeslot 6 before f_init() starts RSL */
8205 f_init_vty();
8206 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8207 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8208
8209 f_init(1, false);
8210 f_sleep(1.0);
8211
8212 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8213
8214 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8215 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8216 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008217 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008218
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008219 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008220 f_sleep(1.0);
8221 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8222 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8223
8224 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8225 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008226 var DchanTuples chan_cleanup := {};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008227 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008228 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01008229 dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008230 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008231 }
8232
8233 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008234 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8235 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8236 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008237
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008238 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008239 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008240 dt.idx := {0, 0};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008241
8242 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008243 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
8244 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008245 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
8246 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
8247 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
8248 }
8249
8250 /* FIXME? Currently the TS stays in state BORKEN: */
8251
8252 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008253 /* rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8254 * f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008255 * f_sleep(1.0);
8256 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
8257 */
8258
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008259 /* Clean up SDCCH lchans */
8260 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8261 f_perform_clear_test_ct(chan_cleanup[i]);
8262 }
8263
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008264 /* clean up config */
8265 f_ts_set_chcomb(0, 0, 6, "PDCH");
8266
8267 f_shutdown_helper();
8268}
8269
Stefan Sperling0796a822018-10-05 13:01:39 +02008270testcase TC_chopped_ipa_ping() runs on test_CT {
Stefan Sperling554123f2018-10-09 14:12:30 +02008271 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port, mp_bsc_ctrl_port};
Stefan Sperling0796a822018-10-05 13:01:39 +02008272 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8273 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8274 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008275 f_shutdown_helper();
Stefan Sperling0796a822018-10-05 13:01:39 +02008276}
8277
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008278testcase TC_chopped_ipa_payload() runs on test_CT {
8279 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port
8280 /* TODO: mp_bsc_ctrl_port does not work yet */};
8281 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8282 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8283 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008284 f_shutdown_helper();
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008285}
8286
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008287/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
8288 the BTS does autonomous MS power control loop */
8289testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
8290 var MSC_ConnHdlr vc_conn;
8291 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8292 //pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
8293 pars.exp_ms_power_params := true;
8294
8295 f_init(1, true);
8296 f_sleep(1.0);
8297 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
8298 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008299 f_shutdown_helper();
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008300}
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008301
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008302/* Verify activation and deactivation of the BCCH carrier power reduction mode */
8303testcase TC_c0_power_red_mode() runs on test_CT {
8304 f_init(1);
8305
8306 for (var integer red := 6; red >= 0; red := red - 2) {
8307 /* Configure BCCH carrier power reduction mode via the VTY */
8308 f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
8309
8310 /* Expect Osmocom specific BS Power Control message on the RSL */
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03008311 var template (present) RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008312 chan_nr := t_RslChanNr_BCCH(0),
8313 bs_power := tr_RSL_IE_BS_Power(red / 2));
8314 tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008315 var RSL_Message unused := f_exp_ipa_rx(tr_rsl_pdu);
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008316
8317 /* Additionally verify the applied value over the CTRL interface */
8318 var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
8319 if (cred != int2str(red)) {
8320 setverdict(fail, "Unexpected BCCH carrier power reduction value ",
8321 cred, " (expected ", red, ")");
8322 }
8323 }
8324
8325 f_shutdown_helper();
8326}
8327
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008328/***********************************************************************
8329 * MSC Pooling
8330 ***********************************************************************/
8331
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008332template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
Harald Weltebf397612021-01-14 20:39:46 +01008333 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 +02008334
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008335private 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 +02008336runs on MSC_ConnHdlr {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008337 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008338 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008339 f_logp(BSCVTY, "Got RSL RR Release");
8340 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008341 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008342 f_logp(BSCVTY, "Got RSL Deact SACCH");
8343 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008344 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008345 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008346 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8347 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008348 break;
8349 }
8350 }
8351}
8352
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008353private altstep as_mgcp_ack_all_dlcx() runs on MSC_ConnHdlr {
8354 var MgcpCommand mgcp_cmd;
8355 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
8356 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
8357 repeat;
8358 }
8359}
8360
8361private altstep as_rsl_ack_all_rel_req() runs on MSC_ConnHdlr {
8362 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
8363 [] RSL.receive(tr_RSL_REL_REQ(g_chan_nr, ?)) {
8364 RSL.send(ts_RSL_REL_CONF(g_chan_nr, main_dcch));
8365 repeat;
8366 }
8367}
8368
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008369friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
8370 template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02008371runs on MSC_ConnHdlr {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008372 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8373 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008374 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008375 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8376 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008377 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008378 f_logp(BSCVTY, "Got RSL RR Release");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008379 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008380 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008381 f_logp(BSCVTY, "Got RSL Deact SACCH");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008382 }
8383 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008384 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008385 /* Also drop the SCCP connection */
8386 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8387 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008388 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008389 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008390 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8391 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008392 }
8393 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008394 deactivate(ack_dlcx);
8395 deactivate(ack_rel_req);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008396}
8397
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01008398friend function f_perform_clear_no_rr_rel(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC)
8399runs on MSC_ConnHdlr {
8400 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8401 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
8402 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8403 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8404 interleave {
8405 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
8406 f_logp(BSCVTY, "Got RSL Deact SACCH");
8407 }
8408 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
8409 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8410 /* Also drop the SCCP connection */
8411 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8412 }
8413 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
8414 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
8415 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8416 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
8417 }
8418 }
8419 deactivate(ack_dlcx);
8420 deactivate(ack_rel_req);
8421}
8422
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01008423friend function f_perform_clear_no_lchan()
8424runs on MSC_ConnHdlr {
8425 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8426 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8427 BSSAP.receive(tr_BSSMAP_ClearComplete);
8428 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8429 /* Also drop the SCCP connection */
8430 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8431}
8432
Vadim Yanitskiy65d879d2022-06-23 18:15:39 +07008433friend function f_perform_clear_test_ct(DchanTuple dt)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008434 runs on test_CT
8435{
8436 /* Instruct BSC to clear channel */
8437 var BssmapCause cause := 0;
8438 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008439 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008440}
8441
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008442private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
8443 template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008444runs on MSC_ConnHdlr {
8445 timer T := 10.0;
8446 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
8447
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008448 f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008449 f_create_bssmap_exp(l3_enc);
8450
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008451 /* RSL_Emulation.f_chan_est() on rsl_pt:
8452 * This is basically code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008453 * RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
8454 */
8455 var RSL_Message rx_rsl;
8456 var GsmRrMessage rr;
8457
8458 /* request a channel to be established */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008459 rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008460 /* expect immediate assignment.
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008461 * Code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008462 * rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
8463 */
8464 timer Tt := 10.0;
8465
8466 /* request a channel to be established */
8467 Tt.start;
8468 alt {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008469 [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008470 Tt.stop;
8471 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008472 [] rsl_pt.receive {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008473 setverdict(fail, "Unexpected RSL message on DCHAN");
8474 mtc.stop;
8475 }
8476 [] Tt.timeout {
8477 setverdict(fail, "Timeout waiting for RSL on DCHAN");
8478 mtc.stop;
8479 }
8480 }
8481 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
8482 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008483 rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008484
8485
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008486 if (expect_bssmap_l3) {
8487 f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
8488 var template PDU_BSSAP exp_l3_compl;
8489 exp_l3_compl := tr_BSSMAP_ComplL3()
8490 if (g_pars.aoip == false) {
8491 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
8492 } else {
8493 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
8494 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008495
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008496 var PDU_BSSAP bssap;
8497 T.start;
8498 alt {
8499 [] BSSAP.receive(exp_l3_compl) -> value bssap {
8500 f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
8501 log("rx exp_l3_compl = ", bssap);
8502 }
8503 [] BSSAP.receive(tr_BSSMAP_ComplL3) {
8504 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
8505 }
8506 [] T.timeout {
8507 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
8508 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008509 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008510
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008511 /* start ciphering, if requested */
8512 if (ispresent(g_pars.encr)) {
8513 f_logp(BSCVTY, "start ciphering");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008514 f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008515 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008516 }
8517
8518 if (do_clear) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008519 f_perform_clear(rsl_pt, rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008520 }
8521 setverdict(pass);
8522 f_sleep(1.0);
8523}
8524
8525private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
8526 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8527 if (g_pars.mscpool.rsl_idx == 0) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008528 f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008529 } else if (g_pars.mscpool.rsl_idx == 1) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008530 f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008531 } else if (g_pars.mscpool.rsl_idx == 2) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008532 f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008533 }
8534}
8535
8536/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
8537private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
8538 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008539 f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
8540 f_perform_compl_l3(RSL, RSL_PROC, ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_IMSI_LV('001010000000002'H))) );
8541 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))) );
8542 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 +02008543}
8544testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
8545
8546 f_init(1, true);
8547 f_sleep(1.0);
8548 var MSC_ConnHdlr vc_conn;
8549 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008550
8551 f_ctrs_msc_init();
8552
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008553 vc_conn := f_start_handler(refers(f_tc_mscpool_L3Compl_on_1_msc), pars);
8554 vc_conn.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008555
8556 f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008557 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008558}
8559
8560/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
8561/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8562 * just as well using only RSL. */
8563testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
8564
8565 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8566 f_sleep(1.0);
8567
8568 /* Control which MSC gets chosen next by the round-robin, otherwise
8569 * would be randomly affected by which other tests ran before this. */
8570 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8571
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008572 f_ctrs_msc_init();
8573
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008574 var MSC_ConnHdlr vc_conn1;
8575 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8576 pars1.mscpool.rsl_idx := 0;
8577 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8578 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8579 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008580 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008581
8582 var MSC_ConnHdlr vc_conn2;
8583 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8584 pars2.mscpool.rsl_idx := 1;
8585 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8586 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8587 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008588 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008589
8590 /* Test round-robin wrap to the first MSC */
8591 var MSC_ConnHdlr vc_conn3;
8592 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8593 pars3.mscpool.rsl_idx := 2;
8594 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
8595 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8596 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008597 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008598 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008599}
8600
8601/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 0
8602 * (configured in osmo-bsc.cfg). */
8603/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8604 * just as well using only RSL. */
8605testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
8606
8607 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8608 f_sleep(1.0);
8609
8610 /* Control which MSC gets chosen next by the round-robin, otherwise
8611 * would be randomly affected by which other tests ran before this. */
8612 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8613
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008614 f_ctrs_msc_init();
8615
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008616 var MSC_ConnHdlr vc_conn1;
8617 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8618 pars1.mscpool.rsl_idx := 0;
8619 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8620 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8621 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008622 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008623
8624 var MSC_ConnHdlr vc_conn2;
8625 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8626 pars2.mscpool.rsl_idx := 1;
8627 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8628 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8629 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008630 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008631
8632 /* Test round-robin wrap to the first MSC */
8633 var MSC_ConnHdlr vc_conn3;
8634 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8635 pars3.mscpool.rsl_idx := 2;
8636 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8637 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8638 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008639 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008640 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008641}
8642
8643/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
8644 * (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
8645 * NULL-NRI setting is stronger than that. */
8646/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8647 * just as well using only RSL. */
8648testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
8649
8650 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8651 f_sleep(1.0);
8652
8653 /* Control which MSC gets chosen next by the round-robin, otherwise
8654 * would be randomly affected by which other tests ran before this. */
8655 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8656
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008657 f_ctrs_msc_init();
8658
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008659 var MSC_ConnHdlr vc_conn1;
8660 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8661 pars1.mscpool.rsl_idx := 0;
8662 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8663 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8664 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008665 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008666
8667 var MSC_ConnHdlr vc_conn2;
8668 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8669 pars2.mscpool.rsl_idx := 1;
8670 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8671 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8672 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008673 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008674
8675 /* Test round-robin wrap to the first MSC */
8676 var MSC_ConnHdlr vc_conn3;
8677 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8678 pars3.mscpool.rsl_idx := 2;
8679 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8680 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8681 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008682 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008683 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008684}
8685
8686/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
8687 * assigned to any MSC (configured in osmo-bsc.cfg). */
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_tmsi_unassigned_nri_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 /* An NRI that is not assigned to any MSC */
8705 pars1.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(1023))));
8706 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8707 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008708 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008709
8710 var MSC_ConnHdlr vc_conn2;
8711 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8712 pars2.mscpool.rsl_idx := 1;
8713 /* An NRI that is not assigned to any MSC */
8714 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(768)), '00F110'O));
8715 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8716 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008717 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008718
8719 /* Test round-robin wrap to the first MSC */
8720 var MSC_ConnHdlr vc_conn3;
8721 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8722 pars3.mscpool.rsl_idx := 2;
8723 /* An NRI that is not assigned to any MSC */
8724 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, valueof(ts_MI_TMSI_NRI_LV(819))));
8725 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8726 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008727 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008728 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008729}
8730
8731/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
8732 * assigned to an MSC that is currently not connected (configured in osmo-bsc.cfg). */
8733/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8734 * just as well using only RSL. */
8735testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
8736
8737 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8738 f_sleep(1.0);
8739
8740 /* Control which MSC gets chosen next by the round-robin, otherwise
8741 * would be randomly affected by which other tests ran before this. */
8742 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8743
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008744 f_ctrs_msc_init();
8745
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008746 var MSC_ConnHdlr vc_conn1;
8747 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8748 pars1.mscpool.rsl_idx := 0;
8749 /* An NRI that is assigned to an unconnected MSC */
8750 pars1.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(512))));
8751 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8752 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008753 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8754 f_ctrs_msc_add(0, "mscpool:subscr:new");
8755 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008756
8757 var MSC_ConnHdlr vc_conn2;
8758 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8759 pars2.mscpool.rsl_idx := 1;
8760 /* An NRI that is assigned to an unconnected MSC */
8761 pars2.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(767))));
8762 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8763 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008764 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8765 f_ctrs_msc_add(1, "mscpool:subscr:new");
8766 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008767
8768 /* Test round-robin wrap to the first MSC */
8769 var MSC_ConnHdlr vc_conn3;
8770 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8771 pars3.mscpool.rsl_idx := 2;
8772 /* An NRI that is assigned to an unconnected MSC */
8773 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(750)), '00F110'O));
8774 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8775 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008776 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8777 f_ctrs_msc_add(0, "mscpool:subscr:new");
8778 f_ctrs_msc_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008779 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008780}
8781
8782/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
8783 * osmo-bsc.cfg). */
8784/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8785 * just as well using only RSL. */
8786testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
8787
8788 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8789 f_sleep(1.0);
8790
8791 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
8792 * this is not using round-robin. */
8793 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8794
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008795 f_ctrs_msc_init();
8796
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008797 var MSC_ConnHdlr vc_conn1;
8798 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8799 pars1.mscpool.rsl_idx := 0;
8800 /* An NRI of the second MSC's range (256-511) */
8801 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(256))));
8802 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8803 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008804 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008805
8806 var MSC_ConnHdlr vc_conn2;
8807 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8808 pars2.mscpool.rsl_idx := 1;
8809 /* An NRI of the second MSC's range (256-511) */
8810 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(260))));
8811 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8812 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008813 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008814
8815 var MSC_ConnHdlr vc_conn3;
8816 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8817 pars3.mscpool.rsl_idx := 2;
8818 /* An NRI of the second MSC's range (256-511) */
8819 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(511)), '00F110'O));
8820 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8821 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008822 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008823 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008824}
8825
8826/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
8827 * while a round-robin remains unaffected by that. */
8828/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8829 * just as well using only RSL. */
8830testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
8831
8832 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8833 f_sleep(1.0);
8834
8835 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
8836 * this is not using round-robin. */
8837 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8838
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008839 f_ctrs_msc_init();
8840
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008841 var MSC_ConnHdlr vc_conn1;
8842 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 2);
8843 pars1.mscpool.rsl_idx := 0;
8844 /* An NRI of the third MSC's range (512-767) */
8845 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(512))));
8846 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8847 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008848 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008849
8850 var MSC_ConnHdlr vc_conn2;
8851 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8852 pars2.mscpool.rsl_idx := 1;
8853 /* An NRI of the third MSC's range (512-767) */
8854 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(678))));
8855 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8856 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008857 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008858
8859 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
8860 var MSC_ConnHdlr vc_conn3;
8861 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8862 pars3.mscpool.rsl_idx := 2;
8863 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000013'H)), '00F110'O));
8864 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8865 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008866 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008867 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008868}
8869
8870/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
8871/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8872 * just as well using only RSL. */
8873testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
8874
8875 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8876 f_sleep(1.0);
8877
8878 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
8879 * instead, and hits msc 0. */
8880 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8881
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008882 f_ctrs_msc_init();
8883
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008884 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-bsc.cfg */
8885 var MSC_ConnHdlr vc_conn1;
8886 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8887 pars1.mscpool.rsl_idx := 0;
8888 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(260)), '99F999'O));
8889 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8890 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008891 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008892
8893 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
8894 var MSC_ConnHdlr vc_conn2;
8895 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8896 pars2.mscpool.rsl_idx := 1;
8897 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(555)), '00F110'O));
8898 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8899 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008900 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008901 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008902}
8903
8904/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
8905 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
8906private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
8907 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
8908 //cid_list := { cIl_allInBSS := ''O };
8909 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
8910 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
8911 var BSSAP_N_UNITDATA_req paging;
8912 var hexstring imsi := '001010000000123'H;
8913
8914 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8915
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008916 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008917 valueof(ts_BSSMAP_Paging(imsi, cid_list, omit, bssmap_chneed))));
8918 BSSAP.send(paging);
8919
8920 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
8921 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
8922 * channel number is picked here. */
8923 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
8924 f_rslem_register(0, new_chan_nr);
8925 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(imsi)));
8926 f_rslem_unregister(0, new_chan_nr);
8927
8928 /* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
8929 * causes this Paging Response to go to the first MSC (bssap_idx := 0). */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008930 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV(imsi))) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008931 f_sleep(1.0);
8932}
8933testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
8934 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
8935 f_sleep(1.0);
8936
8937 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
8938 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
8939 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8940
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008941 f_ctrs_msc_init();
8942
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008943 var MSC_ConnHdlr vc_conn1;
8944 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8945 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008946 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
8947 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008948 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
8949 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008950 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008951 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008952}
8953
8954/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
8955 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
8956private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
8957 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
8958 //cid_list := { cIl_allInBSS := ''O };
8959 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
8960 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
8961 var integer nri_v := 300; /* <-- second MSC's NRI */
Harald Weltebf397612021-01-14 20:39:46 +01008962 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008963 var BSSAP_N_UNITDATA_req paging;
8964
8965 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8966
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008967 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008968 valueof(ts_BSSMAP_Paging('001010000000011'H, cid_list, tmsi, bssmap_chneed))));
8969 BSSAP.send(paging);
8970
8971 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
8972 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
8973 * channel number is picked here. */
8974 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
8975 f_rslem_register(0, new_chan_nr);
8976 RSL.receive(tr_RSL_PAGING_CMD(t_MI_TMSI(tmsi)));
8977 f_rslem_unregister(0, new_chan_nr);
8978
8979 /* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
8980 * third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
8981 * the first MSC (bssap_idx := 0). */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008982 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(nri_v))) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008983 f_sleep(1.0);
8984}
8985testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
8986 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
8987 f_sleep(1.0);
8988
8989 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
8990 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
8991 f_vty_transceive(BSCVTY, "mscpool roundrobin next 2");
8992
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008993 f_ctrs_msc_init();
8994
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008995 var MSC_ConnHdlr vc_conn1;
8996 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8997 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008998 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
8999 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009000 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
9001 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009002 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009003 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009004}
9005
9006/* For round-robin, skip an MSC that has 'no allow-attach' set. */
9007/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
9008 * just as well using only RSL. */
9009testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
9010
9011 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9012 f_sleep(1.0);
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009013 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9014 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009015
9016 /* Control which MSC gets chosen next by the round-robin, otherwise
9017 * would be randomly affected by which other tests ran before this. */
9018 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9019
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009020 f_ctrs_msc_init();
9021
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009022 var MSC_ConnHdlr vc_conn1;
9023 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
9024 pars1.mscpool.rsl_idx := 0;
9025 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
9026 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9027 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009028 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009029
9030 var MSC_ConnHdlr vc_conn2;
9031 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
9032 pars2.mscpool.rsl_idx := 1;
9033 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9034 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9035 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009036 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009037
9038 var MSC_ConnHdlr vc_conn3;
9039 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
9040 pars3.mscpool.rsl_idx := 2;
9041 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
9042 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9043 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009044 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009045 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009046}
9047
9048/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
9049 * TMSI NRI. */
9050testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
9051
9052 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
9053 f_sleep(1.0);
9054
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00009055 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
9056 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
9057
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009058 /* Control which MSC gets chosen next by the round-robin, otherwise
9059 * would be randomly affected by which other tests ran before this. */
9060 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
9061
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009062 f_ctrs_msc_init();
9063
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009064 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
9065 var MSC_ConnHdlr vc_conn1;
9066 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
9067 pars1.mscpool.rsl_idx := 0;
9068 /* An NRI of the second MSC's range (256-511) */
9069 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_TMSI_NRI_LV(260))));
9070 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
9071 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009072 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009073
9074 var MSC_ConnHdlr vc_conn2;
9075 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
9076 pars2.mscpool.rsl_idx := 1;
9077 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9078 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9079 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009080 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009081
9082 var MSC_ConnHdlr vc_conn3;
9083 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 2);
9084 pars3.mscpool.rsl_idx := 2;
9085 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000003'H))));
9086 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9087 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009088 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009089 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009090}
9091
Philipp Maier783681c2020-07-16 16:47:06 +02009092/* Allow/Deny emergency calls globally via VTY */
9093private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
9094 f_vty_enter_cfg_msc(BSCVTY, 0);
9095 if (allow) {
9096 f_vty_transceive(BSCVTY, "allow-emergency allow");
9097 } else {
9098 f_vty_transceive(BSCVTY, "allow-emergency deny");
9099 }
9100 f_vty_transceive(BSCVTY, "exit");
9101 f_vty_transceive(BSCVTY, "exit");
9102}
9103
9104/* Allow/Deny emergency calls per BTS via VTY */
9105private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
9106 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9107 if (allow) {
9108 f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
9109 } else {
9110 f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
9111 }
9112 f_vty_transceive(BSCVTY, "exit");
9113 f_vty_transceive(BSCVTY, "exit");
Neels Hofmeyrb6ed80c2020-10-12 22:52:39 +00009114 f_vty_transceive(BSCVTY, "exit");
Philipp Maier783681c2020-07-16 16:47:06 +02009115}
9116
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02009117/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
9118private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
9119 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9120 if (allow) {
9121 f_vty_transceive(BSCVTY, "srvcc fast-return allow");
9122 } else {
9123 f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
9124 }
9125 f_vty_transceive(BSCVTY, "exit");
9126 f_vty_transceive(BSCVTY, "exit");
9127 f_vty_transceive(BSCVTY, "exit");
9128}
9129
Pau Espin Pedrol14475352021-07-22 15:48:16 +02009130/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
9131private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
9132 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9133 if (allow) {
9134 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
9135 } else {
9136 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
9137 }
9138 f_vty_transceive(BSCVTY, "exit");
9139 f_vty_transceive(BSCVTY, "exit");
9140 f_vty_transceive(BSCVTY, "exit");
9141}
9142
Philipp Maier783681c2020-07-16 16:47:06 +02009143/* Begin assignmet procedure and send an EMERGENCY SETUP (RR) */
9144private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
9145 var PDU_ML3_MS_NW emerg_setup;
9146 var octetstring emerg_setup_enc;
9147 var RSL_Message emerg_setup_data_ind;
9148
9149 f_establish_fully(omit, omit);
9150
9151 emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
9152 emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
9153 emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
9154
9155 RSL.send(emerg_setup_data_ind);
9156}
9157
9158/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
9159 * CALLS are permitted by the BSC config. */
9160private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
9161 var PDU_BSSAP emerg_setup_data_ind_bssap;
9162 var PDU_ML3_MS_NW emerg_setup;
9163 timer T := 3.0;
9164
9165 f_assignment_emerg_setup()
9166
9167 T.start;
9168 alt {
9169 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
9170 emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
9171 if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
9172 setverdict(fail, "no emergency setup");
9173 }
9174 }
9175 [] BSSAP.receive {
9176 setverdict(fail, "unexpected BSSAP message!");
9177 }
9178 [] T.timeout {
9179 setverdict(fail, "timout waiting for EMERGENCY SETUP!");
9180 }
9181 }
9182
9183 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009184 f_perform_clear();
Philipp Maier783681c2020-07-16 16:47:06 +02009185}
9186
9187/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
9188 * forbidden by the BSC config. */
9189private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
9190 var PDU_BSSAP emerg_setup_data_ind_bssap;
9191 timer T := 3.0;
9192
9193 f_assignment_emerg_setup()
9194
9195 T.start;
9196 alt {
9197 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
9198 setverdict(pass);
9199 }
9200 [] RSL.receive {
9201 setverdict(fail, "unexpected RSL message!");
9202 }
9203 [] T.timeout {
9204 setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
9205 }
9206 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009207 BSSAP.receive(tr_BSSMAP_ClearRequest);
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01009208 f_perform_clear_no_rr_rel();
Philipp Maier783681c2020-07-16 16:47:06 +02009209}
9210
9211/* EMERGENCY CALL situation #1, allowed globally and by BTS */
9212testcase TC_assignment_emerg_setup_allow() runs on test_CT {
9213 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9214 var MSC_ConnHdlr vc_conn;
9215
9216 f_init(1, true);
9217 f_sleep(1.0);
9218
9219 f_vty_allow_emerg_msc(true);
9220 f_vty_allow_emerg_bts(true, 0);
9221 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9222 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009223 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009224}
9225
9226/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
9227testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
9228 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9229 var MSC_ConnHdlr vc_conn;
9230
9231 f_init(1, true);
9232 f_sleep(1.0);
9233
9234 f_vty_allow_emerg_msc(false);
9235 f_vty_allow_emerg_bts(true, 0);
9236 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9237 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009238 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009239}
9240
9241/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS */
9242testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
9243 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9244 var MSC_ConnHdlr vc_conn;
9245
9246 /* Note: This simulates a spec violation by the MS, correct MS
9247 * implementations would not try to establish an emergency call because
9248 * the system information tells in advance that emergency calls are
9249 * not forbidden */
9250
9251 f_init(1, true);
9252 f_sleep(1.0);
9253
9254 f_vty_allow_emerg_msc(true);
9255 f_vty_allow_emerg_bts(false, 0);
9256 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9257 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009258 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009259}
9260
Philipp Maier82812002020-08-13 18:48:27 +02009261/* Test what happens when an emergency call arrives while all TCH channels are
9262 * busy, the BSC is expected to terminate one call in favor of the incoming
9263 * emergency call */
9264testcase TC_emerg_premption() runs on test_CT {
9265 var ASP_RSL_Unitdata rsl_ud;
9266 var integer i;
9267 var integer chreq_total, chreq_nochan;
9268 var RSL_Message rx_rsl;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009269 var octetstring l3_payload := gen_l3_valid_payload();
Philipp Maier82812002020-08-13 18:48:27 +02009270
9271 f_init(1);
9272 f_sleep(1.0);
9273
9274 f_vty_allow_emerg_msc(true);
9275 f_vty_allow_emerg_bts(true, 0);
9276
9277 /* Fill up all channels on the BTS */
9278 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
9279 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
9280 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 +02009281 f_chreq_act_ack('33'O, i);
Philipp Maier82812002020-08-13 18:48:27 +02009282 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009283 IPA_RSL[0][0].clear;
Philipp Maier82812002020-08-13 18:48:27 +02009284 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
9285 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
9286
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009287 /* Send EST IND for the first TCH, so we get to test the RR release cause */
9288 var RslChannelNr first_tch := valueof(t_RslChanNr_Bm(1));
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009289 f_ipa_tx(ts_RSL_EST_IND(first_tch, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009290
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009291 /* Accept BSSAP conn, so we get to test the Clear Request cause */
9292 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009293 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009294 var integer sccp_conn_id := rx_c_ind.connectionId;
9295 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
9296
Philipp Maier82812002020-08-13 18:48:27 +02009297 /* Send Channel request for emegergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009298 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier82812002020-08-13 18:48:27 +02009299
9300 /* Expect the BSC to release one (the first) TCH/F on the BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009301 f_expect_chan_rel(first_tch, expect_rr_chan_rel := true, expect_rll_rel_req := false,
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009302 expect_rr_cause := GSM48_RR_CAUSE_PREMPTIVE_REL);
Philipp Maier82812002020-08-13 18:48:27 +02009303
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009304 /* Also expect a BSSMAP Clear Request with PREEMPTION */
9305 var BSSAP_N_DATA_ind rx_clear_req;
9306 const myBSSMAP_Cause preemption := GSM0808_CAUSE_PREEMPTION;
9307 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_clear_req;
9308 log("XXX ", rx_clear_req);
9309 if (rx_clear_req.userData.pdu.bssmap.clearRequest.cause.causeValue != int2bit(enum2int(preemption), 7)) {
9310 setverdict(fail, "BSSMAP Clear Request: expected cause PREEMPTION");
9311 }
9312
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009313 /* Expect the BSC to send activate/assign the channel for the emergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009314 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009315 if (first_tch != rx_rsl.ies[0].body.chan_nr) {
9316 setverdict(fail, "different TCH lchan activated than expected");
9317 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009318 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(first_tch, 33));
9319 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Philipp Maier104f4c02020-09-11 18:12:18 +02009320
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009321 /* complete the BSSMAP Clear to satisfy the conn leak check */
9322 BSSAP.send(ts_BSSAP_DATA_req(sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(preemption))));
9323 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearComplete)) {
9324 BSSAP.send(ts_BSSAP_DISC_req(sccp_conn_id, 0));
9325 }
9326
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009327 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009328}
9329
9330/* Hopping parameters per a timeslot */
Vadim Yanitskiybc6654a2020-09-13 01:27:40 +07009331private type record length(0..64) of GsmArfcn ArfcnList;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009332private type record FHParamsTs {
9333 boolean enabled,
9334 uint6_t hsn,
9335 uint6_t maio,
9336 ArfcnList ma
9337};
9338
9339/* Hopping parameters per a transceiver */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009340private type record FHParamsTrx {
Philipp Maier798d8952021-10-19 14:43:19 +02009341 GsmBandArfcn arfcn,
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009342 FHParamsTs ts[8]
9343};
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009344
9345/* Randomly generate the hopping parameters for the given timeslot numbers */
9346private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
9347runs on test_CT return FHParamsTrx {
9348 var FHParamsTrx fhp;
9349
Philipp Maier798d8952021-10-19 14:43:19 +02009350 /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
9351 * fall in the GSM900 band. */
9352 fhp.arfcn.arfcn := f_rnd_int(3);
9353 fhp.arfcn.pcs := false;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009354
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009355 for (var integer tn := 0; tn < 8; tn := tn + 1) {
9356 if (not match(tn, tr_tn)) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009357 fhp.ts[tn].enabled := false;
9358 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009359 continue;
9360 }
9361
9362 /* Random HSN / MAIO values: 0..63 */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009363 fhp.ts[tn].hsn := f_rnd_int(64);
9364 fhp.ts[tn].maio := f_rnd_int(64);
9365 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009366
9367 /* Random Mobile Allocation (hopping channels) */
9368 var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
9369 var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
9370 for (var integer i := 1; i <= ma_len; i := i + 1) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009371 fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009372 }
9373
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009374 fhp.ts[tn].enabled := true;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009375 }
9376
9377 log("f_TC_fh_params_gen(): ", fhp);
9378 return fhp;
9379}
9380
9381/* Make sure that the given Channel Description IE matches the hopping configuration */
9382private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
9383{
9384 var template (present) ChannelDescription tr_cd;
9385 var template (present) MaioHsn tr_maio_hsn;
9386 var uint3_t tn := cd.chan_nr.tn;
9387
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009388 if (fhp.ts[tn].enabled) {
9389 tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009390 tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
9391 } else {
Philipp Maier798d8952021-10-19 14:43:19 +02009392 tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009393 }
9394
9395 if (not match(cd, tr_cd)) {
9396 setverdict(fail, "Channel Description IE does not match: ",
9397 cd, " vs expected ", tr_cd);
9398 }
9399}
9400
9401/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
9402private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
9403 in MobileAllocationLV ma)
9404{
9405 var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
9406
9407 if (not match(ma, tr_ma)) {
9408 setverdict(fail, "Mobile Allocation IE does not match (tn := ",
9409 tn, "): ", ma, " vs expected: ", tr_ma);
9410 } else {
9411 setverdict(pass);
9412 }
9413}
9414
9415private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
9416 in MobileAllocationLV ma)
9417return template MobileAllocationLV {
9418 /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009419 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009420 return { len := 0, ma := ''B };
9421 }
9422
9423 var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
9424 var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
9425 var bitstring ma_mask := ''B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009426
9427 /* Compose the full bit-mask (all channels, up to 1024 entries) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009428 for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
9429 for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
9430 if (full_mask[fhp.ts[i].ma[j]] == '1'B)
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009431 { continue; }
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009432 full_mask[fhp.ts[i].ma[j]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009433 }
9434 }
9435
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009436 /* Take ARFCN of the TRX itself into account */
Philipp Maier798d8952021-10-19 14:43:19 +02009437 full_mask[fhp.arfcn.arfcn] := '1'B;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009438
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009439 /* Compose a bit-mask for the given timeslot number */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009440 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9441 slot_mask[fhp.ts[tn].ma[i]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009442 }
9443
9444 /* Finally, compose the Mobile Allocation bit-mask */
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009445 for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009446 if (full_mask[i] != '1'B)
9447 { continue; }
9448
9449 /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
9450 if (slot_mask[i] == '1'B) {
9451 ma_mask := ma_mask & '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009452 } else {
9453 ma_mask := ma_mask & '0'B;
9454 }
9455 }
9456
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009457 /* ARFCN 0 (if present) goes to the last position of the bit-mask */
9458 if (full_mask[0] == '1'B) {
9459 /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
9460 if (slot_mask[0] == '1'B) {
9461 ma_mask := ma_mask & '1'B;
9462 } else {
9463 ma_mask := ma_mask & '0'B;
9464 }
9465 }
9466
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009467 /* Ensure that ma_mask is octet-aligned */
Vadim Yanitskiy2aa02522020-09-06 14:05:23 +07009468 var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009469 ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
9470
9471 return { len := ma_mask_len, ma := ma_mask };
9472}
9473
Philipp Maier798d8952021-10-19 14:43:19 +02009474/* Configure the appropriate band for a given arfcn, exc */
9475private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
9476{
9477 var charstring band;
9478 var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
9479
9480 select (arfcn_) {
9481 case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
9482 case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
9483 case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
9484 case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
9485 case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
9486 case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
9487 case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
9488 case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
9489 case else { return; }
9490 }
9491
9492 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9493 f_vty_transceive(BSCVTY, "band " & band);
9494 f_vty_transceive(BSCVTY, "end");
9495}
9496
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009497/* Configure the hopping parameters in accordance with the given record */
9498private function f_TC_fh_params_set(in FHParamsTrx fhp,
9499 uint8_t bts_nr := 0,
9500 uint8_t trx_nr := 0)
9501runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009502
9503 f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
9504
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009505 /* Enter the configuration node for the given BTS/TRX numbers */
9506 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9507
Philipp Maier798d8952021-10-19 14:43:19 +02009508 f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009509
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009510 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009511 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9512
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009513 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009514 f_vty_transceive(BSCVTY, "hopping enabled 0");
9515 f_vty_transceive(BSCVTY, "exit"); /* go back */
9516 continue;
9517 }
9518
9519 /* Configure HSN / MAIO values */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009520 f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
9521 f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009522
9523 /* Configure the Mobile Allocation (hopping channels) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009524 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9525 f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009526 }
9527
9528 f_vty_transceive(BSCVTY, "hopping enabled 1");
9529 f_vty_transceive(BSCVTY, "exit"); /* go back */
9530 }
9531
9532 f_vty_transceive(BSCVTY, "end");
9533}
9534
9535/* Disable frequency hopping on all timeslots */
9536private function f_TC_fh_params_unset(in FHParamsTrx fhp,
9537 uint8_t bts_nr := 0,
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009538 uint8_t trx_nr := 0,
Philipp Maier798d8952021-10-19 14:43:19 +02009539 GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009540runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009541
9542 f_TC_set_band_by_arfcn(bts_nr, arfcn);
9543
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009544 /* Enter the configuration node for the given BTS/TRX numbers */
9545 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9546
Philipp Maier798d8952021-10-19 14:43:19 +02009547 f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009548
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009549 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009550 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9551
9552 /* Delete all ARFCNs from the Mobile Allocation (if any) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009553 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9554 f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009555 }
9556
9557 f_vty_transceive(BSCVTY, "hopping enabled 0");
9558 f_vty_transceive(BSCVTY, "exit"); /* go back */
9559 }
9560
9561 f_vty_transceive(BSCVTY, "end");
9562 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9563}
9564
9565/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
9566 * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
9567testcase TC_fh_params_chan_activ() runs on test_CT {
9568 var FHParamsTrx fhp := f_TC_fh_params_gen();
9569 var RSL_Message rsl_msg;
9570 var RSL_IE_Body ie;
9571
9572 f_init_vty();
9573
9574 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9575 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9576
9577 f_init(1);
9578
9579 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9580 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009581 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9582 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009583
9584 /* Make sure that Channel Identification IE is present */
9585 if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
9586 setverdict(fail, "RSL Channel Identification IE is absent");
9587 continue;
9588 }
9589
9590 /* Make sure that hopping parameters (HSN/MAIO) match */
9591 f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
9592
9593 /* "Mobile Allocation shall be included but empty" - let's check this */
9594 if (ie.chan_ident.ma.v.len != 0) {
9595 setverdict(fail, "Mobile Allocation IE is not empty: ",
9596 ie.chan_ident.ma, ", despite it shall be");
9597 continue;
9598 }
9599 }
9600
9601 /* Disable frequency hopping */
9602 f_TC_fh_params_unset(fhp);
9603
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009604 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009605}
9606
9607/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
9608testcase TC_fh_params_imm_ass() runs on test_CT {
9609 var FHParamsTrx fhp := f_TC_fh_params_gen();
9610 var RSL_Message rsl_msg;
9611 var RSL_IE_Body ie;
9612
9613 f_init_vty();
9614
9615 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9616 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9617
9618 f_init(1);
9619
9620 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9621 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009622 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9623 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009624
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009625 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9626 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009627
9628 /* Make sure that Full Immediate Assign Info IE is present */
9629 if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
9630 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
9631 continue;
9632 }
9633
9634 /* Decode the actual Immediate Assignment message */
9635 var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
9636 if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
9637 setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
9638 continue;
9639 }
9640
9641 /* Make sure that hopping parameters (HSN/MAIO) match */
9642 f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
9643
9644 /* Make sure that the Mobile Allocation IE matches */
9645 f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
9646 rr_msg.payload.imm_ass.mobile_allocation);
9647 }
9648
9649 /* Disable frequency hopping */
9650 f_TC_fh_params_unset(fhp);
Philipp Maier82812002020-08-13 18:48:27 +02009651
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009652 f_shutdown_helper();
Philipp Maier82812002020-08-13 18:48:27 +02009653}
9654
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009655/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
9656testcase TC_fh_params_assignment_cmd() runs on test_CT {
9657 var FHParamsTrx fhp := f_TC_fh_params_gen();
9658 var RSL_Message rsl_msg;
9659 var RSL_IE_Body ie;
9660
9661 f_init_vty();
9662
9663 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9664 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9665
9666 f_init(1);
9667
9668 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +02009669 vc_MGCP[0].stop;
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009670
9671 var template PDU_BSSAP ass_cmd := f_gen_ass_req();
9672 ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
9673
9674 /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
9675 * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
9676 for (var integer i := 0; i < 3; i := i + 1) {
9677 /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009678 var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009679
9680 /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
9681 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009682 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009683
9684 /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009685 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9686 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009687
9688 /* Make sure that L3 Information IE is present */
9689 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9690 setverdict(fail, "RSL L3 Information IE is absent");
9691 continue;
9692 }
9693
9694 /* Decode the L3 message and make sure it is (RR) Assignment Command */
9695 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9696 if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
9697 setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
9698 continue;
9699 }
9700
9701 /* Make sure that hopping parameters (HSN/MAIO) match */
9702 var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
9703 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9704
9705 /* Make sure that Cell Channel Description IE is present if FH is enabled */
9706 if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
Vadim Yanitskiy38d069d2020-09-02 17:18:57 +07009707 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009708 continue;
9709 }
9710
9711 /* Make sure that the Mobile Allocation IE matches (if present) */
9712 var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
9713 if (chan_desc.h and ma_present) {
9714 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9715 l3_msg.payload.ass_cmd.mobile_allocation.v);
9716 } else if (chan_desc.h and not ma_present) {
9717 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9718 continue;
9719 } else if (not chan_desc.h and ma_present) {
9720 setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
9721 continue;
9722 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009723
9724 f_perform_clear_test_ct(dt);
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009725 }
9726
9727 /* Give the IUT some time to release all channels */
9728 f_sleep(3.0);
9729
9730 /* Disable frequency hopping */
9731 f_TC_fh_params_unset(fhp);
9732
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009733 f_shutdown_helper();
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009734}
9735
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009736/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
9737private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
9738runs on test_CT {
9739 var RSL_Message rsl_msg;
9740 var RSL_IE_Body ie;
9741 var DchanTuple dt;
9742
9743 /* Establish a dedicated channel, so we can trigger handover */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +01009744 dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
Vadim Yanitskiyc18ff472021-11-18 20:15:37 +03009745 f_sleep(0.5);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009746
9747 /* Trigger handover from BTS0 to BTS1 */
9748 f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
9749 f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
9750
9751 /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009752 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx := {1, 0});
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009753
9754 /* ACKnowledge channel activation and expect (RR) Handover Command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009755 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33), idx := {1, 0});
9756 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009757
9758 /* Make sure that L3 Information IE is present */
9759 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9760 setverdict(fail, "RSL L3 Information IE is absent");
9761 return;
9762 }
9763
9764 /* Decode the L3 message and make sure it is (RR) Handover Command */
9765 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9766 if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
9767 setverdict(fail, "Failed to match Handover Command: ", l3_msg);
9768 return;
9769 }
9770
9771 /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
9772 var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
9773 if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
9774 setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
9775 return;
9776 }
9777
9778 /* Make sure that hopping parameters (HSN/MAIO) match */
9779 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9780
9781 /* Make sure that Cell Channel Description IE is present */
9782 if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
9783 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
9784 return;
9785 }
9786
9787 /* Make sure that the Mobile Allocation (after time) IE is present and matches */
9788 var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
9789 if (ma_present) {
9790 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9791 l3_msg.payload.ho_cmd.mobile_allocation.v);
9792 } else {
9793 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9794 return;
9795 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009796
9797 f_perform_clear_test_ct(dt);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009798}
9799testcase TC_fh_params_handover_cmd() runs on test_CT {
9800 var FHParamsTrx fhp := f_TC_fh_params_gen();
9801
9802 f_init_vty();
9803
9804 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
9805 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
9806
9807 f_vty_transceive(BSCVTY, "timeslot 0");
9808 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
9809 f_vty_transceive(BSCVTY, "exit"); /* go back */
9810
9811 f_vty_transceive(BSCVTY, "timeslot 1");
9812 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
9813 f_vty_transceive(BSCVTY, "end"); /* we're done */
9814
9815 f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
9816 f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
9817
9818 f_init(2);
9819
9820 f_TC_fh_params_handover_cmd(fhp);
9821
9822 /* Disable frequency hopping on BTS1 */
9823 f_TC_fh_params_unset(fhp, 1);
9824
9825 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
9826 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
9827
9828 f_vty_transceive(BSCVTY, "timeslot 0");
9829 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
9830 f_vty_transceive(BSCVTY, "exit"); /* go back */
9831
9832 f_vty_transceive(BSCVTY, "timeslot 1");
9833 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
9834 f_vty_transceive(BSCVTY, "end"); /* we're done */
9835
9836 f_shutdown_helper();
9837}
9838
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009839/* Verify the hopping parameters in System Information Type 4 */
9840testcase TC_fh_params_si4_cbch() runs on test_CT {
9841 var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
9842 var ASP_RSL_Unitdata rx_rsl_ud;
9843 timer T := 5.0;
9844
9845 f_init_vty();
9846
9847 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
9848 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
9849
9850 f_vty_transceive(BSCVTY, "timeslot 0");
9851 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
9852 f_vty_transceive(BSCVTY, "exit"); /* go back */
9853
9854 f_vty_transceive(BSCVTY, "timeslot 1");
9855 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
9856 f_vty_transceive(BSCVTY, "end"); /* we're done */
9857
9858 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9859 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9860
9861 f_init(1);
9862
9863 T.start;
9864 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009865 [] 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 +07009866 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
9867 var SystemInformation si := dec_SystemInformation(ie.other.payload);
9868
9869 /* Make sure that what we decoded is System Information Type 4 */
9870 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
9871 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
9872 repeat;
9873 }
9874
9875 /* Make sure that CBCH Channel Description IE is present */
9876 if (not ispresent(si.payload.si4.cbch_chan_desc)) {
9877 setverdict(fail, "CBCH Channel Description IE is absent");
9878 break;
9879 }
9880
9881 /* Finally, check the hopping parameters (HSN, MAIO) */
9882 var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
9883 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9884
9885 /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
9886 * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
9887 if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
9888 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9889 break;
9890 } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
9891 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9892 si.payload.si4.cbch_mobile_alloc.v);
9893 }
9894 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009895 [] IPA_RSL[0][0].receive { repeat; }
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009896 [] T.timeout {
9897 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
9898 }
9899 }
9900
9901 /* Disable frequency hopping */
9902 f_TC_fh_params_unset(fhp);
9903
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +07009904 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009905 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
9906
9907 f_vty_transceive(BSCVTY, "timeslot 0");
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +07009908 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009909 f_vty_transceive(BSCVTY, "exit"); /* go back */
9910
9911 f_vty_transceive(BSCVTY, "timeslot 1");
9912 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
9913 f_vty_transceive(BSCVTY, "end"); /* we're done */
9914
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009915 f_shutdown_helper();
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009916}
9917
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009918template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
9919 := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
9920
9921private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
9922 template (present) BSSLAP_PDU expect_bsslap)
9923{
9924 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
9925 if (not match(bsslap, expect_bsslap)) {
9926 log("EXPECTING BSSLAP: ", expect_bsslap);
9927 log("GOT BSSLAP: ", bsslap);
9928 setverdict(fail, "BSSLAP is not as expected");
9929 mtc.stop;
9930 }
9931 setverdict(pass);
9932}
9933
9934/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
9935const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
9936
9937private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
9938 var PDU_BSSAP_LE rx_bsslap;
9939 BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
9940 f_match_bsslap(rx_bsslap, expect_rx_bsslap);
9941}
9942
9943/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9944 * Request on Lb interface. Either with or without the SMLC doing a BSSLAP TA Request. */
9945private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
9946 f_sleep(1.0);
9947
9948 f_establish_fully(omit, omit);
9949 f_bssap_le_register_imsi(g_pars.imsi, omit);
9950
9951 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9952 ts_CellId_CGI('262'H, '42'H, 23, 42))));
9953
9954 var PDU_BSSAP_LE plr;
9955 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9956
9957 if (not do_ta_request) {
9958 /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
9959 var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
9960 if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
9961 log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
9962 log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
9963 setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
9964 mtc.stop;
9965 }
9966 var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
9967 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
9968 if (not match(bsslap, expect_ta_layer3)) {
9969 log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
9970 log("GOT BSSLAP: ", bsslap);
9971 setverdict(fail, "BSSLAP is not as expected");
9972 mtc.stop;
9973 }
9974 /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
9975 * has no need to request the TA from the BSC and directly responds. */
9976 } else {
9977 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9978 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9979 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
9980 }
9981
9982 /* SMLC got the TA from the BSC, now responds with geo information data. */
9983 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
9984 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9985 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
9986
9987 /* The LCS was using an active A-interface conn. It should still remain active after this. */
9988 f_mo_l3_transceive();
9989
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009990 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009991
9992 f_sleep(2.0);
9993 setverdict(pass);
9994}
9995
9996/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9997 * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
9998private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
9999 f_lcs_loc_req_for_active_ms(false);
10000}
10001testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
10002 var MSC_ConnHdlr vc_conn;
10003 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10004
10005 f_init(1, true);
10006 f_sleep(1.0);
10007 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
10008 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010009 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010010}
10011
10012/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10013 * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
10014private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
10015 f_lcs_loc_req_for_active_ms(true);
10016}
10017testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
10018 var MSC_ConnHdlr vc_conn;
10019 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10020
10021 f_init(1, true);
10022 f_sleep(1.0);
10023 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
10024 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010025 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010026}
10027
10028/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
10029 * conn without an active lchan. */
10030private function f_clear_A_conn() runs on MSC_ConnHdlr
10031{
10032 var BssmapCause cause := 0;
10033 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10034 BSSAP.receive(tr_BSSMAP_ClearComplete);
10035 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10036
10037 timer no_more_bssap := 5.0;
10038 no_more_bssap.start;
10039 alt {
10040 [] no_more_bssap.timeout { break; }
10041 [] BSSAP.receive(tr_BSSAP_BSSMAP) {
10042 setverdict(fail, "Expected no more BSSAP after Clear Complete");
10043 mtc.stop;
10044 }
10045 }
10046 setverdict(pass);
10047}
10048
10049/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
10050 * for LCS, for cases where there is only an A conn without an active lchan. */
10051private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
10052{
10053 f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
10054
10055 /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
10056 * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
10057 * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
10058 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10059 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10060 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10061
10062 /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
10063 f_clear_A_conn();
10064 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10065 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10066}
10067
10068/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
10069 * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
10070 */
10071private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
10072 f_sleep(1.0);
10073
10074 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10075 f_bssap_le_register_imsi(g_pars.imsi, omit);
10076
10077 /* Register to receive the Paging Command */
10078 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10079 g_chan_nr := new_chan_nr;
10080 f_rslem_register(0, g_chan_nr);
10081
10082 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10083 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10084 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10085 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10086
10087 var PDU_BSSAP_LE plr;
10088 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10089
10090 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10091 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10092
10093 /* OsmoBSC needs to Page */
10094 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
10095 f_logp(BSCVTY, "got Paging Command");
10096
10097 /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
10098 * the MSC, and releases the lchan directly. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010099 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV(g_pars.imsi))), do_clear := false, expect_bssmap_l3 := false);
10100 f_expect_lchan_rel(RSL, RSL_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010101
10102 /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
10103
10104 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10105
10106 /* SMLC got the TA from the BSC, now responds with geo information data. */
10107 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10108 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10109
10110 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10111
10112 /* The lchan is gone, the A-interface conn was created for the LCS only.
10113 * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
10114 f_verify_active_A_conn_and_clear();
10115
10116 f_sleep(2.0);
10117 setverdict(pass);
10118}
10119testcase TC_lcs_loc_req_for_idle_ms() runs on test_CT {
10120 var MSC_ConnHdlr vc_conn;
10121 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10122
10123 f_init(1, true);
10124 f_sleep(1.0);
10125
10126 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10127 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10128
10129 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
10130 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010131 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010132}
10133
10134/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
10135 */
10136private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
10137 f_sleep(1.0);
10138
10139 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10140 f_bssap_le_register_imsi(g_pars.imsi, omit);
10141
10142 /* provoke an abort by omitting both IMSI and IMEI */
10143 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10144 valueof(ts_BSSMAP_Perform_Location_Request(omit,
10145 ts_CellId_CGI('262'H, '42'H, 23, 42)))));
10146 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10147
10148 /* BSC tells MSC about failure */
10149 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10150 locationEstimate := omit, positioningData := omit,
10151 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
10152
10153 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10154 f_verify_active_A_conn_and_clear();
10155
10156 f_sleep(2.0);
10157 setverdict(pass);
10158}
10159testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
10160 var MSC_ConnHdlr vc_conn;
10161 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10162
10163 f_init(1, true);
10164 f_sleep(1.0);
10165
10166 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10167 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10168
10169 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
10170 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010171 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010172}
10173
10174/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10175 * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
10176private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
10177 f_sleep(1.0);
10178
10179 f_establish_fully(omit, omit);
10180 f_bssap_le_register_imsi(g_pars.imsi, omit);
10181
10182 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10183 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10184
10185 var PDU_BSSAP_LE plr;
10186 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10187
10188 if (do_ta) {
10189 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10190 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10191 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10192 }
10193
10194 /* SMLC fails to respond, BSC runs into timeout */
10195 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
10196 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10197
10198 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10199 locationEstimate := omit, positioningData := omit,
10200 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
10201
10202 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10203 f_verify_active_A_conn_and_clear();
10204
10205 f_sleep(2.0);
10206 setverdict(pass);
10207}
10208
10209/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10210 * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
10211private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
10212 f_lcs_loc_req_for_active_ms_le_timeout(false);
10213}
10214
10215testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
10216 var MSC_ConnHdlr vc_conn;
10217 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10218
10219 f_init(1, true);
10220 f_sleep(1.0);
10221 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
10222 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010223 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010224}
10225
10226/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10227 * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
10228private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
10229 f_lcs_loc_req_for_active_ms_le_timeout(true);
10230}
10231
10232testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
10233 var MSC_ConnHdlr vc_conn;
10234 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10235
10236 f_init(1, true);
10237 f_sleep(1.0);
10238 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
10239 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010240 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010241}
10242
10243/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
10244private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
10245 f_sleep(1.0);
10246
10247 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10248 f_bssap_le_register_imsi(g_pars.imsi, omit);
10249
10250 /* Register to receive the Paging Command */
10251 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10252 g_chan_nr := new_chan_nr;
10253 f_rslem_register(0, g_chan_nr);
10254
10255 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10256 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10257 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10258 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10259
10260 var PDU_BSSAP_LE plr;
10261 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10262
10263 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10264 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10265
10266 /* OsmoBSC needs to Page */
10267 var PDU_BSSAP_LE rx_bsslap;
10268 alt {
10269 [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
10270 f_logp(BSCVTY, "got Paging Command");
10271 repeat;
10272 }
10273 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10274 /* MS does not respond to Paging, TA Req runs into timeout. */
10275 f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
10276 }
10277 }
10278
10279 /* SMLC responds with failure */
10280 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10281 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10282
10283 /* BSC tells MSC about failure */
10284 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10285 locationEstimate := omit, positioningData := omit,
10286 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
10287
10288 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10289 f_verify_active_A_conn_and_clear();
10290
10291 f_sleep(2.0);
10292 setverdict(pass);
10293}
10294testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
10295 var MSC_ConnHdlr vc_conn;
10296 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10297
10298 f_init(1, true);
10299 f_sleep(1.0);
10300
10301 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10302 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10303
10304 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
10305 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010306 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010307}
10308
10309/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
10310 * over. */
10311private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10312 f_sleep(1.0);
10313
10314 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10315 f_bssap_le_register_imsi(g_pars.imsi, omit);
10316
10317 /* Register to receive the Paging Command */
10318 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10319 g_chan_nr := new_chan_nr;
10320 f_rslem_register(0, g_chan_nr);
10321
10322 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10323 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10324 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10325 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10326
10327 var PDU_BSSAP_LE plr;
10328 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10329
10330 /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
10331 * and establish Layer 3. It should use the existing A-interface conn. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010332 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 +020010333 do_clear := false, expect_bssmap_l3 := true);
10334
10335 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10336 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10337
10338 /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
10339 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10340
10341 /* SMLC got the TA from the BSC, now responds with geo information data. */
10342 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10343 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10344 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10345
10346 /* The lchan should still exist, it was from a CM Service Request. */
10347 f_mo_l3_transceive();
10348
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010349 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010350
10351 f_sleep(2.0);
10352 setverdict(pass);
10353}
10354testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
10355 var MSC_ConnHdlr vc_conn;
10356 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10357
10358 f_init(1, true);
10359 f_sleep(1.0);
10360
10361 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10362 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10363
10364 vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
10365 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010366 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010367}
10368
10369/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
10370 * the new lchan after handover. */
10371private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10372 f_sleep(1.0);
10373
10374 f_establish_fully(omit, omit);
10375 f_bssap_le_register_imsi(g_pars.imsi, omit);
10376
10377 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10378 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10379
10380 var PDU_BSSAP_LE plr;
10381 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10382
10383 /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
10384 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
10385
10386 var HandoverState hs := {
10387 rr_ho_cmpl_seen := false,
10388 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +020010389 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010390 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010391 };
10392 /* issue hand-over command on VTY */
10393 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
10394 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
10395 f_rslem_suspend(RSL1_PROC);
10396
10397 /* From the MGW perspective, a handover is is characterized by
10398 * performing one MDCX operation with the MGW. So we expect to see
10399 * one more MDCX during handover. */
10400 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
10401
10402 alt {
10403 [] as_handover(hs);
10404 }
10405
10406 var PDU_BSSAP_LE rx_bsslap;
10407
10408 interleave {
10409 /* Expect the BSC to inform the MSC about the handover */
10410 [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
10411
10412 /* Expect the BSC to inform the SMLC about the handover */
10413 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10414 f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
10415 }
10416 }
10417
10418 /* SMLC now responds with geo information data. */
10419 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10420 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10421 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10422
10423 /* lchan still active */
10424 f_mo_l3_transceive(RSL1);
10425
10426 /* MSC decides it is done now. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010427 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010428
10429 f_sleep(2.0);
10430 setverdict(pass);
10431}
10432testcase TC_ho_during_lcs_loc_req() runs on test_CT {
10433 var MSC_ConnHdlr vc_conn;
10434 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10435
10436 f_init(2, true);
10437 f_sleep(1.0);
10438 vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
10439 vc_conn.done;
Oliver Smith39f53072022-10-27 14:44:04 +020010440 f_shutdown_helper(ho := true);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010441}
10442
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010443private function f_tc_emerg_call_and_lcs_loc_req(charstring id) runs on MSC_ConnHdlr
10444{
10445 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
10446 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
10447 * another lchan. */
10448 g_pars.ra := 'b7'O;
10449 f_assignment_emerg_setup();
10450
10451 var PDU_BSSAP emerg_setup_data_ind_bssap;
10452 timer T := 3.0;
10453 T.start;
10454 alt {
10455 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
10456 var PDU_ML3_MS_NW verify_emerg_setup;
10457 verify_emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
10458 if (not isbound(verify_emerg_setup.msgs.cc.emergencySetup)) {
10459 setverdict(fail, "no emergency setup");
10460 }
10461 }
10462 [] BSSAP.receive {
10463 setverdict(fail, "unexpected BSSAP message!");
10464 }
10465 [] T.timeout {
10466 setverdict(fail, "timeout waiting for EMERGENCY SETUP!");
10467 }
10468 }
10469
10470 /* Here would usually be a CC Call Proceeding from the MSC, but what does the BSC care about DTAP. */
10471
10472 /* Do a Location Request in-between the CC call setup */
10473 f_bssap_le_register_imsi(g_pars.imsi, omit);
10474 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10475 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10476 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10477 /* SMLC got the TA from the BSC, now responds with geo information data. */
10478 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10479 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10480 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10481
10482 /* Go on with voice call assignment */
10483 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
10484 var PDU_BSSAP ass_cmd := f_gen_ass_req();
10485
10486 /* Below speechOrDataIndicator and codecList are copied from an emergency call captured during tests.
10487 * They seem a bit weird (AMR-WB, and the order differ between speechId_DataIndicator and the codecList), but
10488 * seems a good idea to see how osmo-bsc reacts to this. */
10489 ass_cmd.pdu.bssmap.assignmentRequest.channelType := {
10490 elementIdentifier := '0B'O, /* overwritten */
10491 lengthIndicator := 0, /* overwritten */
10492 speechOrDataIndicator := '0001'B, /* speech */
10493 spare1_4 := '0000'B,
10494 channelRateAndType := ChRate_TCHForH_Fpref,
10495 speechId_DataIndicator := 'c2918105'O
10496 };
10497 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({
10498 ts_CodecHR, ts_CodecAMR_WB, ts_CodecEFR, ts_CodecFR}));
10499
10500 f_rslem_dchan_queue_enable();
10501
10502 var ExpectCriteria mgcpcrit := {
10503 connid := omit,
10504 endpoint := omit,
10505 transid := omit
10506 };
10507 f_create_mgcp_expect(mgcpcrit);
10508
10509 BSSAP.send(ass_cmd);
10510
10511 var AssignmentState st := valueof(ts_AssignmentStateInit);
10512 st.voice_call := true;
10513 st.is_assignment := false;
10514 alt {
10515 [] as_modify(st);
10516 [] as_Media();
10517 [st.modify_done] BSSAP.receive(exp_compl) {
10518 setverdict(pass);
10519 }
10520 }
10521
10522 /* Voice call carries on ... */
10523 f_sleep(2.0);
10524
10525 setverdict(pass);
10526 f_perform_clear();
10527}
10528
10529testcase TC_emerg_call_and_lcs_loc_req() runs on test_CT {
10530 var MSC_ConnHdlr vc_conn;
10531 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10532
10533 f_init(1, true);
10534 f_sleep(1.0);
10535 f_vty_allow_emerg_msc(true);
10536 f_vty_allow_emerg_bts(true, 0);
10537 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req), pars);
10538 vc_conn.done;
10539 f_shutdown_helper();
10540}
10541
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010542private altstep no_bssmap_clear_req() runs on MSC_ConnHdlr {
10543 [] BSSAP.receive(tr_BSSMAP_ClearRequest) {
10544 setverdict(fail, "unexpected BSSMAP Clear Request");
10545 mtc.stop;
10546 }
10547}
10548
10549private type enumerated RslRel {
10550 RSLREL_REL_IND,
10551 RSLREL_CONN_FAIL
10552};
10553
10554private function f_emerg_call_and_lcs_loc_req_early_lchan_release(RslRel rsl_rel) runs on MSC_ConnHdlr
10555{
10556 g_pars.ra := f_rnd_ra_emerg();
10557 f_assignment_emerg_setup();
10558
10559 var PDU_BSSAP emerg_setup_data_ind_bssap;
10560 timer T := 3.0;
10561 T.start;
10562 alt {
10563 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
10564 var PDU_ML3_MS_NW verify_emerg_setup;
10565 verify_emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
10566 if (not ischosen(verify_emerg_setup.msgs.cc.emergencySetup)) {
10567 setverdict(fail, "no emergency setup");
10568 }
10569 }
10570 [] BSSAP.receive {
10571 setverdict(fail, "unexpected BSSAP message!");
10572 }
10573 [] T.timeout {
10574 setverdict(fail, "timeout waiting for EMERGENCY SETUP!");
10575 }
10576 }
10577
10578 /* Start a Location Request to locate the emergency */
10579 f_bssap_le_register_imsi(g_pars.imsi, omit);
10580 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10581 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10582 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10583
10584 /* 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
10585 * do a Clear Command when the Location Response arrives. */
10586 activate(no_bssmap_clear_req());
10587
10588 /* the lchan gets interrupted while the Location Request has no response */
10589 select (rsl_rel) {
10590 case (RSLREL_REL_IND) {
10591 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
10592 f_expect_lchan_rel(RSL, RSL_PROC);
10593 }
10594 case (RSLREL_CONN_FAIL) {
10595 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
10596 }
10597 case else {
10598 setverdict(fail, "Unknown RslRel type");
10599 mtc.stop;
10600 }
10601 }
10602
10603 /* Still expect the Location Response to find its way to the MSC. */
10604 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10605 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10606 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10607
10608 setverdict(pass);
10609
10610 select (rsl_rel) {
10611 case (RSLREL_REL_IND) {
10612 f_perform_clear_no_lchan();
10613 }
10614 case (RSLREL_CONN_FAIL) {
10615 f_perform_clear();
10616 }
10617 }
10618}
10619
10620private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind(charstring id) runs on MSC_ConnHdlr
10621{
10622 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_REL_IND);
10623}
10624
10625testcase TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() runs on test_CT {
10626 var MSC_ConnHdlr vc_conn;
10627 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10628
10629 f_init(1, true);
10630 f_sleep(1.0);
10631 f_vty_allow_emerg_msc(true);
10632 f_vty_allow_emerg_bts(true, 0);
10633 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind), pars);
10634 vc_conn.done;
10635 f_shutdown_helper();
10636}
10637
10638private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail(charstring id) runs on MSC_ConnHdlr
10639{
10640 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_CONN_FAIL);
10641}
10642
10643testcase TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() runs on test_CT {
10644 var MSC_ConnHdlr vc_conn;
10645 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10646
10647 f_init(1, true);
10648 f_sleep(1.0);
10649 f_vty_allow_emerg_msc(true);
10650 f_vty_allow_emerg_bts(true, 0);
10651 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail), pars);
10652 vc_conn.done;
10653 f_shutdown_helper();
10654}
10655
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010656/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
10657private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
10658 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10659
10660 /* Also disable attach for the single connected MSC */
10661 f_vty_msc_allow_attach(BSCVTY, { false });
10662
10663 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) ));
10664 f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
10665
10666 /* No MSC is found, expecting a proper release on RSL */
10667 interleave {
10668 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
10669 f_logp(BSCVTY, "Got RSL RR Release");
10670 }
10671 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10672 f_logp(BSCVTY, "Got RSL Deact SACCH");
10673 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010674 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010675 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
10676 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010677 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010678 }
10679 }
10680 setverdict(pass);
10681}
10682testcase TC_no_msc() runs on test_CT {
10683
10684 f_init(1, true);
10685 f_sleep(1.0);
10686 var MSC_ConnHdlr vc_conn;
10687 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10688
10689 f_ctrs_bsc_init(counternames_bsc_mscpool);
10690
10691 vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
10692 vc_conn.done;
10693
10694 f_ctrs_bsc_add("mscpool:subscr:no_msc");
10695 f_ctrs_bsc_verify();
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010696 f_shutdown_helper();
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010697}
10698
Harald Welte0ea2d5e2018-04-07 21:40:29 +020010699/* Dyn PDCH todo:
10700 * activate OSMO as TCH/F
10701 * activate OSMO as TCH/H
10702 * does the BSC-located PCU socket get the updated INFO?
10703 * what if no PCU is connected at the time?
10704 * is the info correct on delayed PCU (re)connect?
10705 */
Harald Welte94e0c342018-04-07 11:33:23 +020010706
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010707private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +020010708 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020010709 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010710
10711 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
10712 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10713 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
10714 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
10715 g_pars.ass_codec_list.codecElements[0];
10716 if (isvalue(g_pars.expect_mr_s0_s7)) {
10717 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
10718 g_pars.expect_mr_s0_s7;
10719 }
10720 }
10721 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
10722 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
10723 log("expecting ASS COMPL like this: ", exp_compl);
10724
10725 f_establish_fully(ass_cmd, exp_compl);
10726
Neels Hofmeyr8746b0d2021-06-01 17:25:39 +020010727 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 +000010728
10729 var RSL_Message rsl;
10730
10731 timer T := 5.0;
10732 T.start;
10733 alt {
10734 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
10735 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
10736 log("Rx L3 from net: ", l3);
10737 if (ischosen(l3.msgs.rrm.channelModeModify)) {
10738 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10739 mtc.stop;
10740 }
10741 }
10742 [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
10743 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10744 mtc.stop;
10745 }
10746 [] T.timeout {
10747 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
10748 setverdict(pass);
10749 }
10750 }
10751 T.stop;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010752
10753 f_perform_clear();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010754}
10755
10756/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
10757 * osmo-bsc. */
10758testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
10759 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10760 var MSC_ConnHdlr vc_conn;
10761
10762 f_init(1, true);
10763 f_sleep(1.0);
10764
10765 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10766 vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
10767 vc_conn.done;
10768 f_shutdown_helper();
10769}
10770
10771/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
10772 */
10773testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
10774 f_init_vty();
10775
10776 f_init(1, false);
10777 f_sleep(1.0);
10778
10779 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
10780
10781 var ASP_RSL_Unitdata rx_rsl_ud;
10782 timer T := 5.0;
10783
10784 T.start;
10785 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010786 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010787 if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
10788 T.stop;
10789 setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
10790 mtc.stop;
10791 }
10792 repeat;
10793 }
10794 [] T.timeout {
10795 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
10796 setverdict(pass);
10797 }
10798 }
10799}
10800
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010801private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
10802 /* First fully set up a speech lchan */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010803 f_assignment_codec(id, do_perform_clear := false);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010804
10805 /* Trigger re-assignment to another lchan */
10806 var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
10807
10808 /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
10809 * one MDCX on MGCP. */
10810 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
10811
10812 /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
10813 * as the old lchan used. */
10814 g_media.bts.ipa_crcx_seen := false;
10815 g_media.bts.ipa_mdcx_seen := false;
10816
10817 /* Send different BTS side RTP port number for the new lchan */
10818 g_media.bts.bts.port_nr := 4223;
10819
10820 f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
10821
10822 /* Trigger re-assignment. */
10823 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
10824
10825 timer T := 5.0;
10826 T.start;
10827 alt {
10828 [] as_assignment(assignment_st);
10829 [] as_Media();
10830 [] T.timeout {
10831 break;
10832 }
10833 }
10834
10835 if (not assignment_st.assignment_done) {
10836 setverdict(fail, "Assignment did not complete");
10837 mtc.stop;
10838 }
10839
10840 f_check_mgcp_expectations()
10841 setverdict(pass);
10842
10843 f_sleep(2.0);
10844 log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
10845
10846 /* Instruct BSC to clear channel */
10847 var BssmapCause cause := 0;
10848 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10849 interleave {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010850 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
10851 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010852 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010853 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010854 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010855 }
10856 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
10857 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10858 }
10859 }
Neels Hofmeyr40a45d12021-09-23 22:57:12 +020010860 f_expect_dlcx_conns();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010861
10862 f_sleep(0.5);
10863}
10864
10865testcase TC_reassignment_fr() runs on test_CT {
10866 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10867 var MSC_ConnHdlr vc_conn;
10868
10869 f_init(1, true);
10870 f_sleep(1.0);
10871
Neels Hofmeyrac432fa2021-11-02 16:45:56 +010010872 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010873
10874 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10875 vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
10876 vc_conn.done;
10877
10878 /* from f_establish_fully() */
10879 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
10880 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
10881 /* from re-assignment */
10882 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
10883 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
10884 f_ctrs_bsc_and_bts_verify();
10885 f_shutdown_helper();
10886}
10887
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010888const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
10889const charstring REEST_CLEAR := "REEST_CLEAR";
10890const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
10891
10892/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
10893 * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
10894 * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
10895 * the MSC as the CM Re-Establishment is handled.
10896 *
10897 * MS bts0 bts1 bsc msc test-component
10898 * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
10899 * | | _1 wait a bit, to settle down
10900 * |<-x x--| | _1 "lose connection"
10901 * | | REEST_LOST_CONNECTION
10902 * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
10903 * | | REEST_CLEAR
10904 * | |<-0---| _1 Clear Command on first A-conn
10905 * | |--0-->| _1 Clear Complete
10906 * | |<----------------->| | _1 Release first channel
10907 * | | REEST_CLEAR_DONE
10908 * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
10909 * |<-----------------|<-------|<-1---| _2 Clear Command, Release
10910 *
10911 */
10912private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
10913 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
10914 var PDU_BSSAP ass_cmd := f_gen_ass_req();
10915
10916 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
10917 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10918
10919 f_establish_fully(ass_cmd, exp_compl);
10920
10921 /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
10922 * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
10923 * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
10924 f_sleep(2.0);
10925 COORD.send(REEST_LOST_CONNECTION);
10926
10927 alt {
10928 [] COORD.receive(REEST_CLEAR);
10929 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10930 setverdict(fail, "Unexpected channel release");
10931 mtc.stop;
10932 }
10933 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
10934 setverdict(fail, "Unexpected channel release");
10935 mtc.stop;
10936 }
10937 }
10938 f_perform_clear()
Neels Hofmeyr969abd02021-09-23 22:24:08 +020010939 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010940 COORD.send(REEST_CLEAR_DONE);
10941}
10942
10943private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
10944 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
10945
10946 /* The MS lost the connection on the first channel, now establishes another one */
10947 COORD.receive(REEST_LOST_CONNECTION);
10948
10949 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
10950 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
10951 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
10952
10953 f_create_bssmap_exp(l3_enc);
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010954 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 +020010955 BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
10956
10957 /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
10958 COORD.send(REEST_CLEAR);
10959 COORD.receive(REEST_CLEAR_DONE);
10960
10961 f_sleep(2.0);
10962
10963 /* Answer the CM Re-Establishment with an Assignment Command. */
10964 var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
10965 var PDU_BSSAP ass_cmd := f_gen_ass_req();
10966 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
10967 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10968
10969 var AssignmentState st := valueof(ts_AssignmentStateInit);
10970 st.voice_call := true;
10971 st.is_assignment := true;
10972
10973 var ExpectCriteria mgcpcrit := {
10974 connid := omit,
10975 endpoint := omit,
10976 transid := omit
10977 };
10978 f_create_mgcp_expect(mgcpcrit);
10979
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010980 f_rslem_dchan_queue_enable(RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010981
10982 BSSAP.send(ass_cmd);
10983
10984 var PDU_BSSAP bssap;
10985
10986 alt {
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010987 [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
10988 [] as_Media_ipacc(RSL1, RSL2);
10989 [] as_Media_mgw();
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010990 [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
10991 break;
10992 }
10993 }
10994
10995 f_sleep(3.0);
10996
10997 f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010998 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010999}
11000
11001testcase TC_cm_reestablishment() runs on test_CT {
11002 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
11003 var MSC_ConnHdlr vc_conn1;
11004
11005 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
11006 var MSC_ConnHdlr vc_conn2;
11007 pars2.imsi := pars1.imsi;
11008 pars2.media_nr := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011009 pars2.expect_tsc := c_BtsParams[1].tsc;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011010
11011 f_init(2, true, guard_timeout := 40.0);
11012 f_sleep(1.0);
11013
11014 vc_conn1 := f_start_handler_create(pars1);
11015 vc_conn2 := f_start_handler_create(pars2);
11016 connect(vc_conn1:COORD, vc_conn2:COORD);
11017 f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
11018 f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
11019 vc_conn1.done;
11020 vc_conn2.done;
11021
11022 f_shutdown_helper();
11023}
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011024
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011025function f_exp_ipa_rx_nonfatal(template (present) RSL_Message t_rx,
11026 boolean ignore_other_rx := true,
11027 BtsTrxIdx idx := {0, 0},
11028 float Tval := 2.0)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011029runs on test_CT return template (omit) RSL_Message {
11030 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011031 timer T := Tval;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011032
11033 T.start;
11034 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011035 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011036 T.stop;
11037 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011038 [ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
11039 [not ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011040 log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
11041 T.stop;
11042 return omit;
11043 }
11044 [] T.timeout {
11045 return omit;
11046 }
11047 }
11048 return rx_rsl_ud.rsl;
11049}
11050
11051private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
11052 f_vty_enter_cfg_bts(pt, bts_nr);
11053 f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
11054 f_vty_transceive(pt, "exit");
11055 f_vty_transceive(pt, "exit");
11056 f_vty_transceive(pt, "exit");
11057}
11058
11059private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +030011060 template (present) RslChannelNr chan_nr := ?,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011061 template (present) uint12_t arfcn := ?,
11062 template (present) uint3_t tsc := ?)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011063{
11064 var RSL_IE_Body full_imm_ass_info;
11065 if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
11066 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
11067 mtc.stop;
11068 }
11069
11070 var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
11071 var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
11072 fn := fn,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011073 ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011074 page_mode := ?);
11075 if (not match(rr_imm_ass, expect_imm_ass)) {
11076 log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
11077 setverdict(fail, "Failed to match Immediate Assignment");
11078 mtc.stop;
11079 }
11080}
11081
11082testcase TC_imm_ass_post_chan_ack() runs on test_CT {
11083 var RSL_Message chan_act;
11084 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011085 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011086
11087 f_init(1, false);
11088 f_sleep(1.0);
11089
11090 /* (should be the default anyway, just to make things clear) */
11091 f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
11092
11093 /* RA containing reason=LU */
11094 var GsmFrameNumber fn := 2342;
11095 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011096 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011097
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011098 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011099
11100 /* First send the Chan Act ACK */
11101 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011102 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011103 var RSL_IE_Body chan_ident_ie;
11104 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11105 setverdict(fail, "RSL Channel Identification IE is absent");
11106 mtc.stop;
11107 }
11108
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011109 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011110
11111 /* Then expect the Immediate Assignment, after we ACKed the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011112 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011113
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011114 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11115 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011116
11117 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011118 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011119
11120 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011121 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011122 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011123 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11124
11125 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011126 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011127 f_shutdown_helper();
11128}
11129
11130testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
11131 var RSL_Message chan_act;
11132 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011133 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011134
11135 f_init(1, false);
11136 f_sleep(1.0);
11137
11138 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11139
11140 /* RA containing reason=LU */
11141 var GsmFrameNumber fn := 2342;
11142 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011143 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011144
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011145 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011146 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011147 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011148 var RSL_IE_Body chan_ident_ie;
11149 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11150 setverdict(fail, "RSL Channel Identification IE is absent");
11151 mtc.stop;
11152 }
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011153
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011154 /* (set bts 0 cfg back to default) */
11155 f_vty_set_imm_ass(BSCVTY);
11156
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011157 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011158 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011159 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11160 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011161
11162 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011163 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011164
11165 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011166 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011167
11168 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011169 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011170 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011171 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11172
11173 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011174 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011175 f_shutdown_helper();
11176}
11177
Neels Hofmeyr23158742021-09-07 19:08:07 +020011178testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
11179 var RSL_Message chan_act;
11180 var RSL_Message imm_ass;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011181 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr23158742021-09-07 19:08:07 +020011182
11183 f_init(1, false);
11184 f_sleep(1.0);
11185
11186 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11187
11188 /* RA containing reason=LU */
11189 var GsmFrameNumber fn := 2342;
11190 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011191 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011192
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011193 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011194 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011195 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr23158742021-09-07 19:08:07 +020011196 var RSL_IE_Body chan_ident_ie;
11197 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11198 setverdict(fail, "RSL Channel Identification IE is absent");
11199 mtc.stop;
11200 }
11201
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011202 /* (set bts 0 cfg back to default) */
11203 f_vty_set_imm_ass(BSCVTY);
11204
Neels Hofmeyr23158742021-09-07 19:08:07 +020011205 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011206 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011207 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11208 chan_ident_ie.chan_ident.ch_desc.v.tsc);
11209
11210 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011211 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011212
11213 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011214 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011215
11216 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011217 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011218 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr23158742021-09-07 19:08:07 +020011219 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11220
11221 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011222 f_perform_clear_test_ct(dt);
Neels Hofmeyr23158742021-09-07 19:08:07 +020011223 f_shutdown_helper();
11224}
11225
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011226testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
11227 /* change Timeslot 6 before f_init() starts RSL */
11228 f_init_vty();
11229 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11230 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11231
11232 f_init(1, false);
11233 f_sleep(1.0);
11234
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011235 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011236 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11237 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011238 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11239 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011240
11241 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11242 f_ts_set_chcomb(0, 0, 6, "PDCH");
11243
11244 /* block all static timeslots so that the dyn TS will be used */
11245 f_disable_all_tch_f();
11246 f_disable_all_tch_h();
11247 f_disable_all_sdcch();
11248
11249 var RSL_Message chan_act;
11250 var RSL_Message imm_ass;
11251
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011252 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11253
11254 /* RA containing reason=LU */
11255 var GsmFrameNumber fn := 2342;
11256 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011257 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011258
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011259 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011260 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
11261 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011262
11263 /* Now activation as SDCCH8 */
11264 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011265 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011266
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011267 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011268 var RSL_IE_Body chan_ident_ie;
11269 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11270 setverdict(fail, "RSL Channel Identification IE is absent");
11271 mtc.stop;
11272 }
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011273
11274 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011275 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011276 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11277 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011278
11279 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011280 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011281
11282 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011283 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011284
11285 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011286 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011287 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011288 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11289
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011290 /* (set bts 0 cfg back to default) */
11291 f_vty_set_imm_ass(BSCVTY);
11292
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011293 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011294 f_perform_clear_test_ct(dt);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011295 f_shutdown_helper();
11296}
11297
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011298testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
11299 /* change Timeslot 6 before f_init() starts RSL */
11300 f_init_vty();
11301 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11302 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11303
11304 f_init(1, false);
11305 f_sleep(1.0);
11306
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011307 var octetstring l3_payload := gen_l3_valid_payload();
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011308 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11309 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011310 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11311 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011312
11313 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11314 f_ts_set_chcomb(0, 0, 6, "PDCH");
11315
11316 /* block all static timeslots so that the dyn TS will be used */
11317 f_disable_all_tch_f();
11318 f_disable_all_tch_h();
11319 f_disable_all_sdcch();
11320
11321 var RSL_Message chan_act;
11322 var RSL_Message imm_ass;
11323
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011324 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11325
11326 /* RA containing reason=LU */
11327 var GsmFrameNumber fn := 2342;
11328 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011329 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011330
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011331 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011332 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011333
11334 /* And already the Immediate Assignment even before the PDCH Deact ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011335 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011336
11337 /* continue the Osmo style PDCH Deact (usual chan rel) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011338 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011339
11340 /* Now activation as SDCCH8 */
11341 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011342 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011343
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011344 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011345 var RSL_IE_Body chan_ident_ie;
11346 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11347 setverdict(fail, "RSL Channel Identification IE is absent");
11348 mtc.stop;
11349 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011350 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011351
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011352 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11353 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011354
11355 /* Check that the lchan is working */
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011356 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011357
11358 var BSSAP_N_CONNECT_ind rx_c_ind;
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011359 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011360 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011361 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11362
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011363 /* (set bts 0 cfg back to default) */
11364 f_vty_set_imm_ass(BSCVTY);
11365
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011366 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011367 f_perform_clear_test_ct(dt);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011368 f_shutdown_helper();
11369}
11370
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011371/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
11372testcase TC_ctrl_trx_rf_locked() runs on test_CT {
11373 var MSC_ConnHdlr vc_conn;
11374
11375 f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
11376 f_sleep(1.0);
11377
11378 /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
11379 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11380 "0,0,operational,unlocked,on,rsl-up;" &
11381 "1,0,operational,unlocked,on,rsl-up;" &
11382 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011383 "2,1,operational,unlocked,on,rsl-down;" &
11384 "2,2,operational,unlocked,on,rsl-down;" &
11385 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011386 "3,0,inoperational,locked,on,rsl-down;");
11387
11388 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock BTS 1 TRX 0");
11389 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11390 /* give it a moment to settle the FSM status */
11391 f_sleep(1.0);
11392
11393 /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
11394 * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
11395 * of "off"? But that's for a future patch if at all. */
11396 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11397 "0,0,operational,unlocked,on,rsl-up;" &
11398 "1,0,operational,locked,on,rsl-up;" &
11399 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011400 "2,1,operational,unlocked,on,rsl-down;" &
11401 "2,2,operational,unlocked,on,rsl-down;" &
11402 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011403 "3,0,inoperational,locked,on,rsl-down;");
11404
11405 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
11406 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11407 f_sleep(1.0);
11408 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11409 "0,0,operational,unlocked,on,rsl-up;" &
11410 "1,0,operational,locked,on,rsl-up;" &
11411 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011412 "2,1,operational,unlocked,on,rsl-down;" &
11413 "2,2,operational,unlocked,on,rsl-down;" &
11414 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011415 "3,0,inoperational,locked,on,rsl-down;");
11416
11417 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
11418 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
11419 f_sleep(1.0);
11420 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11421 "0,0,operational,unlocked,on,rsl-up;" &
11422 "1,0,operational,unlocked,on,rsl-up;" &
11423 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011424 "2,1,operational,unlocked,on,rsl-down;" &
11425 "2,2,operational,unlocked,on,rsl-down;" &
11426 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011427 "3,0,inoperational,locked,on,rsl-down;");
11428
11429 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
11430 f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
11431 f_sleep(1.0);
11432 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11433 "0,0,operational,unlocked,on,rsl-up;" &
11434 "1,0,operational,unlocked,on,rsl-up;" &
11435 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011436 "2,1,operational,unlocked,on,rsl-down;" &
11437 "2,2,operational,unlocked,on,rsl-down;" &
11438 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011439 "3,0,inoperational,locked,on,rsl-down;");
11440
11441 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
11442 f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
11443 f_sleep(1.0);
11444 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11445 "0,0,operational,unlocked,on,rsl-up;" &
11446 "1,0,operational,unlocked,on,rsl-up;" &
11447 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011448 "2,1,operational,unlocked,on,rsl-down;" &
11449 "2,2,operational,unlocked,on,rsl-down;" &
11450 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011451 "3,0,inoperational,locked,on,rsl-down;");
11452
11453 f_shutdown_helper();
11454}
11455
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011456const CounterNameVals counternames_cm_serv_rej := {
11457 { "cm_serv_rej", 0 },
11458 { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
11459 { "cm_serv_rej:illegal_ms", 0 },
11460 { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
11461 { "cm_serv_rej:imei_not_accepted", 0 },
11462 { "cm_serv_rej:illegal_me", 0 },
11463 { "cm_serv_rej:plmn_not_allowed", 0 },
11464 { "cm_serv_rej:loc_not_allowed", 0 },
11465 { "cm_serv_rej:roaming_not_allowed", 0 },
11466 { "cm_serv_rej:network_failure", 0 },
11467 { "cm_serv_rej:synch_failure", 0 },
11468 { "cm_serv_rej:congestion", 0 },
11469 { "cm_serv_rej:srv_opt_not_supported", 0 },
11470 { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
11471 { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
11472 { "cm_serv_rej:call_can_not_be_identified", 0 },
11473 { "cm_serv_rej:incorrect_message", 0 },
11474 { "cm_serv_rej:invalid_mandantory_inf", 0 },
11475 { "cm_serv_rej:msg_type_not_implemented", 0 },
11476 { "cm_serv_rej:msg_type_not_compatible", 0 },
11477 { "cm_serv_rej:inf_eleme_not_implemented", 0 },
11478 { "cm_serv_rej:condtional_ie_error", 0 },
11479 { "cm_serv_rej:msg_not_compatible", 0 },
11480 { "cm_serv_rej:protocol_error", 0 },
11481 { "cm_serv_rej:retry_in_new_cell", 0 }
11482};
11483
11484private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
11485{
11486 f_create_chan_and_exp();
Vadim Yanitskiya7fc5a62021-12-04 20:10:08 +030011487 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011488 BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011489 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_CM_SERV_REJ));
11490 f_perform_clear();
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011491 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011492}
11493testcase TC_cm_serv_rej() runs on test_CT {
11494 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11495 var MSC_ConnHdlr vc_conn;
11496
11497 f_init(1, true);
11498 f_sleep(1.0);
11499
11500 f_ctrs_bts_init(1, counternames_cm_serv_rej);
11501
11502 vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
11503 vc_conn.done;
11504
11505 f_ctrs_bts_add(0, "cm_serv_rej", 1);
11506 f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
11507 f_ctrs_bts_verify();
11508
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011509 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011510 f_shutdown_helper();
11511}
11512
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011513/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
11514 * Activ Ack (SYS#5627). */
11515private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
11516 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Vadim Yanitskiyf0310e32021-10-26 00:30:59 +030011517
11518 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11519 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011520
11521 var BSSMAP_FIELD_CodecType codecType;
11522 codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
11523
11524 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
11525
11526 /* First establish a signalling lchan */
11527 f_create_chan_and_exp();
11528 f_rslem_dchan_queue_enable();
11529
11530 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011531
11532 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
Vadim Yanitskiy6be4cf42022-06-04 21:25:47 +060011533 activate(as_Media_mgw(fail_on_dlcx := false));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011534
11535 var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
11536 f_rslem_register(0, chan_nr);
11537
11538 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
11539 BSSAP.send(ass_cmd);
11540
11541
11542 /* Wait for the Channel Activ for the TCH channel */
11543 var ASP_RSL_Unitdata rx_rsl_ud;
11544 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
11545
11546 /* make the original SDCCH disappear */
11547 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
11548
11549 /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
11550 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
11551
11552 interleave {
11553 [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
11554 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
11555 }
11556
11557 BSSAP.send(ts_BSSMAP_ClearCommand(0));
11558 BSSAP.receive(tr_BSSMAP_ClearComplete);
11559 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11560
11561 var MgcpCommand mgcp;
Vadim Yanitskiy6be4cf42022-06-04 21:25:47 +060011562 var MGCP_RecvFrom mrf;
11563 var template MgcpMessage msg_dlcx := { command := tr_DLCX };
11564 alt {
11565 [g_pars.aoip] MGCP.receive(tr_DLCX) -> value mgcp {
11566 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
11567 }
11568 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
11569 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
11570 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
11571 }));
11572 }
11573 }
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011574
11575 f_sleep(0.5);
11576}
11577testcase TC_lost_sdcch_during_assignment() runs on test_CT {
11578 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11579 var MSC_ConnHdlr vc_conn;
11580
11581 f_init(1, true);
11582 f_sleep(1.0);
11583
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011584 vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
11585 vc_conn.done;
11586
11587 f_shutdown_helper();
11588}
11589
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011590const CounterNameVals counternames_bsc_bts_all_available_allocated := {
11591 { "all_allocated:sdcch", 0 },
11592 { "all_allocated:static_sdcch", 0 },
11593 { "all_allocated:tch", 0 },
11594 { "all_allocated:static_tch", 0 }
11595}
11596
11597private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
11598{
11599 /* Make sure counters settle first */
11600 f_sleep(1.0);
11601
11602 /* Take a baseline of counters */
11603 f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
11604
11605 /* Elapse some time so that we see changes in counters, hopefully where expected */
11606 f_sleep(2.0);
11607
11608 /* Get new counters */
11609 var charstring_list all_changed := {};
11610 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
11611 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
11612
11613 /* Compare with expectations */
11614 var charstring_list all_expect_changed := {};
11615 for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
11616 all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
11617 }
11618 f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
11619}
11620
11621testcase TC_ratectr_all_available_allocated() runs on test_CT {
11622 var ASP_RSL_Unitdata rsl_ud;
11623 var integer i;
11624 var integer chreq_total, chreq_nochan;
11625
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011626 f_init(1, guard_timeout := 60.0);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011627 f_sleep(1.0);
11628
11629 /* Exhaust all dedicated SDCCH lchans.
11630 /* GSM 44.018 Table 9.1.8.2:
11631 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11632 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011633 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011634 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011635 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 +020011636 }
11637
11638 /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
11639 * level.
11640 * All SDCCH are now occupied. */
11641 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11642
11643 /* Also fill up all remaining (TCH) channels */
11644 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011645 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 +020011646 }
11647
11648 /* All TCH are now also occupied */
11649 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11650 "all_allocated:tch", "all_allocated:static_tch"});
11651
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011652 /* Clean up SDCCH lchans */
11653 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11654 f_perform_clear_test_ct(chan_cleanup[i]);
11655 }
11656
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011657 f_shutdown_helper();
11658}
11659
11660testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
11661 var ASP_RSL_Unitdata rsl_ud;
11662 var integer i;
11663 var integer chreq_total, chreq_nochan;
11664
11665 f_init_vty();
11666 f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
11667 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11668 /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
11669
11670 f_init(1, guard_timeout := 60.0);
11671 f_sleep(1.0);
11672
11673 /* The dyn TS wants to activate PDCH mode, ACK that. */
11674 var RslChannelNr chan_nr;
11675 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011676 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11677 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011678
11679 /* Exhaust all dedicated SDCCH lchans.
11680 /* GSM 44.018 Table 9.1.8.2:
11681 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11682 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011683 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011684 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011685 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 +020011686 }
11687
11688 /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
11689 * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
11690 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
11691
11692 /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
11693 * Will release them later, so remember all the DchanTuples. */
11694 var DchanTuples dyn_sddch := {};
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011695 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 +020011696
11697 /* Also occupy the seven other SDCCH of the dyn TS */
11698 for (i := 0; i < 7; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011699 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 +020011700 }
11701
11702 /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
11703 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11704
11705 /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
11706 for (i := 0; i < 5; i := i+1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011707 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 +020011708 }
11709
11710 /* All TCH lchans are now also occupied, both static and dynamic */
11711 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11712 "all_allocated:tch", "all_allocated:static_tch"});
11713
11714 /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
11715 * incrementing. */
11716 var BssmapCause cause := 0;
11717 var DchanTuple dt := dyn_sddch[0];
11718 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011719 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011720
11721 /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
11722 * count as occupied, so those still both increment. */
11723 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
11724 "all_allocated:tch", "all_allocated:static_tch"});
11725
11726 /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
11727 for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
11728 dt := dyn_sddch[i];
11729 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011730 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011731 }
11732
11733 /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
11734 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011735 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11736 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011737
11738 /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
11739 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
11740
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011741 /* Clean up SDCCH lchans */
11742 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11743 f_perform_clear_test_ct(chan_cleanup[i]);
11744 }
11745
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011746 /* clean up config */
11747 f_ts_reset_chcomb(0);
11748
11749 f_shutdown_helper();
11750}
11751
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011752private function f_TC_chan_alloc_algo(DchanTuple dt, BtsTrxIdx idx)
11753runs on test_CT {
11754 /* MSC sends an Assignment Request */
11755 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11756 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11757 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11758 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
11759
11760 /* Expect the BSC to allocate a TCH channel on the given BTS/TRX */
11761 var RSL_Message rsl_chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
11762 /* Send CHAN ACT NACK, so that the requested TCH channel becomes BORKEN */
11763 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(rsl_chan_act.ies[0].body.chan_nr, RSL_ERR_EQUIPMENT_FAIL), idx);
11764 /* Expect to receive an Assignment Failure */
11765 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail));
11766}
11767
11768testcase TC_chan_alloc_algo_ascending() runs on test_CT {
11769 /* We need to access BTS2, which has 4 TRXs */
11770 f_init(nr_bts := 3);
11771
11772 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020011773 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011774
11775 f_vty_enter_cfg_bts(BSCVTY, 2);
11776 f_vty_transceive(BSCVTY, "channel allocator ascending");
11777 f_vty_transceive(BSCVTY, "end");
11778
11779 /* Expect the BSC to allocate 4 x TCH/F channels on BTS2/TRX0 */
11780 for (var integer i := 0; i < 4; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011781 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011782 f_TC_chan_alloc_algo(dt, {2, 0});
11783 f_perform_clear_test_ct(dt);
11784 }
11785
11786 /* At this point all 4 x TCH/F channels are BORKEN, but they will be
11787 * resurrected upon the A-bis/OML link re-establishment. */
11788 f_shutdown_helper();
11789}
11790
11791testcase TC_chan_alloc_algo_descending() runs on test_CT {
11792 /* We need to access BTS2, which has 4 TRXs */
11793 f_init(nr_bts := 3);
11794
11795 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020011796 vc_MGCP[0].stop;
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011797
11798 f_vty_enter_cfg_bts(BSCVTY, 2);
11799 f_vty_transceive(BSCVTY, "channel allocator descending");
11800 f_vty_transceive(BSCVTY, "end");
11801
11802 /* Expect the BSC to allocate 5 x TCH/F channels on BTS2/TRX3 */
11803 for (var integer i := 0; i < 5; i := i + 1) {
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011804 var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011805 f_TC_chan_alloc_algo(dt, {2, 3});
11806 f_perform_clear_test_ct(dt);
11807 }
11808
11809 /* At this point all 5 x TCH/F channels are BORKEN, but they will be
11810 * resurrected upon the A-bis/OML link re-establishment. */
11811 f_shutdown_helper();
11812}
11813
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011814testcase TC_chan_alloc_algo_ass_dynamic() runs on test_CT {
11815 const BtsTrxIdx TRX0 := {2, 0};
11816 const BtsTrxIdx TRX3 := {2, 3};
11817
11818 /* We need to access BTS2, which has 4 TRXs */
11819 f_init(nr_bts := 3);
11820
11821 /* HACK: work around "Couldn't find Expect for CRCX" */
Pau Espin Pedrol3c630532022-10-20 19:00:11 +020011822 vc_MGCP[0].stop;
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011823
11824 f_vty_enter_cfg_bts(BSCVTY, 2);
11825 f_vty_transceive(BSCVTY, "channel allocator mode assignment dynamic");
11826 f_vty_transceive(BSCVTY, "channel allocator dynamic-param ul-rxlev thresh 50 avg-num 2");
11827 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 0");
11828 f_vty_transceive(BSCVTY, "end");
11829
11830 var DchanTuple dt;
11831
11832 f_logp(BSCVTY, "Case a) Unknown Uplink RxLev, fall-back to ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011833 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011834 f_TC_chan_alloc_algo(dt, TRX0);
11835 f_perform_clear_test_ct(dt);
11836
11837 f_logp(BSCVTY, "Case b) Not enough RxLev samples, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011838 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011839 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11840 ts_RSL_IE_UplinkMeas(30, 0),
11841 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011842 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011843 f_TC_chan_alloc_algo(dt, TRX0);
11844 f_perform_clear_test_ct(dt);
11845
11846 f_logp(BSCVTY, "Case c) Uplink RxLev below the threshold, use ascending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011847 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011848 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11849 ts_RSL_IE_UplinkMeas(45, 0),
11850 ts_RSL_IE_BS_Power(0)), TRX0);
11851 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
11852 ts_RSL_IE_UplinkMeas(48, 0),
11853 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011854 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011855 f_TC_chan_alloc_algo(dt, TRX0);
11856 f_perform_clear_test_ct(dt);
11857
11858 f_logp(BSCVTY, "Case d) Uplink RxLev above the threshold, use descending");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011859 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011860 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11861 ts_RSL_IE_UplinkMeas(50, 0),
11862 ts_RSL_IE_BS_Power(0)), TRX0);
11863 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
11864 ts_RSL_IE_UplinkMeas(58, 0),
11865 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011866 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011867 f_TC_chan_alloc_algo(dt, TRX3);
11868 f_perform_clear_test_ct(dt);
11869
11870 f_vty_enter_cfg_bts(BSCVTY, 2);
11871 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 90");
11872 f_vty_transceive(BSCVTY, "end");
11873
11874 f_logp(BSCVTY, "Case e) Uplink RxLev above the threshold, but C0 load is not");
Pau Espin Pedrolcc77b492023-01-02 18:56:37 +010011875 dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011876 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11877 ts_RSL_IE_UplinkMeas(50, 0),
11878 ts_RSL_IE_BS_Power(0)), TRX0);
11879 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
11880 ts_RSL_IE_UplinkMeas(58, 0),
11881 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011882 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011883 f_TC_chan_alloc_algo(dt, TRX0);
11884 f_perform_clear_test_ct(dt);
11885
11886 f_vty_enter_cfg_bts(BSCVTY, 2);
11887 f_vty_transceive(BSCVTY, "channel allocator ascending");
11888 f_vty_transceive(BSCVTY, "end");
11889
11890 /* At this point some TCH/F channels are BORKEN, but they will be
11891 * resurrected upon the A-bis/OML link re-establishment. */
11892 f_shutdown_helper();
11893}
11894
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020011895private function f_vty_mgw_enable(integer mgw_nr := 1) runs on test_CT {
11896 var rof_charstring cmds := {
11897 "remote-ip " & mp_test_ip,
11898 "remote-port " & int2str(2427 + mgw_nr)
11899 };
11900 f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
11901 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " reconnect")
11902}
11903private function f_vty_mgw_disable(integer mgw_nr := 1) runs on test_CT {
11904 f_vty_config3(BSCVTY, {"network"}, { "no mgw " &int2str(mgw_nr) });
11905}
11906private function f_vty_mgw_block(integer mgw_nr := 1, boolean blocked := true) runs on test_CT {
11907 var charstring arg;
11908 if (blocked) {
11909 arg := "block";
11910 } else {
11911 arg := "unblock";
11912 }
11913 f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " " & arg);
11914}
11915private const charstring COORD_CMD_ESTABLISHED := "COORD_CMD_ESTABLISHED";
11916private function f_TC_mgwpool_call_seq_1(charstring id) runs on MSC_ConnHdlr {
11917 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
11918 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11919 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11920 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11921
11922 f_establish_fully(ass_cmd, exp_compl);
11923 COORD.send(COORD_CMD_ESTABLISHED);
11924
11925 COORD.receive(COORD_CMD_ESTABLISHED);
11926 f_perform_clear()
11927 f_create_mgcp_delete_ep(g_media.mgcp_ep);
11928}
11929private function f_TC_mgwpool_call_seq_2(charstring id) runs on MSC_ConnHdlr {
11930 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
11931 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11932 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11933 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11934
11935
11936 COORD.receive(COORD_CMD_ESTABLISHED);
11937 f_establish_fully(ass_cmd, exp_compl);
11938 COORD.send(COORD_CMD_ESTABLISHED);
11939
11940 f_perform_clear()
11941 f_create_mgcp_delete_ep(g_media.mgcp_ep);
11942}
11943/* Test load is spread around 2 available MGWs */
11944testcase TC_mgwpool_all_used() runs on test_CT {
11945 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
11946 var MSC_ConnHdlr vc_conn1;
11947 pars1.mgwpool_idx := 0;
11948
11949 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
11950 var MSC_ConnHdlr vc_conn2;
11951 pars2.mgwpool_idx := 1;
11952
11953 f_init(1, true, nr_mgw := 2);
11954 f_sleep(1.0);
11955
11956 f_vty_mgw_enable(1);
11957
11958 vc_conn1 := f_start_handler_create(pars1);
11959 vc_conn2 := f_start_handler_create(pars2);
11960 connect(vc_conn1:COORD, vc_conn2:COORD);
11961 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
11962 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
11963 vc_conn1.done;
11964 vc_conn2.done;
11965
11966 f_vty_mgw_disable(1);
11967
11968 f_shutdown_helper();
11969}
11970
11971/* Test blocked MGW in the pool are not selected */
11972testcase TC_mgwpool_blocked_not_used() runs on test_CT {
11973 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
11974 var MSC_ConnHdlr vc_conn1;
11975 pars1.mgwpool_idx := 0;
11976
11977 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
11978 var MSC_ConnHdlr vc_conn2;
11979 pars2.mgwpool_idx := 0; /* expect it in the first one, since the second will be blocked */
11980 pars2.media_nr := 2;
11981
11982 f_init(1, true, nr_mgw := 2);
11983 f_sleep(1.0);
11984
11985 f_vty_mgw_enable(1);
11986 f_vty_mgw_block(1, true);
11987
11988 vc_conn1 := f_start_handler_create(pars1);
11989 vc_conn2 := f_start_handler_create(pars2);
11990 connect(vc_conn1:COORD, vc_conn2:COORD);
11991 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
11992 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
11993 vc_conn1.done;
11994 vc_conn2.done;
11995
11996 f_vty_mgw_disable(1);
11997
11998 f_shutdown_helper();
11999}
12000
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012001/* Test BTS pinning to an MGW is applied */
12002testcase TC_mgwpool_pin_bts() runs on test_CT {
12003 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
12004 var MSC_ConnHdlr vc_conn1;
12005 pars1.mgwpool_idx := 0;
12006
12007 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
12008 var MSC_ConnHdlr vc_conn2;
12009 pars2.mgwpool_idx := 0; /* expect it in the first one, since the BTS is pinned to the first MGW */
12010 pars2.media_nr := 2;
12011
12012 f_init(1, true, nr_mgw := 2);
12013 f_sleep(1.0);
12014
12015 f_vty_mgw_enable(1);
12016 f_vty_cfg_bts(BSCVTY, 0, { "mgw pool-target 0" });
12017
12018 vc_conn1 := f_start_handler_create(pars1);
12019 vc_conn2 := f_start_handler_create(pars2);
12020 connect(vc_conn1:COORD, vc_conn2:COORD);
12021 f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
12022 f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
12023 vc_conn1.done;
12024 vc_conn2.done;
12025
12026 f_vty_cfg_bts(BSCVTY, 0, { "no mgw pool-target" } );
Vadim Yanitskiy389d7e02022-10-25 17:44:05 +070012027 f_vty_mgw_disable(1);
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012028
12029 f_shutdown_helper();
12030}
12031
Oliver Smithc9a5f532022-10-21 11:32:23 +020012032private function f_tc_ho_meas_rep_multi_band(charstring id) runs on MSC_ConnHdlr {
12033 g_pars := f_gen_test_hdlr_pars();
12034 var PDU_BSSAP ass_req := f_gen_ass_req();
12035 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
12036 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
12037 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
12038 f_establish_fully(ass_req, exp_compl);
12039
12040 /* Send a measurement report with bad rxlev except on 3rd entry. The
12041 * measurement report is divided into two sub lists, as described in
12042 * 3GPP TS 04.08 § 10.5.2.20. */
12043 var NcellReports neighbor_rep := {
12044 /* Sub list 1: same band */
Oliver Smitha6773042022-10-24 12:56:30 +020012045 { rxlev := 0, bcch_freq := 0, bsic := 12 }, /* ARFCN 800, band 1800, LAC 98 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012046 /* Sub list 2: different band */
Oliver Smitha6773042022-10-24 12:56:30 +020012047 { rxlev := 0, bcch_freq := 1, bsic := 13 }, /* ARFCN 200, band 850, LAC 97 */
12048 { rxlev := 40, bcch_freq := 2, bsic := 14 }, /* ARFCN 1000, band 900, LAC 99 */
12049 { rxlev := 0, bcch_freq := 3, bsic := 11 } /* ARFCN 0, band 900, LAC 96 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012050 };
12051 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
12052 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
12053 l3_mr, 0));
12054
12055 /* Expect a handover to the third entry. If the BSC parsed the report
Oliver Smitha6773042022-10-24 12:56:30 +020012056 * correctly, the third entry has LAC 99. */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012057 var template BSSMAP_FIELD_CellIdentificationList cid_list := {
Oliver Smitha6773042022-10-24 12:56:30 +020012058 cIl_LAC := { ts_BSSMAP_CI_LAC(99) }
Oliver Smithc9a5f532022-10-21 11:32:23 +020012059 };
12060 alt {
12061 [] BSSAP.receive(tr_BSSMAP_HandoverRequired(cid_list := cid_list)) {
12062 setverdict(pass);
12063 }
12064 [] BSSAP.receive(tr_BSSMAP_HandoverRequired()) {
12065 setverdict(fail, "Handover has unexpected LAC in Cell Identification List. The BSC probably"
12066 & " didn't parse the multi-band measurement report correctly.");
12067 }
12068 }
12069
12070 f_ho_out_of_this_bsc(skip_meas_rep := true);
12071}
12072testcase TC_ho_meas_rep_multi_band() runs on test_CT {
12073 /* Verify that the BSC parses the measurement report correctly when
12074 * neighbors in multiple bands are configured (OS#5717). See
12075 * gsm_arfcn2band_rc() in libosmocore src/gsm/gsm_utils.c for the
12076 * ARFCN -> band mapping. The MS is connected to band 1800. */
12077 var MSC_ConnHdlr vc_conn;
12078
12079 f_init_vty();
12080 f_bts_0_cfg(BSCVTY,
12081 {"neighbor-list mode automatic",
12082 "handover 1",
12083 "handover algorithm 2",
12084 "handover2 window rxlev averaging 1",
12085 "no neighbors",
12086 "neighbor lac 99 arfcn 1000 bsic any", /* band 900 */
12087 "neighbor lac 98 arfcn 800 bsic any", /* band 1800 */
12088 "neighbor lac 97 arfcn 200 bsic any", /* band 850 */
Oliver Smitha6773042022-10-24 12:56:30 +020012089 "neighbor lac 96 arfcn 0 bsic any"}); /* band 900 */
Oliver Smithc9a5f532022-10-21 11:32:23 +020012090 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
12091
12092 f_init(1, true);
12093 f_sleep(1.0);
12094
12095 f_ctrs_bsc_and_bts_handover_init();
12096
12097 vc_conn := f_start_handler(refers(f_tc_ho_meas_rep_multi_band));
12098 vc_conn.done;
12099
12100 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
12101 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
12102 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
12103 f_ctrs_bsc_and_bts_add(0, "handover:completed");
12104 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
12105 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
12106 f_ctrs_bsc_and_bts_verify();
12107 f_shutdown_helper(ho := true);
12108}
12109
Harald Welte28d943e2017-11-25 15:00:50 +010012110control {
Harald Welte898113b2018-01-31 18:32:21 +010012111 /* CTRL interface testing */
Harald Welte4003d112017-12-09 22:35:39 +010012112 execute( TC_ctrl_msc_connection_status() );
Stefan Sperlingb041b3d2018-01-03 17:14:55 +010012113 execute( TC_ctrl_msc0_connection_status() );
Neels Hofmeyrf65ce872021-09-23 18:40:10 +020012114 /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
12115 * these in the AoIP test suite. */
12116 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12117 execute( TC_stat_num_msc_connected_1() );
12118 execute( TC_stat_num_msc_connected_2() );
12119 execute( TC_stat_num_msc_connected_3() );
12120 }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020012121 execute( TC_stat_num_bts_connected_1() );
12122 execute( TC_stat_num_bts_connected_2() );
12123 execute( TC_stat_num_bts_connected_3() );
Harald Welte96c94412017-12-09 03:12:45 +010012124 execute( TC_ctrl() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012125 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +020012126 execute( TC_ctrl_location() );
12127 }
Harald Welte898113b2018-01-31 18:32:21 +010012128
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012129 execute( TC_si_default() );
Neels Hofmeyr66aeba42020-07-06 02:21:21 +020012130 execute( TC_si2quater_2_earfcns() );
12131 execute( TC_si2quater_3_earfcns() );
12132 execute( TC_si2quater_4_earfcns() );
12133 execute( TC_si2quater_5_earfcns() );
12134 execute( TC_si2quater_6_earfcns() );
Neels Hofmeyrad132f22020-07-08 02:20:16 +020012135 execute( TC_si2quater_12_earfcns() );
12136 execute( TC_si2quater_23_earfcns() );
12137 execute( TC_si2quater_32_earfcns() );
12138 execute( TC_si2quater_33_earfcns() );
12139 execute( TC_si2quater_42_earfcns() );
12140 execute( TC_si2quater_48_earfcns() );
12141 execute( TC_si2quater_49_earfcns() );
Pau Espin Pedrol85a84432020-07-20 18:45:03 +020012142 execute( TC_si_acc_rotate() );
Alexander Couzens4ad3a352020-09-10 22:29:12 +020012143 execute( TC_si_acc_ramp_rotate() );
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020012144
Harald Welte898113b2018-01-31 18:32:21 +010012145 /* RSL DCHAN Channel ACtivation / Deactivation */
Harald Welteae026692017-12-09 01:03:01 +010012146 execute( TC_chan_act_noreply() );
Harald Welte4003d112017-12-09 22:35:39 +010012147 execute( TC_chan_act_counter() );
Harald Welteae026692017-12-09 01:03:01 +010012148 execute( TC_chan_act_ack_noest() );
Philipp Maier9c60a622020-07-09 15:08:46 +020012149 execute( TC_chan_act_ack_noest_emerg() );
Philipp Maier606f07d2020-08-12 17:21:58 +020012150 execute( TC_chan_rqd_emerg_deny() );
Harald Welteae026692017-12-09 01:03:01 +010012151 execute( TC_chan_act_ack_est_ind_noreply() );
12152 execute( TC_chan_act_ack_est_ind_refused() );
Harald Welte618ef642017-12-14 14:58:20 +010012153 execute( TC_chan_act_nack() );
Harald Welte799c97b2017-12-14 17:50:30 +010012154 execute( TC_chan_exhaustion() );
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +070012155 execute( TC_chan_deact_silence() );
Harald Welte4003d112017-12-09 22:35:39 +010012156 execute( TC_chan_rel_rll_rel_ind() );
12157 execute( TC_chan_rel_conn_fail() );
12158 execute( TC_chan_rel_hard_clear() );
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +020012159 execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
12160 execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
Harald Welte99787102019-02-04 10:41:36 +010012161 execute( TC_chan_rel_hard_clear_csfb() );
Harald Welted8c36cd2017-12-09 23:05:31 +010012162 execute( TC_chan_rel_hard_rlsd() );
Harald Welte550daf92018-06-11 19:22:13 +020012163 execute( TC_chan_rel_hard_rlsd_ms_dead() );
Harald Welte85804d42017-12-10 14:11:58 +010012164 execute( TC_chan_rel_a_reset() );
Pau Espin Pedrolc675b612020-01-09 19:55:40 +010012165 execute( TC_chan_rel_sccp_tiar_timeout() );
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +020012166 execute( TC_chan_rel_rr_cause() );
Harald Welte6f521d82017-12-11 19:52:02 +010012167
Harald Weltecfe2c962017-12-15 12:09:32 +010012168 execute( TC_outbound_connect() );
Harald Welte898113b2018-01-31 18:32:21 +010012169
12170 /* Assignment related */
Harald Welte16a4adf2017-12-14 18:54:01 +010012171 execute( TC_assignment_cic_only() );
Harald Welte235ebf12017-12-15 14:18:16 +010012172 execute( TC_assignment_csd() );
12173 execute( TC_assignment_ctm() );
12174 execute( TC_assignment_sign() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012175 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12176 execute( TC_assignment_aoip_tla_v6() );
12177 }
Harald Welte235ebf12017-12-15 14:18:16 +010012178 execute( TC_assignment_fr_a5_0() );
12179 execute( TC_assignment_fr_a5_1() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012180 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte8f67d1d2018-05-25 20:38:42 +020012181 execute( TC_assignment_fr_a5_1_codec_missing() );
12182 }
Harald Welte235ebf12017-12-15 14:18:16 +010012183 execute( TC_assignment_fr_a5_3() );
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +020012184 execute( TC_assignment_fr_a5_4() );
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +020012185 execute( TC_assignment_fr_a5_4_fail() );
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +020012186 execute( TC_assignment_fr_a5_not_sup() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012187 execute( TC_ciph_mode_a5_0() );
12188 execute( TC_ciph_mode_a5_1() );
Oliver Smith50b98122021-07-09 15:00:28 +020012189 execute( TC_ciph_mode_a5_2_0() );
Oliver Smith1dff88d2021-07-09 08:45:51 +020012190 execute( TC_ciph_mode_a5_2_1() );
Harald Welte3c86ea02018-05-10 22:28:05 +020012191 execute( TC_ciph_mode_a5_3() );
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +020012192 execute( TC_ciph_mode_a5_4() );
Harald Welte16a4adf2017-12-14 18:54:01 +010012193
Harald Welte60aa5762018-03-21 19:33:13 +010012194 execute( TC_assignment_codec_fr() );
Neels Hofmeyr559d5d02021-04-16 16:50:49 +020012195 execute( TC_assignment_codec_fr_by_mode_modify() );
Harald Welte60aa5762018-03-21 19:33:13 +010012196 execute( TC_assignment_codec_hr() );
12197 execute( TC_assignment_codec_efr() );
12198 execute( TC_assignment_codec_amr_f() );
12199 execute( TC_assignment_codec_amr_h() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012200
Neels Hofmeyrf246a922020-05-13 02:27:10 +020012201 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier8a581d22019-03-26 18:32:48 +010012202 execute( TC_assignment_codec_amr_f_S1() );
12203 execute( TC_assignment_codec_amr_h_S1() );
12204 execute( TC_assignment_codec_amr_f_S124() );
12205 execute( TC_assignment_codec_amr_h_S124() );
12206 execute( TC_assignment_codec_amr_f_S0() );
12207 execute( TC_assignment_codec_amr_f_S02() );
12208 execute( TC_assignment_codec_amr_f_S024() );
12209 execute( TC_assignment_codec_amr_f_S0247() );
12210 execute( TC_assignment_codec_amr_h_S0() );
12211 execute( TC_assignment_codec_amr_h_S02() );
12212 execute( TC_assignment_codec_amr_h_S024() );
12213 execute( TC_assignment_codec_amr_h_S0247() );
12214 execute( TC_assignment_codec_amr_f_S01234567() );
12215 execute( TC_assignment_codec_amr_f_S0234567() );
12216 execute( TC_assignment_codec_amr_f_zero() );
12217 execute( TC_assignment_codec_amr_f_unsupp() );
12218 execute( TC_assignment_codec_amr_h_S7() );
Neels Hofmeyr21863562020-11-26 00:34:33 +000012219 execute( TC_assignment_codec_amr_f_start_mode_auto() );
12220 execute( TC_assignment_codec_amr_h_start_mode_auto() );
Neels Hofmeyr3eb94562020-11-26 02:40:26 +000012221 execute( TC_assignment_codec_amr_f_start_mode_4() );
12222 execute( TC_assignment_codec_amr_h_start_mode_4() );
Neels Hofmeyr454d7922020-11-26 02:24:57 +000012223 execute( TC_assignment_codec_amr_startmode_cruft() );
Philipp Maier8a581d22019-03-26 18:32:48 +010012224 }
Harald Welte60aa5762018-03-21 19:33:13 +010012225
Philipp Maierac09bfc2019-01-08 13:41:39 +010012226 execute( TC_assignment_codec_fr_exhausted_req_hr() );
12227 execute( TC_assignment_codec_fr_exhausted_req_fr() );
12228 execute( TC_assignment_codec_fr_exhausted_req_fr_hr() );
12229 execute( TC_assignment_codec_fr_exhausted_req_hr_fr() );
12230 execute( TC_assignment_codec_hr_exhausted_req_fr() );
12231 execute( TC_assignment_codec_hr_exhausted_req_hr() );
12232 execute( TC_assignment_codec_hr_exhausted_req_hr_fr() );
12233 execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
12234 execute( TC_assignment_codec_req_hr_fr() );
12235 execute( TC_assignment_codec_req_fr_hr() );
Pau Espin Pedrol14475352021-07-22 15:48:16 +020012236 execute( TC_assignment_sdcch_exhausted_req_signalling() );
12237 execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
12238 execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
Philipp Maierac09bfc2019-01-08 13:41:39 +010012239
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +020012240 execute( TC_assignment_codec_hr_osmux_on() );
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +020012241 execute( TC_assignment_osmux() );
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020012242 execute( TC_assignment_osmux_cn() );
12243 execute( TC_assignment_osmux_bts() );
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +020012244
Harald Welte898113b2018-01-31 18:32:21 +010012245 /* RLL Establish Indication on inactive DCHAN / SAPI */
Harald Welte5cd20ed2017-12-13 21:03:20 +010012246 execute( TC_rll_est_ind_inact_lchan() );
12247 execute( TC_rll_est_ind_inval_sapi1() );
12248 execute( TC_rll_est_ind_inval_sapi3() );
12249 execute( TC_rll_est_ind_inval_sacch() );
12250
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +070012251 /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
12252 execute( TC_tch_dlci_link_id_sapi() );
12253
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012254 /* SAPI N Reject triggered by RLL establishment failures */
12255 execute( TC_rll_rel_ind_sapi_n_reject() );
12256 execute( TC_rll_err_ind_sapi_n_reject() );
12257 execute( TC_rll_timeout_sapi_n_reject() );
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +070012258 execute( TC_rll_sapi_n_reject_dlci_cc() );
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070012259
Harald Welte898113b2018-01-31 18:32:21 +010012260 /* Paging related tests */
Harald Welte6f521d82017-12-11 19:52:02 +010012261 execute( TC_paging_imsi_nochan() );
12262 execute( TC_paging_tmsi_nochan() );
12263 execute( TC_paging_tmsi_any() );
12264 execute( TC_paging_tmsi_sdcch() );
12265 execute( TC_paging_tmsi_tch_f() );
12266 execute( TC_paging_tmsi_tch_hf() );
12267 execute( TC_paging_imsi_nochan_cgi() );
12268 execute( TC_paging_imsi_nochan_lac_ci() );
12269 execute( TC_paging_imsi_nochan_ci() );
12270 execute( TC_paging_imsi_nochan_lai() );
12271 execute( TC_paging_imsi_nochan_lac() );
12272 execute( TC_paging_imsi_nochan_all() );
Harald Welte751d3eb2018-01-31 15:51:06 +010012273 execute( TC_paging_imsi_nochan_plmn_lac_rnc() );
12274 execute( TC_paging_imsi_nochan_rnc() );
12275 execute( TC_paging_imsi_nochan_lac_rnc() );
12276 execute( TC_paging_imsi_nochan_lacs() );
12277 execute( TC_paging_imsi_nochan_lacs_empty() );
Stefan Sperling049a86e2018-03-20 15:51:00 +010012278 execute( TC_paging_imsi_nochan_cgi_unknown_cid() );
Harald Welte10985002017-12-12 09:29:15 +010012279 execute( TC_paging_imsi_a_reset() );
Harald Weltee65d40e2017-12-13 00:09:06 +010012280 execute( TC_paging_imsi_load() );
Philipp Maier779a7922018-02-16 11:00:37 +010012281 execute( TC_paging_counter() );
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +010012282 execute( TC_paging_resp_unsol() );
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +020012283 execute( TC_paging_500req() );
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +020012284 execute( TC_paging_450req_no_paging_load_ind() );
Pau Espin Pedrol07657ae2023-01-03 12:08:05 +010012285 execute( TC_paging_imsi_nochan_ci_resp_invalid_mi() );
Harald Welte4e9b9cc2017-12-14 18:31:02 +010012286
12287 execute( TC_rsl_drop_counter() );
Stefan Sperling830dc9d2018-02-12 21:08:28 +010012288 execute( TC_rsl_unknown_unit_id() );
12289
12290 execute( TC_oml_unknown_unit_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012291
12292 execute( TC_classmark() );
Harald Welteeddf0e92020-06-21 19:42:15 +020012293 execute( TC_common_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012294 execute( TC_unsol_ass_fail() );
Harald Welteea99a002018-01-31 20:46:43 +010012295 execute( TC_unsol_ass_compl() );
Harald Weltefbf9b5e2018-01-31 20:41:23 +010012296 execute( TC_unsol_ho_fail() );
Harald Weltee3bd6582018-01-31 22:51:25 +010012297 execute( TC_err_82_short_msg() );
Harald Weltee9e02e42018-01-31 23:36:25 +010012298 execute( TC_err_84_unknown_msg() );
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012299
Harald Welte261af4b2018-02-12 21:20:39 +010012300 execute( TC_ho_int() );
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +020012301 execute( TC_ho_int_a5_0() );
12302 execute( TC_ho_int_a5_1() );
12303 execute( TC_ho_int_a5_3() );
12304 execute( TC_ho_int_a5_4() );
Neels Hofmeyr5f144212020-11-03 15:41:58 +000012305 execute( TC_ho_int_radio_link_failure() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012306
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012307 /* TC_ho_out_of_this_bsc is run last, see comment below */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +020012308 execute( TC_ho_out_fail_no_msc_response() );
12309 execute( TC_ho_out_fail_rr_ho_failure() );
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +020012310 execute( TC_ho_out_fail_no_result_after_ho_cmd() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012311
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012312 execute( TC_ho_into_this_bsc() );
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +020012313 execute( TC_ho_into_this_bsc_a5_0() );
12314 execute( TC_ho_into_this_bsc_a5_1() );
12315 execute( TC_ho_into_this_bsc_a5_3() );
12316 execute( TC_ho_into_this_bsc_a5_4() );
Neels Hofmeyr93182e02022-02-17 21:59:07 +010012317 execute( TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() );
12318 execute( TC_ho_into_this_bsc_a5_1_3() );
Neels Hofmeyr907b23b2022-02-17 21:58:47 +010012319 execute( TC_ho_into_this_bsc_a5_mismatch() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012320 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12321 execute( TC_ho_into_this_bsc_tla_v6() );
12322 }
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +020012323 execute( TC_srvcc_eutran_to_geran() );
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +030012324 execute( TC_srvcc_eutran_to_geran_a5_3() );
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +010012325 execute( TC_srvcc_eutran_to_geran_src_sai() );
Pau Espin Pedrol35801c32021-04-19 13:03:20 +020012326 execute( TC_srvcc_eutran_to_geran_ho_out() );
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +020012327 execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
12328 execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012329 execute( TC_ho_in_fail_msc_clears() );
12330 execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
12331 execute( TC_ho_in_fail_no_detect() );
12332 execute( TC_ho_in_fail_no_detect2() );
Neels Hofmeyra23f3b12022-03-02 19:57:12 +010012333 execute( TC_ho_into_this_bsc_sccp_cr_without_bssap() );
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012334
Neels Hofmeyr91401012019-07-11 00:42:35 +020012335 execute( TC_ho_neighbor_config_1() );
12336 execute( TC_ho_neighbor_config_2() );
12337 execute( TC_ho_neighbor_config_3() );
12338 execute( TC_ho_neighbor_config_4() );
12339 execute( TC_ho_neighbor_config_5() );
12340 execute( TC_ho_neighbor_config_6() );
12341 execute( TC_ho_neighbor_config_7() );
12342
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012343 execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() );
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010012344 execute( TC_bssmap_clear_does_not_cause_bssmap_reset() );
Neels Hofmeyrfd445c32018-03-09 15:39:31 +010012345 execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() );
Harald Welte94e0c342018-04-07 11:33:23 +020012346
12347 execute( TC_dyn_pdch_ipa_act_deact() );
12348 execute( TC_dyn_pdch_ipa_act_nack() );
12349 execute( TC_dyn_pdch_osmo_act_deact() );
12350 execute( TC_dyn_pdch_osmo_act_nack() );
Pau Espin Pedrol37a4c152021-11-16 19:02:23 +010012351 execute( TC_dyn_ts_sdcch8_act_deact() );
12352 execute( TC_dyn_ts_sdcch8_all_subslots_used() );
12353 execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
12354 execute( TC_dyn_ts_sdcch8_act_nack() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012355
Stefan Sperling0796a822018-10-05 13:01:39 +020012356 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +020012357 execute( TC_chopped_ipa_payload() );
Stefan Sperling0796a822018-10-05 13:01:39 +020012358
Pau Espin Pedrol8f773632019-11-05 11:46:53 +010012359 /* Power control related */
12360 execute( TC_assignment_verify_ms_power_params_ie() );
Vadim Yanitskiy4b233042021-06-30 00:58:43 +020012361 execute( TC_c0_power_red_mode() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012362
12363 /* MSC pooling */
12364 /* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
12365 * RESET->RESET-ACK is unconditionally negotiated for all configured MSCs, they always all appear as connected
12366 * to osmo-bsc. The MSC pooling tests however require disconnecting selected MSCs, and hence don't work out as
12367 * intended on SCCPlite. So for now, run these only for SCCP/M3UA. */
12368 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12369 execute( TC_mscpool_L3Compl_on_1_msc() );
12370 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
12371 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
12372 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
12373 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
12374 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
12375 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
12376 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
12377 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
12378 execute( TC_mscpool_paging_and_response_imsi() );
12379 execute( TC_mscpool_paging_and_response_tmsi() );
12380 execute( TC_mscpool_no_allow_attach_round_robin() );
12381 execute( TC_mscpool_no_allow_attach_valid_nri() );
12382 }
12383
Harald Welte99f3ca02018-06-14 13:40:29 +020012384 execute( TC_early_conn_fail() );
12385 execute( TC_late_conn_fail() );
Oliver Smithaf03bef2021-08-24 15:34:51 +020012386 execute( TC_stats_conn_fail() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012387
Philipp Maier783681c2020-07-16 16:47:06 +020012388 /* Emergency call handling (deny / allow) */
12389 execute( TC_assignment_emerg_setup_allow() );
12390 execute( TC_assignment_emerg_setup_deny_msc() );
12391 execute( TC_assignment_emerg_setup_deny_bts() );
Philipp Maier82812002020-08-13 18:48:27 +020012392 execute( TC_emerg_premption() );
12393
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +070012394 /* Frequency hopping parameters handling */
12395 execute( TC_fh_params_chan_activ() );
12396 execute( TC_fh_params_imm_ass() );
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070012397 execute( TC_fh_params_assignment_cmd() );
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070012398 execute( TC_fh_params_handover_cmd() );
Vadim Yanitskiyca974032020-09-01 07:20:39 +070012399 execute( TC_fh_params_si4_cbch() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012400
12401 if (mp_enable_lcs_tests) {
12402 execute( TC_lcs_loc_req_for_active_ms() );
12403 execute( TC_lcs_loc_req_for_active_ms_ta_req() );
12404 execute( TC_lcs_loc_req_for_idle_ms() );
12405 execute( TC_lcs_loc_req_no_subscriber() );
12406 execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
12407 execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
12408 execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
12409 execute( TC_cm_service_during_lcs_loc_req() );
12410 execute( TC_ho_during_lcs_loc_req() );
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020012411 execute( TC_emerg_call_and_lcs_loc_req() );
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020012412 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() );
12413 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012414 }
Neels Hofmeyrbf037052020-10-28 22:52:02 +000012415
12416 execute( TC_no_msc() );
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000012417
12418 execute( TC_refuse_chan_act_to_vamos() );
12419 execute( TC_refuse_mode_modif_to_vamos() );
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000012420
12421 execute( TC_reassignment_fr() );
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020012422
12423 execute( TC_cm_reestablishment() );
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020012424
12425 execute( TC_imm_ass_post_chan_ack() );
12426 execute( TC_imm_ass_pre_chan_ack() );
Neels Hofmeyr23158742021-09-07 19:08:07 +020012427 execute( TC_imm_ass_pre_ts_ack() );
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020012428 execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020012429 execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020012430
12431 execute( TC_ctrl_trx_rf_locked() );
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012432
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012433 execute( TC_ratectr_all_available_allocated() );
12434 execute( TC_ratectr_all_available_allocated_dyn() );
12435
Neels Hofmeyrb7581872021-11-07 14:02:49 +010012436 execute( TC_cm_serv_rej() );
12437
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012438 execute( TC_lost_sdcch_during_assignment() );
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012439
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012440 /* Channel allocator */
12441 execute( TC_chan_alloc_algo_ascending() );
12442 execute( TC_chan_alloc_algo_descending() );
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012443 execute( TC_chan_alloc_algo_ass_dynamic() );
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012444
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012445 /* MGW pool */
12446 /* TODO: this conditional canbe dropped once osmo-bsc >1.10.0 is released: */
12447 if (Misc_Helpers.f_osmo_repo_is("nightly")) {
12448 execute( TC_mgwpool_all_used() );
12449 execute( TC_mgwpool_blocked_not_used() );
Pau Espin Pedrol3f41e322022-10-20 19:34:43 +020012450 execute( TC_mgwpool_pin_bts() );
Pau Espin Pedrold2355e82022-10-20 19:34:43 +020012451 }
12452
Oliver Smithc9a5f532022-10-21 11:32:23 +020012453 execute( TC_ho_meas_rep_multi_band() );
12454
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012455 /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
12456 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
12457 execute( TC_ho_out_of_this_bsc() );
Harald Welte28d943e2017-11-25 15:00:50 +010012458}
12459
12460}