blob: d4a7b201639aa4eccab072dc1232573171c10a5b [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;
Harald Welteae026692017-12-09 01:03:01 +010084const float T3101_MAX := 12.0;
Harald Welte28d943e2017-11-25 15:00:50 +010085
Harald Welte799c97b2017-12-14 17:50:30 +010086/* make sure to sync this with the osmo-bts.cfg you're using */
Philipp Maiercb6cc482018-03-26 13:08:00 +020087const integer NUM_TCHH_PER_BTS := 2;
88const integer NUM_TCHF_PER_BTS := 4;
Neels Hofmeyr74083c22020-07-29 00:43:01 +020089const integer NUM_SDCCH_PER_BTS := 3;
Harald Welte799c97b2017-12-14 17:50:30 +010090
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060091friend type record BtsTrxIdx {
92 uint8_t bts,
93 uint8_t trx
94}
95
96private type record BtsParams {
97 integer trx_num,
98 integer tsc
99}
100
Neels Hofmeyrbf720202021-10-02 12:58:24 +0200101/* Default Training Sequence Code expected for bts[i]:
102 * BTS 0 has BSIC 10 (and no explicit timeslot training_sequence_code config), so expecting TSC = (BSIC & 7) = 2.
103 * BTS 1 has BSIC 11, TSC = (BSIC & 7) = 3.
104 * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
105 * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
106 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600107private const BtsParams c_BtsParams[NUM_BTS_CFG] := {
108 /* BTS0 */ { trx_num := 1, tsc := 2 },
109 /* BTS1 */ { trx_num := 1, tsc := 3 },
Vadim Yanitskiy7a3d2932022-05-29 20:37:46 +0600110 /* BTS2 */ { trx_num := 4, tsc := 4 },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600111 /* BTS3 */ { trx_num := 1, tsc := 4 }
Neels Hofmeyrbf720202021-10-02 12:58:24 +0200112}
Harald Welte4003d112017-12-09 22:35:39 +0100113
Pau Espin Pedrolf7634dc2022-09-02 17:56:00 +0200114private const RSL_IE_Body mr_conf_amr_5_90 :=
115 valueof(RSL_IE_Body:{multirate_cfg := ts_RSL_MultirateCfg(true, 0, '00000100'B /* 5,90k */)});
116
Harald Welte21b46bd2017-12-17 19:46:32 +0100117/* per-BTS state which we keep */
Harald Welte96c94412017-12-09 03:12:45 +0100118type record BTS_State {
Harald Welte21b46bd2017-12-17 19:46:32 +0100119 /* component reference to the IPA_Client component used for RSL */
Harald Weltea5d2ab22017-12-09 14:21:42 +0100120 IPA_Client rsl
Harald Welte96c94412017-12-09 03:12:45 +0100121}
122
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200123/* Default list of counters for an 'msc' entity. */
124const CounterNameVals counternames_msc_mscpool := {
125 { "mscpool:subscr:new", 0 },
126 { "mscpool:subscr:known", 0 },
127 { "mscpool:subscr:reattach", 0 },
128 { "mscpool:subscr:attach_lost", 0 },
129 { "mscpool:subscr:paged", 0 }
130};
131
Neels Hofmeyrbf037052020-10-28 22:52:02 +0000132/* List of global mscpool counters, not related to a specific 'msc' entity. */
133const CounterNameVals counternames_bsc_mscpool := {
134 { "mscpool:subscr:no_msc", 0 }
135};
136
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000137/* Default list of counters for 'bsc' and 'bts' entities. */
138const CounterNameVals counternames_bsc_bts_handover := {
139 { "assignment:attempted", 0 },
140 { "assignment:completed", 0 },
141 { "assignment:stopped", 0 },
142 { "assignment:no_channel", 0 },
143 { "assignment:timeout", 0 },
144 { "assignment:failed", 0 },
145 { "assignment:error", 0 },
146
147 { "handover:attempted", 0 },
148 { "handover:completed", 0 },
149 { "handover:stopped", 0 },
150 { "handover:no_channel", 0 },
151 { "handover:timeout", 0 },
152 { "handover:failed", 0 },
153 { "handover:error", 0 },
154
155 { "intra_cell_ho:attempted", 0 },
156 { "intra_cell_ho:completed", 0 },
157 { "intra_cell_ho:stopped", 0 },
158 { "intra_cell_ho:no_channel", 0 },
159 { "intra_cell_ho:timeout", 0 },
160 { "intra_cell_ho:failed", 0 },
161 { "intra_cell_ho:error", 0 },
162
163 { "intra_bsc_ho:attempted", 0 },
164 { "intra_bsc_ho:completed", 0 },
165 { "intra_bsc_ho:stopped", 0 },
166 { "intra_bsc_ho:no_channel", 0 },
167 { "intra_bsc_ho:timeout", 0 },
168 { "intra_bsc_ho:failed", 0 },
169 { "intra_bsc_ho:error", 0 },
170
171 { "interbsc_ho_out:attempted", 0 },
172 { "interbsc_ho_out:completed", 0 },
173 { "interbsc_ho_out:stopped", 0 },
174 { "interbsc_ho_out:timeout", 0 },
175 { "interbsc_ho_out:failed", 0 },
176 { "interbsc_ho_out:error", 0 },
177
178 { "interbsc_ho_in:attempted", 0 },
179 { "interbsc_ho_in:completed", 0 },
180 { "interbsc_ho_in:stopped", 0 },
181 { "interbsc_ho_in:no_channel", 0 },
182 { "interbsc_ho_in:timeout", 0 },
183 { "interbsc_ho_in:failed", 0 },
184 { "interbsc_ho_in:error", 0 }
185};
186
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100187const CounterNameVals counternames_bts_handover := {
188 { "incoming_intra_bsc_ho:attempted", 0 },
189 { "incoming_intra_bsc_ho:completed", 0 },
190 { "incoming_intra_bsc_ho:stopped", 0 },
191 { "incoming_intra_bsc_ho:no_channel", 0 },
192 { "incoming_intra_bsc_ho:timeout", 0 },
193 { "incoming_intra_bsc_ho:failed", 0 },
194 { "incoming_intra_bsc_ho:error", 0 }
195};
196
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200197/* Set of all System Information received during one RSL port's startup.
198 * Note that some System Information may be sent on RSL, but lacking actual SI data, to indicate that the BTS should not
199 * broadcast that SI type. That will be reflected as 'omit' here.
200 */
201type record SystemInformationConfig {
202 SystemInformationType1 si1 optional,
203 SystemInformationType2 si2 optional,
204 SystemInformationType2bis si2bis optional,
205 SystemInformationType2ter si2ter optional,
Neels Hofmeyrad132f22020-07-08 02:20:16 +0200206 SI2quaterRestOctetsList si2quater optional,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200207 SystemInformationType3 si3 optional,
208 SystemInformationType4 si4 optional,
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100209 SystemInformationType13 si13 optional,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200210 SystemInformationType5 si5 optional,
211 SystemInformationType5bis si5bis optional,
212 SystemInformationType5ter si5ter optional,
213 SystemInformationType6 si6 optional
214};
215
216const SystemInformationConfig SystemInformationConfig_omit := {
217 si1 := omit,
218 si2 := omit,
219 si2bis := omit,
220 si2ter := omit,
221 si2quater := omit,
222 si3 := omit,
223 si4 := omit,
224 si13 := omit,
225 si5 := omit,
226 si5bis := omit,
227 si5ter := omit,
228 si6 := omit
229};
230
231/* tr_EUTRAN_CellDesc with defaults used in BSC_Tests.ttcn */
232template EUTRAN_CellDesc tr_EUTRAN_CellDesc_default(template (present) uint16_t e_arfcn := ?,
233 template uint3_t meas_bw := 3)
234:= tr_EUTRAN_CellDesc(e_arfcn := e_arfcn,
235 meas_bw_presence := '1'B,
236 meas_bw := meas_bw);
237
238/* tr_EUTRAN_NeighbourCells with defaults used in BSC_Tests.ttcn */
Harald Welte65e419a2020-08-21 12:38:33 +0200239template EUTRAN_NeighbourCells tr_EUTRAN_NeighbourCells_default(template (present) EUTRAN_CellDescs cell_desc_list := { tr_EUTRAN_CellDesc_default },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200240 template uint3_t prio := 3,
241 template (present) uint5_t thresh_high := 20,
242 template uint5_t thresh_low := 10,
243 template uint5_t qrxlevmin := 22)
244:= tr_EUTRAN_NeighbourCells(
245 cell_desc_list := cell_desc_list,
246 prio_presence := '1'B,
247 prio := prio,
248 thresh_high := thresh_high,
249 thresh_low_presence := '1'B,
250 thresh_low := thresh_low,
251 qrxlevmin_presence := '1'B,
252 qrxlevmin := qrxlevmin);
253
254template SystemInformationConfig SystemInformationConfig_default := {
255 si1 := {
256 cell_chan_desc := '8FB38000000000000000000000000000'O,
257 rach_control := {
258 max_retrans := RACH_MAX_RETRANS_7,
259 tx_integer := '1001'B,
260 cell_barr_access := false,
261 re_not_allowed := true,
262 acc := '0000010000000000'B
263 },
264 rest_octets := ?
265 },
266 si2 := {
267 bcch_freq_list := '00000000000000000000000000000000'O,
268 ncc_permitted := '11111111'B,
269 rach_control := {
270 max_retrans := RACH_MAX_RETRANS_7,
271 tx_integer := '1001'B,
272 cell_barr_access := false,
273 re_not_allowed := true,
274 acc := '0000010000000000'B
275 }
276 },
277 si2bis := omit,
278 si2ter := {
279 extd_bcch_freq_list := '8E320000000000000000000000000800'O,
280 rest_octets := ?
281 },
282 si2quater := {
283 tr_SI2quaterRestOctets_EUTRAN( repeated_neigh_cells := { tr_EUTRAN_NeighbourCells_default } )
284 },
285 si3 := {
286 cell_id := 0,
287 lai := {
288 mcc_mnc := '001F01'H,
289 lac := 1
290 },
291 ctrl_chan_desc := {
292 msc_r99 := true,
293 att := true,
294 bs_ag_blks_res := 1,
295 ccch_conf := CCHAN_DESC_1CCCH_COMBINED,
296 si22ind := false,
297 cbq3 := CBQ3_IU_MODE_NOT_SUPPORTED,
298 spare := '00'B,
299 bs_pa_mfrms := 3,
300 t3212 := 30
301 },
302 cell_options := {
303 dn_ind := false,
304 pwrc := false,
305 dtx := MS_SHALL_USE_UL_DTX,
306 radio_link_tout_div4 := 7
307 },
308 cell_sel_par := {
309 cell_resel_hyst_2dB := 2,
310 ms_txpwr_max_cch := 7,
311 acs := '0'B,
312 neci := true,
313 rxlev_access_min := 0
314 },
315 rach_control := {
316 max_retrans := RACH_MAX_RETRANS_7,
317 tx_integer := '1001'B,
318 cell_barr_access := false,
319 re_not_allowed := true,
320 acc := '0000010000000000'B
321 },
322 rest_octets := {
323 sel_params := {
324 presence := '0'B,
325 params := omit
326 },
327 pwr_offset := {
328 presence := '0'B,
329 offset := omit
330 },
331 si_2ter_ind := '1'B,
332 early_cm_ind := '0'B,
333 sched_where := {
334 presence := '0'B,
335 where := omit
336 },
337 gprs_ind := {
338 presence := '1'B,
339 ind := {
340 ra_colour := 0,
341 si13_pos := '0'B
342 }
343 },
344 umts_early_cm_ind := '1'B,
345 si2_quater_ind := {
346 presence := '1'B,
347 ind := '0'B
348 },
349 iu_mode_ind := omit,
350 si21_ind := {
351 presence := '0'B,
352 pos := omit
353 }
354 }
355 },
356 si4 := {
357 lai := {
358 mcc_mnc := '001F01'H,
359 lac := 1
360 },
361 cell_sel_par := {
362 cell_resel_hyst_2dB := 2,
363 ms_txpwr_max_cch := 7,
364 acs := '0'B,
365 neci := true,
366 rxlev_access_min := 0
367 },
368 rach_control := {
369 max_retrans := RACH_MAX_RETRANS_7,
370 tx_integer := '1001'B,
371 cell_barr_access := false,
372 re_not_allowed := true,
373 acc := '0000010000000000'B
374 },
Neels Hofmeyr74083c22020-07-29 00:43:01 +0200375 cbch_chan_desc := {
376 iei := '64'O,
377 v := {
378 chan_nr := {
379 u := {
380 sdcch4 := {
381 tag := '001'B,
382 sub_chan := 2
383 }
384 },
385 tn := 0
386 },
387 tsc := 2,
388 h := false,
389 arfcn := 871,
390 maio_hsn := omit
391 }
392 },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200393 cbch_mobile_alloc := omit,
394 rest_octets := {
395 sel_params := {
396 presence := '0'B,
397 params := omit
398 },
399 pwr_offset := {
400 presence := '0'B,
401 offset := omit
402 },
403 gprs_ind := {
404 presence := '1'B,
405 ind := {
406 ra_colour := 0,
407 si13_pos := '0'B
408 }
409 },
410 s_presence := '0'B,
411 s := omit
412 }
413 },
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100414 si13 := {
415 rest_octets := {
416 presence := '1'B,
417 bcch_change_mark := ?,
418 si_change_field := '0000'B,
419 presence2 := '0'B,
420 si13_change_mark := omit,
421 gprs_ma := omit,
422 zero := '0'B, /* PBCCH not present in cell */
423 rac := 0,
424 spgc_ccch_sup := '0'B,
425 priority_access_thr := '110'B,
426 network_control_order := '00'B,
427 gprs_cell_opts := {
428 nmo := '01'B,
429 t3168 := '011'B,
430 t3192 := '010'B,
431 drx_timer_max := '011'B,
432 access_burst_type := '0'B,
433 control_ack_type := '1'B,
434 bs_cv_max := 15,
435 pan_presence := '1'B,
436 pan_dec := 1,
437 pan_inc := 1,
438 pan_max := '111'B,
439 ext_info_presence := ?,
440 ext_info_length := *,
441 ext_info := *
442 },
443 gprs_pwr_ctrl_params := {
444 alpha := 0,
445 t_avg_w := '10000'B,
446 t_avg_t := '10000'B,
447 pc_meas_chan := '0'B,
448 n_avg_i := '1000'B
449 }
450 }
451 },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200452 si5 := {
453 bcch_freq_list := '10000000000000000000000000000000'O
454 },
455 si5bis := omit,
456 si5ter := {
457 extd_bcch_freq_list := '9E050020000000000000000000000000'O
458 },
459 si6 := {
460 cell_id := 0,
461 lai := {
462 mcc_mnc := '001F01'H,
463 lac := 1
464 },
465 cell_options := {
466 dtx_ext := '1'B,
467 pwrc := false,
468 dtx := '01'B,
469 radio_link_timeout := '0111'B
470 },
471 ncc_permitted := '11111111'B,
Vadim Yanitskiy348b07c2022-03-10 17:11:22 +0300472 rest_octets := {
473 pch_nch_info := ?,
474 vbs_vgcs_options := ?,
475 dtm_support := '0'B,
476 rac := omit,
477 max_lapdm := omit,
478 band_ind := '0'B /* C0 ARFCN indicates 1800 band */
479 }
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200480 }
481 };
482
483
484/* List of all the System Information received on all RSL ports */
485type record of SystemInformationConfig SystemInformationConfig_list;
486
487function f_sysinfo_dec_raw(inout SystemInformationConfig si, RSL_Message rsl)
488{
489 var RSL_IE_Body sysinfo_type_ie;
490 var RSL_IE_SysinfoType si_type;
491 var octetstring data;
492
493 if (f_rsl_find_ie(rsl, RSL_IE_SYSINFO_TYPE, sysinfo_type_ie) == false) {
494 setverdict(fail, "Cannot find RSL_IE_SYSINFO_TYPE");
495 mtc.stop;
496 }
497 si_type := sysinfo_type_ie.sysinfo_type;
498
499 if (rsl.msg_type == RSL_MT_BCCH_INFO) {
500 var RSL_IE_Body bcch_ie;
501 if (f_rsl_find_ie(rsl, RSL_IE_FULL_BCCH_INFO, bcch_ie)) {
502 data := bcch_ie.other.payload;
503 }
504 } else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
505 var RSL_IE_Body l3_ie;
506 if (f_rsl_find_ie(rsl, RSL_IE_L3_INFO, l3_ie)) {
507 data := l3_ie.l3_info.payload;
508 }
509 } else {
510 setverdict(fail, "Don't understand this System Information message");
511 mtc.stop;
512 }
513
514 var boolean handled := false;
515
516 if (rsl.msg_type == RSL_MT_BCCH_INFO) {
517 handled := true;
518
519 if (si_type == RSL_SYSTEM_INFO_1) {
520 if (not isbound(data)) {
521 si.si1 := omit;
522 } else {
523 si.si1 := dec_SystemInformation(data).payload.si1;
524 }
525 } else if (si_type == RSL_SYSTEM_INFO_2) {
526 if (not isbound(data)) {
527 si.si2 := omit;
528 } else {
529 si.si2 := dec_SystemInformation(data).payload.si2;
530 }
531 } else if (si_type == RSL_SYSTEM_INFO_2bis) {
532 if (not isbound(data)) {
533 si.si2bis := omit;
534 } else {
535 si.si2bis := dec_SystemInformation(data).payload.si2bis;
536 }
537 } else if (si_type == RSL_SYSTEM_INFO_2ter) {
538 if (not isbound(data)) {
539 si.si2ter := omit;
540 } else {
541 si.si2ter := dec_SystemInformation(data).payload.si2ter;
542 }
543 } else if (si_type == RSL_SYSTEM_INFO_2quater) {
544 if (not isbound(data)) {
545 si.si2quater := {};
546 } else {
547 var SystemInformationType2quater decoded := dec_SystemInformation(data).payload.si2quater;
548 /* this is a *record* of SI2quaterRestOctets! (multiplexed) */
549 si.si2quater[decoded.rest_octets.si2quater_index] := decoded.rest_octets;
550 }
551 } else if (si_type == RSL_SYSTEM_INFO_3) {
552 if (not isbound(data)) {
553 si.si3 := omit;
554 } else {
555 si.si3 := dec_SystemInformation(data).payload.si3;
556 }
557 } else if (si_type == RSL_SYSTEM_INFO_4) {
558 if (not isbound(data)) {
559 si.si4 := omit;
560 } else {
561 si.si4 := dec_SystemInformation(data).payload.si4;
562 }
563 } else if (si_type == RSL_SYSTEM_INFO_13) {
564 if (not isbound(data)) {
565 si.si13 := omit;
566 } else {
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100567 si.si13 := dec_SystemInformation(data).payload.si13;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200568 }
569 } else {
570 handled := false;
571 }
572 } else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
573 handled := true;
574
575 if (si_type == RSL_SYSTEM_INFO_5) {
576 if (not isbound(data)) {
577 si.si5 := omit;
578 } else {
579 si.si5 := dec_SystemInformation(data).payload.si5;
580 }
581 } else if (si_type == RSL_SYSTEM_INFO_5bis) {
582 if (not isbound(data)) {
583 si.si5bis := omit;
584 } else {
585 si.si5bis := dec_SystemInformation(data).payload.si5bis;
586 }
587 } else if (si_type == RSL_SYSTEM_INFO_5ter) {
588 if (not isbound(data)) {
589 si.si5ter := omit;
590 } else {
591 si.si5ter := dec_SystemInformation(data).payload.si5ter;
592 }
593 } else if (si_type == RSL_SYSTEM_INFO_6) {
594 if (not isbound(data)) {
595 si.si6 := omit;
596 } else {
597 si.si6 := dec_SystemInformation(data).payload.si6;
598 }
599 } else {
600 handled := false;
601 }
602 }
603
604 if (not handled) {
605 setverdict(fail, "Unexpected SI type in ", rsl.msg_type, " message: ", si_type);
606 }
607}
608
Harald Weltea4ca4462018-02-09 00:17:14 +0100609type component test_CT extends CTRL_Adapter_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600610 /* Array of per-BTS/TRX state */
611 var BTS_State bts[NUM_BTS][NUM_TRX];
Harald Welte89ab1912018-02-23 18:56:29 +0100612 /* RSL common Channel Port (for RSL_Emulation) */
613 port RSL_CCHAN_PT RSL_CCHAN[NUM_BTS];
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600614 /* array of per-BTS/TRX RSL test ports */
615 port IPA_RSL_PT IPA_RSL[NUM_BTS][NUM_TRX];
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100616 port IPA_CODEC_PT IPA; /* Required for compilation of TC_rsl_unknown_unit_id() */
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +0200617 /* CTRL muxed over IPA in SCCPlite conn BSC<->MSC (or BSC-NAT) */
618 port IPA_CTRL_PT SCCPLITE_IPA_CTRL;
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200619 /* Configure/manage IPA_Emulation per-BTS/TRX port: */
620 port IPA_CFG_PT IPA_CFG_PORT[NUM_BTS][NUM_TRX];
Harald Weltea5d2ab22017-12-09 14:21:42 +0100621
Daniel Willmann191e0d92018-01-17 12:44:35 +0100622 var MGCP_Emulation_CT vc_MGCP;
Harald Weltebc03c762018-02-12 18:09:38 +0100623 port TELNETasp_PT BSCVTY;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100624
Daniel Willmannebdecc02020-08-12 15:30:17 +0200625 /* StatsD */
626 var StatsD_Checker_CT vc_STATSD;
627
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200628 var RAN_Adapter g_bssap[NUM_MSC];
Harald Welte47cd0e32020-08-21 12:39:11 +0200629 var BSSAP_LE_Adapter g_bssap_le;
Harald Weltea4ca4462018-02-09 00:17:14 +0100630 /* for old legacy-tests only */
631 port BSSAP_CODEC_PT BSSAP;
Harald Welte47cd0e32020-08-21 12:39:11 +0200632 port BSSAP_LE_CODEC_PT BSSAP_LE;
Harald Weltea4ca4462018-02-09 00:17:14 +0100633
Harald Welte21b46bd2017-12-17 19:46:32 +0100634 /* are we initialized yet */
Harald Welte28d943e2017-11-25 15:00:50 +0100635 var boolean g_initialized := false;
Harald Welte21b46bd2017-12-17 19:46:32 +0100636
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200637 /* Osmux is enabled through VTY */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200638 var boolean g_osmux_enabled_cn := false;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +0200639 var boolean g_osmux_enabled_bts := false;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200640
Pau Espin Pedrolc675b612020-01-09 19:55:40 +0100641 /*Configure T(tias) over VTY, seconds */
642 var integer g_bsc_sccp_timer_ias := 7 * 60;
643 /*Configure T(tiar) over VTY, seconds */
644 var integer g_bsc_sccp_timer_iar := 15 * 60;
645
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +0200646 /* global test case guard timer (actual timeout value is set in f_init()) */
Harald Welteae026692017-12-09 01:03:01 +0100647 timer T_guard := 30.0;
648
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200649 var CounterNameValsList g_ctr_msc;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000650 var CounterNameValsList g_ctr_bsc;
651 var CounterNameValsList g_ctr_bts;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200652
653 /* System Information bytes as received during RSL startup, for each RSL[idx]. */
654 var SystemInformationConfig_list g_system_information := {};
Harald Welte28d943e2017-11-25 15:00:50 +0100655}
656
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200657type record of charstring phys_chan_configs;
Harald Welte28d943e2017-11-25 15:00:50 +0100658modulepar {
Harald Welte21b46bd2017-12-17 19:46:32 +0100659 /* IP address at which the BSC can be reached */
Harald Welte696ddb62017-12-08 14:01:43 +0100660 charstring mp_bsc_ip := "127.0.0.1";
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100661 /* port number to which to establish the IPA OML connections */
662 integer mp_bsc_oml_port := 3002;
Harald Welte21b46bd2017-12-17 19:46:32 +0100663 /* port number to which to establish the IPA RSL connections */
Harald Welte696ddb62017-12-08 14:01:43 +0100664 integer mp_bsc_rsl_port := 3003;
Harald Welte21b46bd2017-12-17 19:46:32 +0100665 /* port number to which to establish the IPA CTRL connection */
Harald Welte96c94412017-12-09 03:12:45 +0100666 integer mp_bsc_ctrl_port := 4249;
Daniel Willmannebdecc02020-08-12 15:30:17 +0200667 /* port number to which to listen for STATSD metrics */
668 integer mp_bsc_statsd_port := 8125;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100669 /* IP address at which the test binds */
670 charstring mp_test_ip := "127.0.0.1";
Harald Weltea4ca4462018-02-09 00:17:14 +0100671
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200672 RAN_Configurations mp_bssap_cfg := {
673 {
674 transport := BSSAP_TRANSPORT_AoIP,
675 sccp_service_type := "mtp3_itu",
676 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
677 own_pc := 185, /* 0.23.1 first MSC emulation */
678 own_ssn := 254,
679 peer_pc := 187, /* 0.23.3 osmo-bsc */
680 peer_ssn := 254,
681 sio := '83'O,
Harald Weltecb0cc432020-06-21 19:42:31 +0200682 rctx := 1
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200683 },
684 {
685 transport := BSSAP_TRANSPORT_AoIP,
686 sccp_service_type := "mtp3_itu",
687 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
688 own_pc := 2, /* 0.0.2 second MSC emulation */
689 own_ssn := 254,
690 peer_pc := 187, /* 0.23.3 osmo-bsc */
691 peer_ssn := 254,
692 sio := '83'O,
693 rctx := 2
694 },
695 {
696 transport := BSSAP_TRANSPORT_AoIP,
697 sccp_service_type := "mtp3_itu",
698 sctp_addr := { 23907, "127.0.0.1", 2905, "127.0.0.1" },
699 own_pc := 3, /* 0.0.3 third 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 := 3
705 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100706 };
Pau Espin Pedrol58cf6822019-05-28 18:11:33 +0200707
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200708 /* Must match per BTS config in osmo-bsc.cfg */
709 phys_chan_configs phys_chan_config := {
710 "CCCH+SDCCH4+CBCH",
711 "TCH/F",
712 "TCH/F",
713 "TCH/F",
714 "TCH/F",
Vadim Yanitskiy343c9eb2021-07-16 18:36:01 +0600715 "TCH/H",
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200716 "PDCH",
717 "PDCH"
718 };
719
Harald Welte47cd0e32020-08-21 12:39:11 +0200720 BSSAP_LE_Configuration mp_bssap_le_cfg := {
721 sccp_service_type := "mtp3_itu",
722 sctp_addr := { 23908, "127.0.0.1", 2905, "127.0.0.1" },
Neels Hofmeyrac086c12020-09-18 23:46:42 +0200723 own_pc := 190, /* 0.23.6 SMLC emulation */
Harald Welte47cd0e32020-08-21 12:39:11 +0200724 own_ssn := 252, /* SMLC side SSN */
725 peer_pc := 187, /* 0.23.3 osmo-bsc */
726 peer_ssn := 250, /* BSC side SSN */
727 sio := '83'O,
728 rctx := 6
729 };
Neels Hofmeyrcfe44062020-10-15 02:28:08 +0200730 boolean mp_enable_lcs_tests := true;
Harald Welte47cd0e32020-08-21 12:39:11 +0200731
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100732 /* Value set in osmo-bsc.cfg "ms max power" */
733 uint8_t mp_exp_ms_power_level := 7;
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600734
735 /* Whether to check for memory leaks */
736 boolean mp_verify_talloc_count := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100737}
738
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200739friend function f_gen_test_hdlr_pars(integer bssap_idx := 0) return TestHdlrParams {
Philipp Maier48604732018-10-09 15:00:37 +0200740
741 var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200742 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier48604732018-10-09 15:00:37 +0200743 pars.aoip := true;
744 } else {
745 pars.aoip := false;
746 }
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100747 pars.exp_ms_power_level := mp_exp_ms_power_level;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200748 pars.mscpool.bssap_idx := bssap_idx;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600749 pars.expect_tsc := c_BtsParams[0].tsc;
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300750 pars.imsi := f_rnd_imsi('00101'H);
751
752 log(testcasename(), ": using IMSI ", pars.imsi);
Neels Hofmeyrb5b7a6e2021-06-04 19:03:45 +0200753
Philipp Maier48604732018-10-09 15:00:37 +0200754 return pars;
755}
756
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200757/* Convenience functions for rate counters using g_ctr_msc. */
758
759private function f_ctrs_msc_init(integer mscs_count := NUM_MSC, CounterNameVals counternames := counternames_msc_mscpool) runs on test_CT {
760 g_ctr_msc := f_counter_name_vals_get_n(IPA_CTRL, "msc", mscs_count, counternames);
761 log("initial msc rate counters: ", g_ctr_msc);
762}
763
764private function f_ctrs_msc_add(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr9656e922020-06-30 01:27:01 +0200765 f_counter_name_vals_list_add(g_ctr_msc, msc_nr, countername, val);
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200766}
767
768/* f_ctrs_msc_init();
769 * f_do_thing(on_msc := 0);
770 * f_do_thing(on_msc := 0);
771 * f_do_other(on_msc := 1);
772 * f_ctrs_msc_add(0, "thing", 2);
773 * f_ctrs_msc_add(1, "other");
774 * f_ctrs_msc_verify();
775 */
776private function f_ctrs_msc_verify() runs on test_CT {
777 log("verifying msc rate counters: ", g_ctr_msc);
778 f_counter_name_vals_expect_n(IPA_CTRL, "msc", g_ctr_msc);
779}
780
781/* convenience: f_ctrs_msc_add() and f_ctrs_msc_verify() in one call.
782 * f_ctrs_msc_init();
783 * f_do_thing(on_msc := 0);
784 * f_do_thing(on_msc := 0);
785 * f_do_thing(on_msc := 0);
786 * f_ctrs_msc_expect(0, "thing", 3);
787 */
788private function f_ctrs_msc_expect(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
789 f_ctrs_msc_add(msc_nr, countername, val);
790 f_ctrs_msc_verify();
791}
792
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000793/* Convenience functions for rate counters using g_ctr_bts, always also including g_ctr_bsc. */
794
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100795private 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 +0000796 g_ctr_bts := f_counter_name_vals_get_n(IPA_CTRL, "bts", bts_count, counternames);
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100797 log("initial bts rate counters: ", g_ctr_bts);
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100798}
799
800function f_ctrs_bsc_and_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
801 f_ctrs_bts_init(bts_count, counternames);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000802 f_ctrs_bsc_init(counternames);
803}
804
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100805private function f_ctrs_bsc_and_bts_handover_init(integer bts_count := NUM_BTS) runs on test_CT {
806 var CounterNameVals bts_names := counternames_bsc_bts_handover & counternames_bts_handover;
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100807 f_ctrs_bts_init(bts_count, bts_names);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100808 f_ctrs_bsc_init(counternames_bsc_bts_handover);
809}
810
811private function f_ctrs_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000812 f_counter_name_vals_list_add(g_ctr_bts, bts_nr, countername, val);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100813}
814
815private function f_ctrs_bsc_and_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
816 f_ctrs_bts_add(bts_nr, countername, val);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000817 f_ctrs_bsc_add(countername, val);
818}
819
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100820function f_ctrs_bts_verify() runs on test_CT {
821 f_counter_name_vals_expect_n(IPA_CTRL, "bts", g_ctr_bts);
822}
823
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000824/* f_ctrs_bsc_and_bts_init();
825 * f_do_thing(on_bts := 0);
826 * f_do_thing(on_bts := 0);
827 * f_do_other(on_bts := 1);
828 * f_ctrs_bsc_and_bts_add(0, "thing", 2);
829 * f_ctrs_bsc_and_bts_add(1, "other");
830 * f_ctrs_bsc_and_bts_verify();
831 */
832private function f_ctrs_bsc_and_bts_verify() runs on test_CT {
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100833 f_ctrs_bts_verify();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000834 f_ctrs_bsc_verify();
835}
836
837/* convenience: f_ctrs_bsc_and_bts_add() and f_ctrs_bsc_and_bts_verify() in one call.
838 * f_ctrs_bsc_and_bts_init();
839 * f_do_thing(on_bts := 0);
840 * f_do_thing(on_bts := 0);
841 * f_do_thing(on_bts := 0);
842 * f_ctrs_bsc_and_bts_expect(0, "thing", 3);
843 */
844private function f_ctrs_bsc_and_bts_expect(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
845 f_ctrs_bsc_and_bts_add(bts_nr, countername, val);
846 f_ctrs_bsc_and_bts_verify();
847}
848
849
850/* Convenience functions for rate counters using g_ctr_bsc. */
851
852private function f_ctrs_bsc_init(CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
853 g_ctr_bsc := f_counter_name_vals_get_n(IPA_CTRL, "bsc", 1, counternames);
854 log("initial bsc rate counters: ", g_ctr_bsc);
855}
856
857private function f_ctrs_bsc_add(charstring countername, integer val := 1) runs on test_CT {
858 f_counter_name_vals_list_add(g_ctr_bsc, 0, countername, val);
859}
860
861/* f_ctrs_bsc_init();
862 * f_do_thing();
863 * f_do_thing();
864 * f_do_other();
865 * f_ctrs_bsc_add("thing", 2);
866 * f_ctrs_bsc_add("other");
867 * f_ctrs_bsc_verify();
868 */
869private function f_ctrs_bsc_verify() runs on test_CT {
870 f_counter_name_vals_expect_n(IPA_CTRL, "bsc", g_ctr_bsc);
871}
872
873/* convenience: f_ctrs_bsc_add() and f_ctrs_bsc_verify() in one call.
874 * f_ctrs_bsc_init();
875 * f_do_thing();
876 * f_ctrs_bsc_expect("thing", 1);
877 */
878private function f_ctrs_bsc_expect(charstring countername, integer val := 1) runs on test_CT {
879 f_ctrs_bsc_add(countername, val);
880 f_ctrs_bsc_verify();
881}
882
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200883
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200884friend function f_shutdown_helper() runs on test_CT {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100885 /* Run the subscr and conn leak test only when the VTY is initialized */
Vadim Yanitskiy6e068012022-02-05 21:35:43 +0600886 if (BSCVTY.checkstate("Mapped") and mp_verify_talloc_count) {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100887 f_verify_talloc_count(BSCVTY, {"struct bsc_subscr", "struct gsm_subscriber_connection"});
888 }
889
Daniel Willmann637ef6c2018-07-25 10:49:09 +0200890 all component.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100891 setverdict(pass);
Daniel Willmannafce8662018-07-06 23:11:32 +0200892 mtc.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100893}
894
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200895private function f_legacy_bssap_reset(integer bssap_idx := 0) runs on test_CT {
Harald Weltea4ca4462018-02-09 00:17:14 +0100896 var BSSAP_N_UNITDATA_ind ud_ind;
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200897 var boolean reset_received := false;
Harald Weltea4ca4462018-02-09 00:17:14 +0100898 timer T := 5.0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200899 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 +0200900 ts_BSSMAP_Reset(0, g_osmux_enabled_cn)));
Harald Weltea4ca4462018-02-09 00:17:14 +0100901 T.start;
902 alt {
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200903 [] 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 +0200904 tr_BSSMAP_ResetAck(g_osmux_enabled_cn))) {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200905 log("BSSMAP: Received RESET-ACK in response to RESET, we're ready to go!");
Harald Weltea4ca4462018-02-09 00:17:14 +0100906 }
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200907 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200908 log("BSSMAP: Respoding to inbound RESET with RESET-ACK");
Harald Weltea4ca4462018-02-09 00:17:14 +0100909 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +0200910 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200911 reset_received := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100912 repeat;
913 }
914 [] BSSAP.receive { repeat; }
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200915 [] T.timeout {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200916 log("BSSMAP: Timeout waiting for RESET-ACK after sending RESET");
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200917 /* If we received a RESET after ours was sent, it
918 may be a race condition where the other peer beacame
919 available after we sent it, but we are in a desired
920 state anyway, so go forward. */
921 if (not reset_received) {
922 setverdict(fail);
923 }
924 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100925 }
Harald Welte28d943e2017-11-25 15:00:50 +0100926}
927
Harald Welteae026692017-12-09 01:03:01 +0100928type record IPA_Client {
Harald Welte21b46bd2017-12-17 19:46:32 +0100929 /* IPA Emulation component reference */
Harald Welteae026692017-12-09 01:03:01 +0100930 IPA_Emulation_CT vc_IPA,
Harald Welte21b46bd2017-12-17 19:46:32 +0100931 /* Unit-ID and other CCM parameters to use for IPA client emulation */
Harald Welteae026692017-12-09 01:03:01 +0100932 IPA_CCM_Parameters ccm_pars,
Harald Welte21b46bd2017-12-17 19:46:32 +0100933 /* String identifier for this IPA Client */
Harald Welte624f9632017-12-16 19:26:04 +0100934 charstring id,
Harald Welte21b46bd2017-12-17 19:46:32 +0100935 /* Associated RSL Emulation Component (if any). Only used in "Handler mode" */
Harald Welte624f9632017-12-16 19:26:04 +0100936 RSL_Emulation_CT vc_RSL optional
Harald Welte28d943e2017-11-25 15:00:50 +0100937}
938
Harald Welte21b46bd2017-12-17 19:46:32 +0100939/*! Start the IPA/RSL related bits for one IPA_Client.
940 * \param clnt IPA_Client for which to establish
941 * \param bsc_host IP address / hostname of the BSC
942 * \param bsc_port TCP port number of the BSC
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600943 * \param idx BTS/TRX index values
Harald Welte21b46bd2017-12-17 19:46:32 +0100944 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600945function f_ipa_rsl_start(inout IPA_Client clnt, charstring bsc_host, PortNumber bsc_port,
946 BtsTrxIdx idx := {0, 0}, boolean handler_mode := false)
Harald Welte28d943e2017-11-25 15:00:50 +0100947runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +0100948 timer T := 10.0;
949
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600950 clnt.id := "IPA-BTS" & int2str(idx.bts) & "-TRX" & int2str(idx.trx) & "-RSL";
Harald Welte71389132021-12-09 21:58:18 +0100951 clnt.vc_IPA := IPA_Emulation_CT.create(clnt.id & "-IPA") alive;
Harald Welteae026692017-12-09 01:03:01 +0100952 clnt.ccm_pars := c_IPA_default_ccm_pars;
953 clnt.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600954 clnt.ccm_pars.unit_id := int2str(1234 + idx.bts) & "/0/" & int2str(idx.trx);
Harald Welte624f9632017-12-16 19:26:04 +0100955 if (handler_mode) {
Harald Welte71389132021-12-09 21:58:18 +0100956 clnt.vc_RSL := RSL_Emulation_CT.create(clnt.id & "-RSL") alive;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600957 connect(clnt.vc_RSL:CCHAN_PT, self:RSL_CCHAN[idx.bts]);
Harald Welte624f9632017-12-16 19:26:04 +0100958 }
Harald Welteae026692017-12-09 01:03:01 +0100959
960 map(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200961 connect(clnt.vc_IPA:CFG_PORT, self:IPA_CFG_PORT[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100962 if (handler_mode) {
963 connect(clnt.vc_IPA:IPA_RSL_PORT, clnt.vc_RSL:IPA_PT);
964 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600965 connect(clnt.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[idx.bts][idx.trx]);
Harald Welte624f9632017-12-16 19:26:04 +0100966 }
Harald Welteae026692017-12-09 01:03:01 +0100967
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600968 var integer local_port := 10000 + idx.bts * 1000 + idx.trx;
969 clnt.vc_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", local_port, clnt.ccm_pars));
Harald Welte624f9632017-12-16 19:26:04 +0100970 if (handler_mode) {
971 clnt.vc_RSL.start(RSL_Emulation.main());
972 return;
973 }
Harald Welteae026692017-12-09 01:03:01 +0100974
975 /* wait for IPA RSL link to connect and send ID ACK */
976 T.start;
977 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600978 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) {
Harald Welteae026692017-12-09 01:03:01 +0100979 T.stop;
Harald Welteae026692017-12-09 01:03:01 +0100980 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +0600981 [] IPA_RSL[idx.bts][idx.trx].receive(ASP_IPA_Event:?) { repeat }
982 [] IPA_RSL[idx.bts][idx.trx].receive { repeat }
Harald Welteae026692017-12-09 01:03:01 +0100983 [] T.timeout {
Harald Welte96c94412017-12-09 03:12:45 +0100984 setverdict(fail, "Timeout RSL waiting for ASP_IPA_EVENT_ID_ACK");
Daniel Willmannafce8662018-07-06 23:11:32 +0200985 mtc.stop;
Harald Welteae026692017-12-09 01:03:01 +0100986 }
987 }
988}
989
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +0200990function f_ipa_rsl_stop(inout IPA_Client clnt, BtsTrxIdx idx := {0, 0}) runs on test_CT {
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +0100991 var IPL4asp_Types.Result res := {
992 errorCode := omit,
993 connId := omit,
994 os_error_code := omit,
995 os_error_text := omit
996 };
997
Harald Welte12055472018-03-17 20:10:08 +0100998 if (not isbound(clnt) or not isbound(clnt.vc_IPA)) {
999 return;
1000 }
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001001
1002 /* Alive components don't finish sockets (TCP FIN) when they are
1003 * stopped. Hence, we need to manually call close() on them to make sure
1004 * the IUT knows about it. */
Pau Espin Pedrol80d4b4f2022-06-10 18:39:42 +02001005 f_ipa_cfg_disconnect(IPA_CFG_PORT[idx.bts][idx.trx], res);
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01001006
Harald Welte12055472018-03-17 20:10:08 +01001007 clnt.vc_IPA.stop;
1008 if (isbound(clnt.vc_RSL)) {
1009 clnt.vc_RSL.stop;
1010 }
1011}
1012
Harald Welte21b46bd2017-12-17 19:46:32 +01001013/* Wait for the OML connection to be brought up by the external osmo-bts-omldummy */
Harald Weltea5d2ab22017-12-09 14:21:42 +01001014function f_wait_oml(integer bts_nr, charstring status, float secs_max) runs on test_CT {
1015 timer T := secs_max;
1016 T.start;
1017 while (true) {
1018 if (f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-connection-state") == status) {
1019 T.stop;
Harald Weltebd868bd2017-12-10 18:28:40 +01001020 /* the 'degraded' state exists from OML connection time, and we have to wait
1021 * until all MO's are initialized */
1022 T.start(1.0);
1023 T.timeout;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001024 return;
1025 }
Harald Weltef0d6ac62017-12-17 17:02:21 +01001026 f_sleep(0.1);
Harald Weltea5d2ab22017-12-09 14:21:42 +01001027 if (not T.running) {
Max99253902018-11-16 17:57:39 +01001028 setverdict(fail, "Timeout waiting for BTS" & int2str(bts_nr) & " oml-connection-state ", status);
Daniel Willmannafce8662018-07-06 23:11:32 +02001029 mtc.stop;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001030 }
1031 }
1032}
1033
Harald Welte21b46bd2017-12-17 19:46:32 +01001034/* global altstep for global guard timer; also takes care of responding RESET witH RESET-ACK */
Harald Welteae026692017-12-09 01:03:01 +01001035altstep as_Tguard() runs on test_CT {
Harald Welte60e823a2017-12-10 14:10:59 +01001036 var BSSAP_N_UNITDATA_ind ud_ind;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001037 [] T_guard.timeout {
1038 setverdict(fail, "Timeout of T_guard");
Daniel Willmannafce8662018-07-06 23:11:32 +02001039 mtc.stop;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001040 }
Harald Welte60e823a2017-12-10 14:10:59 +01001041 /* always respond with RESET ACK to RESET */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001042 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
Harald Welte60e823a2017-12-10 14:10:59 +01001043 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001044 ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
Harald Welte69c1c262017-12-13 21:02:08 +01001045 repeat;
Harald Welte60e823a2017-12-10 14:10:59 +01001046 }
Harald Welte28d943e2017-11-25 15:00:50 +01001047}
1048
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001049altstep no_bssmap_reset() runs on test_CT {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001050 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001051 setverdict(fail, "unexpected BSSMAP Reset");
Daniel Willmannafce8662018-07-06 23:11:32 +02001052 mtc.stop;
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001053 }
1054}
1055
Daniel Willmann191e0d92018-01-17 12:44:35 +01001056function f_init_mgcp(charstring id) runs on test_CT {
1057 id := id & "-MGCP";
1058
1059 var MGCPOps ops := {
1060 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
1061 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
1062 };
1063 var MGCP_conn_parameters mgcp_pars := {
1064 callagent_ip := mp_bsc_ip,
Harald Welte9e4273e2018-01-29 22:01:22 +01001065 callagent_udp_port := -1,
Daniel Willmann191e0d92018-01-17 12:44:35 +01001066 mgw_ip := mp_test_ip,
Pau Espin Pedrol1a026a52019-06-18 17:21:52 +02001067 mgw_udp_port := 2427,
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02001068 /* Enable it for SCCPlite, since we have 2 MGCP sockets towards MGW (UDP one +
1069 the on with MGCP over IPA forwarded from MSC one) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001070 multi_conn_mode := (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER)
Daniel Willmann191e0d92018-01-17 12:44:35 +01001071 };
1072
Harald Welte71389132021-12-09 21:58:18 +01001073 vc_MGCP := MGCP_Emulation_CT.create(id) alive;
Daniel Willmann191e0d92018-01-17 12:44:35 +01001074 vc_MGCP.start(MGCP_Emulation.main(ops, mgcp_pars, id));
1075}
1076
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001077/* Enable or disable (current default) Osmux. When enabling, BSSMAP Reset
1078 * contains extra IE (OsmuxSupport) and osmo-bsc will handle AssignReq with
1079 * OsmuxCID IE.
1080 */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001081private function f_vty_allow_osmux_cn(boolean allow) runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001082 f_vty_enter_cfg_msc(BSCVTY, 0);
1083 if (allow) {
1084 f_vty_transceive(BSCVTY, "osmux on");
1085 } else {
1086 f_vty_transceive(BSCVTY, "osmux off");
1087 }
1088 f_vty_transceive(BSCVTY, "exit");
1089 f_vty_transceive(BSCVTY, "exit");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001090}
1091
Max2253c0b2018-11-06 19:28:05 +01001092function f_init_vty(charstring id := "foo") runs on test_CT {
Harald Welte94e0c342018-04-07 11:33:23 +02001093 if (BSCVTY.checkstate("Mapped")) {
1094 /* skip initialization if already executed once */
1095 return;
1096 }
Harald Weltebc03c762018-02-12 18:09:38 +01001097 map(self:BSCVTY, system:BSCVTY);
1098 f_vty_set_prompts(BSCVTY);
1099 f_vty_transceive(BSCVTY, "enable");
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01001100 f_cs7_inst_0_cfg(BSCVTY, {"sccp-timer ias " & int2str(g_bsc_sccp_timer_ias),
1101 "sccp-timer iar " & int2str(g_bsc_sccp_timer_iar)});
Harald Weltebc03c762018-02-12 18:09:38 +01001102}
1103
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +02001104friend function f_logp(TELNETasp_PT pt, charstring log_msg)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001105{
1106 // log on TTCN3 log output
1107 log(log_msg);
1108 // log in stderr log
Neels Hofmeyr8bdafe52021-12-14 17:25:48 +01001109 if (pt.checkstate("Mapped")) {
1110 f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
1111 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001112}
1113
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001114private function f_sysinfo_seen(integer rsl_idx, RSL_Message rsl) runs on test_CT
1115{
1116 if (rsl_idx >= lengthof(g_system_information)) {
1117 g_system_information[rsl_idx] := SystemInformationConfig_omit
1118 }
1119 f_sysinfo_dec_raw(g_system_information[rsl_idx], rsl);
1120}
1121
1122altstep as_catch_RSL_sysinfo(integer rsl_idx) runs on test_CT {
1123 var ASP_RSL_Unitdata rx_rsl_ud;
1124
1125 /* For handler_mode := false, receiving the RSL bootstrap messages directly on IPA_RSL */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001126 [] 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 +02001127 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1128 repeat;
1129 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001130 [] 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 +02001131 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1132 repeat;
1133 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001134 [] 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 +02001135 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1136 repeat;
1137 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001138 [] 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 +02001139 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1140 repeat;
1141 }
1142
1143 /* For handler_mode := true, receiving the RSL bootstrap messages via RSL_Emulation */
1144 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
1145 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1146 repeat;
1147 }
1148 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
1149 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1150 repeat;
1151 }
1152 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
1153 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1154 repeat;
1155 }
1156 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
1157 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1158 repeat;
1159 }
1160}
1161
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001162/* TODO: use BooleanList from COMMON/src/General_Types.ttcn */
1163private type record of boolean my_BooleanList;
1164
1165private function f_vty_msc_allow_attach(TELNETasp_PT pt, my_BooleanList allow_attach_list)
1166{
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001167 var charstring config := f_vty_transceive_ret(pt, "show running-config");
1168
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001169 for (var integer msc_nr := 0; msc_nr < sizeof(allow_attach_list); msc_nr := msc_nr+1) {
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001170 if (f_strstr(config, "\nmsc " & int2str(msc_nr) & "\n") < 0) {
1171 /* There is no 'msc N' for this msc_nr in the running config, so don't create an empty msc by
1172 * stepping into that config node. */
1173 log("msc ", msc_nr, " is not configured, skipping");
1174 continue;
1175 }
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001176 f_vty_enter_cfg_msc(pt, msc_nr);
1177 if (allow_attach_list[msc_nr]) {
1178 /* strict := false: ignore if osmo-bsc does not support this config option (latest build) */
1179 f_vty_transceive(pt, "allow-attach", strict := false);
1180 } else {
1181 f_vty_transceive(pt, "no allow-attach", strict := false);
1182 }
1183 f_vty_transceive(pt, "exit");
1184 f_vty_transceive(pt, "exit");
1185 }
1186}
1187
Harald Welte21b46bd2017-12-17 19:46:32 +01001188/* global initialization function
1189 * \param nr_bts Number of BTSs we should start/bring up
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001190 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false).
1191 * \param nr_msc Number of virtual MSCs to bring up to connect to osmo-bsc.
1192 */
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001193function f_init(integer nr_bts := NUM_BTS, boolean handler_mode := false,
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +02001194 integer nr_msc := 1, float guard_timeout := 30.0) runs on test_CT {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001195 var integer bssap_idx;
Harald Welte28d943e2017-11-25 15:00:50 +01001196
Harald Welteae026692017-12-09 01:03:01 +01001197 if (g_initialized) {
1198 return;
Harald Welte28d943e2017-11-25 15:00:50 +01001199 }
Harald Welteae026692017-12-09 01:03:01 +01001200 g_initialized := true;
1201
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +02001202 T_guard.start(guard_timeout);
Daniel Willmanne68f9272018-11-27 15:15:28 +01001203 activate(as_Tguard());
1204
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001205 f_init_vty("VirtMSC");
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02001206 f_vty_allow_osmux_cn(g_osmux_enabled_cn);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001207
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001208 var my_BooleanList allow_attach := { false, false, false };
Daniel Willmannebdecc02020-08-12 15:30:17 +02001209 f_init_statsd("VirtMSC", vc_STATSD, mp_test_ip, mp_bsc_statsd_port);
1210
Neels Hofmeyr9db8e0e2021-08-23 20:45:58 +02001211 /* Make sure each MSC's internal state is "DISCONNECTED" at first */
1212 for (bssap_idx := 0; bssap_idx < NUM_MSC; bssap_idx := bssap_idx+1) {
1213 f_vty_transceive(BSCVTY, "msc " & int2str(bssap_idx) & " bssmap reset", strict := false);
1214 }
1215
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001216 for (bssap_idx := 0; bssap_idx < nr_msc; bssap_idx := bssap_idx+1) {
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001217 allow_attach[bssap_idx] := true;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001218 /* Call a function of our 'parent component' RAN_Adapter_CT to start the
1219 * MSC-side BSSAP emulation */
1220 if (handler_mode) {
1221 var RanOps ranops := MSC_RanOps;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02001222 ranops.use_osmux := g_osmux_enabled_cn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001223 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", ranops);
1224 connect(self:SCCPLITE_IPA_CTRL, g_bssap[bssap_idx].vc_RAN:CTRL_CLIENT);
1225 f_ran_adapter_start(g_bssap[bssap_idx]);
1226 } else {
1227 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", omit);
1228 connect(self:BSSAP, g_bssap[bssap_idx].vc_SCCP:SCCP_SP_PORT);
1229 f_ran_adapter_start(g_bssap[bssap_idx]);
1230 f_legacy_bssap_reset();
1231 }
Harald Welte67089ee2018-01-17 22:19:03 +01001232 }
Harald Welted5833a82018-05-27 16:52:56 +02001233
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02001234 if (mp_enable_lcs_tests) {
1235 if (handler_mode) {
1236 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", SMLC_BssapLeOps);
1237 } else {
1238 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", omit);
1239 connect(self:BSSAP_LE, g_bssap_le.vc_SCCP:SCCP_SP_PORT);
1240 }
1241 f_bssap_le_adapter_start(g_bssap_le);
Harald Welte47cd0e32020-08-21 12:39:11 +02001242 }
Harald Welte47cd0e32020-08-21 12:39:11 +02001243
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001244 /* start the test with exactly all enabled MSCs allowed to attach */
1245 f_vty_msc_allow_attach(BSCVTY, allow_attach);
1246
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01001247 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Harald Welte28d943e2017-11-25 15:00:50 +01001248
Daniel Willmann191e0d92018-01-17 12:44:35 +01001249 f_init_mgcp("VirtMSC");
1250
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001251 for (var integer i := 0; i < nr_bts; i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001252 f_init_bts(i, c_BtsParams[i].trx_num, handler_mode);
Harald Welte696ddb62017-12-08 14:01:43 +01001253 }
Neels Hofmeyr9c0f9c82022-01-23 01:20:28 +01001254
1255 /* Emit a marker to appear in the SUT's own logging output */
1256 f_logp(BSCVTY, testcasename() & "() start");
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001257}
Harald Welte696ddb62017-12-08 14:01:43 +01001258
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001259function f_init_bts(integer bts_idx := 0,
1260 integer trx_num := NUM_TRX_CFG,
1261 boolean handler_mode := false)
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001262runs on test_CT {
1263 /* wait until osmo-bts-omldummy has respawned */
1264 f_wait_oml(bts_idx, "degraded", 5.0);
1265
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001266 /* start RSL connection(s) */
1267 for (var integer trx_idx := 0; trx_idx < trx_num; trx_idx := trx_idx + 1) {
1268 f_ipa_rsl_start(bts[bts_idx][trx_idx].rsl,
1269 mp_bsc_ip, mp_bsc_rsl_port,
1270 {bts_idx, trx_idx}, handler_mode);
1271 }
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001272 /* wait until BSC tells us "connected" */
1273 f_wait_oml(bts_idx, "connected", 5.0);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001274
1275 /* Set up BTS with VTY commands: */
1276 f_vty_enter_cfg_bts(BSCVTY, bts_idx);
1277 if (g_osmux_enabled_bts) {
1278 f_vty_transceive(BSCVTY, "osmux on");
1279 } else {
1280 f_vty_transceive(BSCVTY, "osmux off");
1281 }
1282 f_vty_transceive(BSCVTY, "end");
Harald Welte28d943e2017-11-25 15:00:50 +01001283}
1284
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001285function f_init_bts_and_check_sysinfo(integer bts_idx := 0,
1286 integer trx_num := NUM_TRX_CFG,
1287 boolean handler_mode := false,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001288 template SystemInformationConfig expect_si)
1289runs on test_CT {
1290 var default sysinfo := activate(as_catch_RSL_sysinfo(bts_idx));
1291
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001292 f_init_bts(bts_idx, trx_num, handler_mode);
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001293
1294 /* Give some time to (hopefully/most likely) collect all system informations from RSL startup.
1295 * We could stop as soon as all expected SI are received, but then we might miss SI that we don't expect and
1296 * that might be sent afterwards. So rather give a generous timeout and be quite sure to catch all SI.
1297 */
1298 f_sleep(5.0);
1299 log("RSL ", bts_idx, " SYSTEM INFORMATION: ", g_system_information[bts_idx]);
1300
1301 deactivate(sysinfo);
1302
1303 if (match(g_system_information[bts_idx], expect_si)) {
1304 setverdict(pass);
1305 } else {
1306 log("RSL ", bts_idx, ": EXPECTED SI: ", expect_si);
1307 log("RSL ", bts_idx, ": GOT SI: ", g_system_information[bts_idx]);
1308 setverdict(fail, "received SI does not match expectations");
1309 return;
1310 }
1311}
1312
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001313/* expect to receive a RSL message matching a specified template on a given BTS / TRX */
1314function f_exp_ipa_rx(template (present) RSL_Message t_rx,
1315 BtsTrxIdx idx := {0, 0},
1316 float Tval := 2.0)
Harald Welteae026692017-12-09 01:03:01 +01001317runs on test_CT return RSL_Message {
1318 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001319 timer T := Tval;
Harald Welteae026692017-12-09 01:03:01 +01001320
1321 T.start;
1322 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001323 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Harald Welteae026692017-12-09 01:03:01 +01001324 T.stop;
1325 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001326 [] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
Harald Welteb2917702017-12-10 15:48:52 +01001327 [] T.timeout {
1328 setverdict(fail, "Timeout expecting ", t_rx);
Daniel Willmannafce8662018-07-06 23:11:32 +02001329 mtc.stop;
Harald Welteb2917702017-12-10 15:48:52 +01001330 }
Harald Welteae026692017-12-09 01:03:01 +01001331 }
1332 return rx_rsl_ud.rsl;
1333}
1334
Harald Welte21b46bd2017-12-17 19:46:32 +01001335/* helper function to transmit RSL on a given BTS/stream */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001336function f_ipa_tx(template (value) RSL_Message t_tx,
1337 BtsTrxIdx idx := {0, 0},
1338 IpaStreamId sid := IPAC_PROTO_RSL_TRX0)
Harald Welteae026692017-12-09 01:03:01 +01001339runs on test_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001340 IPA_RSL[idx.bts][idx.trx].send(ts_ASP_RSL_UD(t_tx, sid));
Harald Welteae026692017-12-09 01:03:01 +01001341}
1342
1343
Harald Welte4003d112017-12-09 22:35:39 +01001344/* verify we get a CHAN_ACT after CHAN RQD */
Harald Welteae026692017-12-09 01:03:01 +01001345testcase TC_chan_act_noreply() runs on test_CT {
1346 var BSSAP_N_UNITDATA_ind ud_ind;
Harald Welte930d0a72018-03-22 22:08:40 +01001347 var RSL_Message rsl_unused;
Harald Welte28d943e2017-11-25 15:00:50 +01001348
Harald Welte89d42e82017-12-17 16:42:41 +01001349 f_init(1);
Harald Welte28d943e2017-11-25 15:00:50 +01001350
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001351 f_ipa_tx(ts_RSL_CHAN_RQD('23'O, 23));
1352 rsl_unused := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001353 f_shutdown_helper();
Harald Welte28d943e2017-11-25 15:00:50 +01001354}
1355
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001356const CounterNameVals counternames_bts_chreq := {
1357 { "chreq:total", 0 },
1358 { "chreq:attempted_emerg", 0 },
1359 { "chreq:attempted_call", 0 },
1360 { "chreq:attempted_location_upd", 0 },
1361 { "chreq:attempted_pag", 0 },
1362 { "chreq:attempted_pdch", 0 },
1363 { "chreq:attempted_other", 0 },
1364 { "chreq:attempted_unknown", 0 },
1365 { "chreq:successful", 0 },
1366 { "chreq:successful_emerg", 0 },
1367 { "chreq:successful_call", 0 },
1368 { "chreq:successful_location_upd", 0 },
1369 { "chreq:successful_pag", 0 },
1370 { "chreq:successful_pdch", 0 },
1371 { "chreq:successful_other", 0 },
1372 { "chreq:successful_unknown", 0 },
1373 { "chreq:no_channel", 0 },
1374 { "chreq:max_delay_exceeded", 0 }
1375};
1376
1377/* verify the "chreq:*" counters */
1378private function f_chan_act_counter(OCT1 ra, charstring chreq_ctr_suffix) runs on test_CT
1379{
1380 var GsmFrameNumber fn := 23;
1381
1382 f_logp(BSCVTY, "f_chan_act_counter(" & chreq_ctr_suffix & ")");
1383
1384 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001385 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn));
1386 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001387 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1388
1389 f_ctrs_bts_add(0, "chreq:total");
1390 f_ctrs_bts_add(0, "chreq:attempted_" & chreq_ctr_suffix);
1391 f_ctrs_bts_verify();
1392
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001393 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
1394 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001395
1396 f_ctrs_bts_add(0, "chreq:successful");
1397 f_ctrs_bts_add(0, "chreq:successful_" & chreq_ctr_suffix);
1398 f_ctrs_bts_verify();
1399
1400 /* test is done, release RSL Conn Fail Ind to clean up */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001401 f_ipa_tx(ts_RSL_CONN_FAIL_IND(chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1402 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
1403 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001404 f_sleep(1.0);
1405}
1406
Harald Welte4003d112017-12-09 22:35:39 +01001407testcase TC_chan_act_counter() runs on test_CT {
1408 var BSSAP_N_UNITDATA_ind ud_ind;
1409 var integer chreq_total;
Harald Welte930d0a72018-03-22 22:08:40 +01001410 var RSL_Message rsl_unused;
Harald Welte4003d112017-12-09 22:35:39 +01001411
Harald Welte89d42e82017-12-17 16:42:41 +01001412 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001413
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001414 f_vty_allow_emerg_bts(true, 0);
1415
1416 f_ctrs_bts_init(1, counternames_bts_chreq);
1417
1418 /* emergency call: RA & 0xe0 == 0xa0 --> CHREQ_T_EMERG_CALL */
1419 f_chan_act_counter('a3'O, "emerg");
1420
1421 /* voice TCH/H: RA & 0xf0 == 0x40 --> CHREQ_T_VOICE_CALL_TCH_H */
1422 f_chan_act_counter('43'O, "call");
1423
1424 /* LU: RA & 0xf0 == 0x00 --> CHREQ_T_LOCATION_UPD */
1425 f_chan_act_counter('03'O, "location_upd");
1426
1427 /* Paging: RA & 0xf0 == 0x20 --> CHREQ_T_PAG_R_TCH_F */
1428 f_chan_act_counter('23'O, "pag");
1429 /* Paging: RA & 0xf0 == 0x30 --> CHREQ_T_PAG_R_TCH_FH */
1430 f_chan_act_counter('33'O, "pag");
1431
1432 /* LU: RA & 0xfc == 0x78 --> CHREQ_T_PDCH_TWO_PHASE */
1433 /* no PCU, so PDCH not allowed. Skip this test for now. */
1434 /* f_chan_act_counter('7b'O, "pdch"); */
1435
1436 /* LU: RA & 0xf0 == 0x10 --> CHREQ_T_SDCCH */
1437 f_chan_act_counter('13'O, "other");
Harald Welte4003d112017-12-09 22:35:39 +01001438
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001439 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001440}
1441
Harald Welteae026692017-12-09 01:03:01 +01001442/* CHAN RQD -> CHAN ACT -> CHAN ACT ACK -> RF CHAN REL */
Philipp Maier9c60a622020-07-09 15:08:46 +02001443private function f_TC_chan_act_ack_noest(OCT1 ra := '23'O) runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +01001444 var RSL_Message rx_rsl;
1445
Harald Welteae026692017-12-09 01:03:01 +01001446 /* Send CHAN RQD and wait for allocation; acknowledge it */
Philipp Maier9c60a622020-07-09 15:08:46 +02001447 var RslChannelNr chan_nr := f_chreq_act_ack(ra);
Harald Welteae026692017-12-09 01:03:01 +01001448
1449 /* expect BSC to disable the channel again if there's no RLL EST IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001450 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := T3101_MAX);
Harald Welteae026692017-12-09 01:03:01 +01001451
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001452 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001453}
1454
Philipp Maier9c60a622020-07-09 15:08:46 +02001455/* Normal variant */
1456testcase TC_chan_act_ack_noest() runs on test_CT {
Philipp Maieraf58db22020-08-12 17:24:40 +02001457 f_init(1);
Philipp Maier9c60a622020-07-09 15:08:46 +02001458 f_TC_chan_act_ack_noest();
1459}
1460
1461/* Emergency call variant */
1462testcase TC_chan_act_ack_noest_emerg() runs on test_CT {
1463 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
Philipp Maieraf58db22020-08-12 17:24:40 +02001464 f_init(1);
1465 f_vty_allow_emerg_bts(true, 0);
Philipp Maier9c60a622020-07-09 15:08:46 +02001466 f_TC_chan_act_ack_noest(ra := 'A5'O);
1467}
1468
Philipp Maier606f07d2020-08-12 17:21:58 +02001469/* Emergency call variant, but emergency calls are not allowed */
1470testcase TC_chan_rqd_emerg_deny() runs on test_CT {
1471 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
1472
1473 var RSL_Message rx_rsl;
1474 var GsmRrMessage rr;
1475
1476 f_init(1);
1477 f_vty_allow_emerg_bts(false, 0);
1478
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001479 IPA_RSL[0][0].clear;
1480 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier606f07d2020-08-12 17:21:58 +02001481
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001482 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Philipp Maier606f07d2020-08-12 17:21:58 +02001483 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
1484 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1485 setverdict(pass);
1486 } else {
1487 setverdict(fail, "immediate assignment not rejected");
1488 }
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01001489
1490 f_shutdown_helper();
Philipp Maier606f07d2020-08-12 17:21:58 +02001491}
1492
Harald Welteae026692017-12-09 01:03:01 +01001493/* Test behavior if MSC never answers to CR */
1494testcase TC_chan_act_ack_est_ind_noreply() runs on test_CT {
Harald Weltef77aef62018-01-28 15:35:42 +01001495 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
1496 var IpaStreamId sid := IPAC_PROTO_RSL_TRX0;
Harald Welteae026692017-12-09 01:03:01 +01001497 var RSL_Message rx_rsl;
Harald Weltef77aef62018-01-28 15:35:42 +01001498 var ASP_RSL_Unitdata rx_rsl_ud;
Harald Welteae026692017-12-09 01:03:01 +01001499
Harald Welte89d42e82017-12-17 16:42:41 +01001500 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001501
1502 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001503 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001504
1505 var octetstring l3 := '00010203040506'O
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001506 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
Harald Welteae026692017-12-09 01:03:01 +01001507
1508 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3)));
1509
1510 /* expect BSC to disable the channel again if there's no response from MSC */
Harald Weltef77aef62018-01-28 15:35:42 +01001511 /* MS waits 20s (T3210) at LU; 10s (T3230) at CM SERV REQ and 5s (T3220) AT detach */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001512 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001513 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001514}
1515
1516/* Test behavior if MSC answers with CREF to CR */
1517testcase TC_chan_act_ack_est_ind_refused() runs on test_CT {
1518 var BSSAP_N_CONNECT_ind rx_c_ind;
1519 var RSL_Message rx_rsl;
1520
Harald Welte89d42e82017-12-17 16:42:41 +01001521 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001522
1523 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001524 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001525
1526 var octetstring l3 := '00010203040506'O
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001527 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
Harald Welteae026692017-12-09 01:03:01 +01001528
1529 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1530 BSSAP.send(ts_BSSAP_DISC_req(rx_c_ind.connectionId, 0));
1531
1532 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001533 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001534 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001535}
1536
Harald Welte618ef642017-12-14 14:58:20 +01001537/* CHAN RQD -> CHAN ACT -> CHAN ACT NACK -> RF CHAN REL */
1538testcase TC_chan_act_nack() runs on test_CT {
1539 var RSL_Message rx_rsl;
1540 var integer chact_nack;
1541
Harald Welte89d42e82017-12-17 16:42:41 +01001542 f_init(1);
Harald Welte618ef642017-12-14 14:58:20 +01001543
1544 chact_nack := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack");
1545
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001546 f_ipa_tx(ts_RSL_CHAN_RQD('33'O, 33));
1547 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Harald Welte618ef642017-12-14 14:58:20 +01001548 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1549
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001550 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte618ef642017-12-14 14:58:20 +01001551
1552 /* wait for some time to hope the NACK arrives before the CTRL GET below */
1553 f_sleep(0.5);
1554
1555 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack", chact_nack+1);
1556
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001557 f_shutdown_helper();
Harald Welte618ef642017-12-14 14:58:20 +01001558}
1559
Harald Welte799c97b2017-12-14 17:50:30 +01001560/* Test for channel exhaustion due to RACH overload */
1561testcase TC_chan_exhaustion() runs on test_CT {
1562 var ASP_RSL_Unitdata rsl_ud;
1563 var integer i;
1564 var integer chreq_total, chreq_nochan;
1565
Harald Welte89d42e82017-12-17 16:42:41 +01001566 f_init(1);
Harald Welte799c97b2017-12-14 17:50:30 +01001567
1568 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
1569 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
1570
Neels Hofmeyr85fa37f2021-10-06 13:50:38 +02001571 /* GSM 44.018 Table 9.1.8.2:
Pau Espin Pedrolfe200d72018-12-10 12:41:04 +01001572 * RA = '33'O -> Establishment cause = 0011xxxx (MS dual rate capable and asks for "TCH/H or TCH/F").
1573 * With current setup, expect 4xSDCCH + 4xTCH/F + 1xTCH/H to succeed */
Philipp Maiercb6cc482018-03-26 13:08:00 +02001574 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 +01001575 var RslChannelNr chan_nr := f_chreq_act_ack('33'O, i);
Harald Welte799c97b2017-12-14 17:50:30 +01001576 }
1577
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001578 IPA_RSL[0][0].clear;
Harald Welte799c97b2017-12-14 17:50:30 +01001579
Harald Weltedd8cbf32018-01-28 12:07:52 +01001580 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001581 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
Harald Welte799c97b2017-12-14 17:50:30 +01001582
1583 /* now expect additional channel activations to fail */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001584 f_ipa_tx(ts_RSL_CHAN_RQD('42'O, 42));
Harald Welte799c97b2017-12-14 17:50:30 +01001585
1586 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001587 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV))) {
Harald Welte799c97b2017-12-14 17:50:30 +01001588 setverdict(fail, "Received CHAN ACT ACK without resources?!?");
1589 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001590 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) -> value rsl_ud {
Harald Welte799c97b2017-12-14 17:50:30 +01001591 var GsmRrMessage rr;
1592 /* match on IMM ASS REJ */
1593 rr := dec_GsmRrMessage(rsl_ud.rsl.ies[1].body.full_imm_ass_info.payload);
1594 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1595 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001596 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS+1);
Harald Welte799c97b2017-12-14 17:50:30 +01001597 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel",
1598 chreq_nochan+1);
1599 setverdict(pass);
1600 } else {
1601 repeat;
1602 }
1603 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001604 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte799c97b2017-12-14 17:50:30 +01001605 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001606 f_shutdown_helper();
Harald Welte799c97b2017-12-14 17:50:30 +01001607}
1608
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001609/* Test channel deactivation due to silence from MS */
1610testcase TC_chan_deact_silence() runs on test_CT {
1611 var RslChannelNr chan_nr;
1612
1613 f_init(1);
1614
1615 /* Request for a dedicated channel */
1616 chan_nr := f_chreq_act_ack('23'O);
1617
1618 /* Wait some time until the channel is released */
1619 f_sleep(2.0);
1620
1621 /* Expect CHANnel RELease */
1622 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001623 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001624 log("Received CHANnel RELease");
1625 setverdict(pass);
1626 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001627 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001628 /* See OS#3709, OsmoBSC should not send Immediate
1629 * Assignment Reject since a dedicated channel was
1630 * already allocated, and Immediate Assignment was
1631 * already sent. */
1632 setverdict(fail, "Unexpected Immediate Assignment!");
1633 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001634 [] IPA_RSL[0][0].receive {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001635 setverdict(fail, "Unexpected RSL message!");
1636 }
1637 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001638 f_shutdown_helper();
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001639}
1640
Harald Weltecfe2c962017-12-15 12:09:32 +01001641/***********************************************************************
1642 * Assignment Testing
1643 ***********************************************************************/
1644
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02001645/* Verify that the BSC refuses any BSSAP connection from the MSC (They are all BSC->MSC direction,
1646 * except for the inter-BSC handover, MT side) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001647testcase TC_outbound_connect(integer bssap_idx := 0) runs on test_CT {
Harald Welte89d42e82017-12-17 16:42:41 +01001648 f_init(1);
Harald Weltecfe2c962017-12-15 12:09:32 +01001649
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001650 BSSAP.send(ts_BSSAP_CONNECT_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
1651 2342, ts_BSSMAP_AssignmentReq));
Harald Weltecfe2c962017-12-15 12:09:32 +01001652 BSSAP.receive(tr_BSSAP_DISC_ind(2342, ?, ?));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001653 f_shutdown_helper();
Harald Weltecfe2c962017-12-15 12:09:32 +01001654}
1655
Harald Welte16a4adf2017-12-14 18:54:01 +01001656/* Test behavior if MSC answers with CREF to CR */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001657testcase TC_assignment_cic_only(integer bssap_idx := 0) runs on test_CT {
Harald Welte16a4adf2017-12-14 18:54:01 +01001658 var BSSAP_N_CONNECT_ind rx_c_ind;
1659 var RSL_Message rx_rsl;
1660 var DchanTuple dt;
1661
Harald Welte89d42e82017-12-17 16:42:41 +01001662 f_init(1);
Harald Welte16a4adf2017-12-14 18:54:01 +01001663
1664 dt := f_est_dchan('23'O, 23, '00000000'O);
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001665 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte17b27da2018-05-25 20:33:53 +02001666 /* send assignment without AoIP IEs */
1667 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(ts_BSSMAP_IE_CIC(0, 1))));
1668 } else {
1669 /* Send assignmetn without CIC in IPA case */
1670 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
1671 valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
1672 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(omit, tla)));
1673 }
Harald Welte16a4adf2017-12-14 18:54:01 +01001674 alt {
1675 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1676 setverdict(fail, "AoIP BSC cannot accept ASSIGNMENT without AoIP Transport IE");
1677 }
Harald Welte235ebf12017-12-15 14:18:16 +01001678 /* TODO: Actually expect GSM0808_CAUSE_REQ_A_IF_TYPE_NOT_SUPP */
Harald Welte16a4adf2017-12-14 18:54:01 +01001679 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1680 setverdict(pass);
1681 }
1682 [] BSSAP.receive { repeat; }
1683 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001684 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001685 f_shutdown_helper();
Harald Welte16a4adf2017-12-14 18:54:01 +01001686}
1687
Harald Welteed848512018-05-24 22:27:58 +02001688/* generate an assignment request for either AoIP or SCCPlite */
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001689function 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 +02001690 var PDU_BSSAP ass_cmd;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001691 var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001692 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welteed848512018-05-24 22:27:58 +02001693 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001694 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001695 if (osmux_enabled) {
1696 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla, osmux_cid));
1697 } else {
1698 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla));
1699 }
Harald Welteed848512018-05-24 22:27:58 +02001700 } else {
1701 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrol096d73d2019-06-06 12:49:17 +02001702 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(cic, omit));
Harald Welteed848512018-05-24 22:27:58 +02001703 }
1704 return ass_cmd;
1705}
1706
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02001707function f_gen_handover_req(integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4",
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001708 template (value) BSSMAP_IE_CellIdentifier cell_id_source := ts_CellID_LAC_CI(1, 1),
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001709 template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit,
1710 template (omit) TestHdlrEncrParams enc := omit) return PDU_BSSAP {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001711 var PDU_BSSAP ho_req;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001712
1713 var BSSMAP_IE_EncryptionInformation encryptionInformation :=
1714 valueof(ts_BSSMAP_IE_EncrInfo('0000000000000000'O,'01'O));
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03001715 var template (omit) BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := omit;
1716 var template (omit) BSSMAP_IE_KC128 kc128 := omit;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001717 if (ispresent(enc)) {
1718 var TestHdlrEncrParams v_enc := valueof(enc);
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01001719 encryptionInformation := valueof(ts_BSSMAP_IE_EncrInfo(v_enc.enc_key, v_enc.enc_alg_permitted));
1720 if (ispresent(v_enc.enc_alg_chosen)) {
1721 chosenEncryptionAlgorithm := valueof(
1722 ts_BSSMAP_IE_ChosenEncryptionAlgorithm(int2oct(enum2int(
1723 f_cipher_mode_bssmap_to_rsl(v_enc.enc_alg_chosen)), 1)));
1724 }
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001725 if (ispresent(v_enc.enc_kc128)) {
1726 kc128 := ts_BSSMAP_IE_Kc128(v_enc.enc_kc128);
1727 }
1728 }
1729
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001730 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001731 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001732 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001733 ho_req := valueof(ts_BSSMAP_HandoverRequest(omit, tla,
1734 cell_id_source := cell_id_source,
1735 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001736 encryptionInformation := encryptionInformation,
1737 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
Neels Hofmeyr9fe13202022-03-04 00:05:43 +01001738 kC128 := kc128,
1739 /* on AoIP, allow "all" codecs (until we add more concise
1740 * tests) */
1741 codecList := ts_BSSMAP_IE_CodecList(
1742 {ts_CodecAMR_F, ts_CodecAMR_H,
1743 ts_CodecEFR, ts_CodecFR, ts_CodecHR})));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001744 } else {
1745 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001746 ho_req := valueof(ts_BSSMAP_HandoverRequest(cic, omit,
1747 cell_id_source := cell_id_source,
1748 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001749 encryptionInformation := encryptionInformation,
1750 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
1751 kC128 := kc128));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001752 }
1753 return ho_req;
1754}
1755
Harald Welteed848512018-05-24 22:27:58 +02001756/* generate an assignment complete template for either AoIP or SCCPlite */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001757function f_gen_exp_compl(integer bssap_idx := 0)
1758runs on MSC_ConnHdlr return template PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001759 var template PDU_BSSAP exp_compl;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001760 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001761 var template BSSMAP_IE_Osmo_OsmuxCID exp_osmux_cid := omit;
1762 if (g_pars.use_osmux_cn) {
1763 var template (present) INT1 exp_cid := ?;
1764 if (isbound(g_media.mgcp_conn[0].local_osmux_cid) and isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1765 exp_cid := (g_media.mgcp_conn[0].local_osmux_cid, g_media.mgcp_conn[1].local_osmux_cid);
1766 } else if (isbound(g_media.mgcp_conn[0].local_osmux_cid)) {
1767 exp_cid := g_media.mgcp_conn[0].local_osmux_cid;
1768 } else if (isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1769 exp_cid := g_media.mgcp_conn[1].local_osmux_cid;
1770 }
1771 exp_osmux_cid := tr_OsmuxCID(exp_cid);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001772 }
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001773 exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, exp_osmux_cid);
Harald Welteed848512018-05-24 22:27:58 +02001774 } else {
1775 /* CIC is optional "*" as the MSC allocated it */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001776 exp_compl := tr_BSSMAP_AssignmentComplete(*, omit, omit);
Harald Welteed848512018-05-24 22:27:58 +02001777 }
1778 return exp_compl;
1779}
1780
Harald Welte235ebf12017-12-15 14:18:16 +01001781/* Run everything required up to sending a caller-specified assignment command and expect response */
1782function f_assignment_exp(PDU_BSSAP ass_cmd, template PDU_BSSAP exp, charstring fail_text)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001783runs on test_CT return DchanTuple {
Harald Welte235ebf12017-12-15 14:18:16 +01001784 var BSSAP_N_CONNECT_ind rx_c_ind;
1785 var RSL_Message rx_rsl;
1786 var DchanTuple dt;
1787
Harald Welte89d42e82017-12-17 16:42:41 +01001788 f_init(1);
Harald Welte235ebf12017-12-15 14:18:16 +01001789
1790 dt := f_est_dchan('23'O, 23, '00000000'O);
1791 /* send assignment without AoIP IEs */
1792 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
1793 alt {
1794 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1795 if (ischosen(exp.pdu.bssmap.assignmentComplete)) {
1796 setverdict(pass);
1797 } else {
1798 setverdict(fail, fail_text);
1799 }
1800 }
1801 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1802 if (ischosen(exp.pdu.bssmap.assignmentFailure)) {
1803 setverdict(pass);
1804 } else {
1805 setverdict(fail, fail_text);
1806 }
1807 }
1808 [] BSSAP.receive { repeat; }
1809 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001810 return dt;
Harald Welte235ebf12017-12-15 14:18:16 +01001811}
1812testcase TC_assignment_csd() runs on test_CT {
1813 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001814 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001815 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
1816 //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 +01001817 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for CSD");
1818 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001819 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001820}
1821
1822testcase TC_assignment_ctm() runs on test_CT {
1823 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001824 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001825 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
1826 //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 +01001827 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
1828 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001829 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001830}
1831
Harald Welte4003d112017-12-09 22:35:39 +01001832type record DchanTuple {
1833 integer sccp_conn_id,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001834 RslChannelNr rsl_chan_nr,
1835 BtsTrxIdx idx
Harald Weltea5d2ab22017-12-09 14:21:42 +01001836}
1837
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +02001838type record of DchanTuple DchanTuples;
1839
Harald Welted6939652017-12-13 21:02:46 +01001840/* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001841private function f_chreq_act_ack(OCT1 ra := '23'O,
1842 GsmFrameNumber fn := 23,
1843 BtsTrxIdx idx := {0, 0})
Harald Welted6939652017-12-13 21:02:46 +01001844runs on test_CT return RslChannelNr {
1845 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001846 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
1847 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Harald Welted6939652017-12-13 21:02:46 +01001848 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001849 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10), idx);
1850 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Harald Welted6939652017-12-13 21:02:46 +01001851 return chan_nr;
1852}
1853
Harald Welte4003d112017-12-09 22:35:39 +01001854/* helper function to establish a dedicated channel via BTS and MSC */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001855function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1856 BtsTrxIdx idx := {0, 0})
Harald Welte4003d112017-12-09 22:35:39 +01001857runs on test_CT return DchanTuple {
1858 var BSSAP_N_CONNECT_ind rx_c_ind;
Harald Welte4003d112017-12-09 22:35:39 +01001859 var DchanTuple dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001860
Harald Welte4003d112017-12-09 22:35:39 +01001861 /* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001862 dt.rsl_chan_nr := f_chreq_act_ack(ra, fn, idx);
Harald Welte4003d112017-12-09 22:35:39 +01001863
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001864 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 +01001865
1866 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1867 dt.sccp_conn_id := rx_c_ind.connectionId;
1868 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1869
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001870 dt.idx := idx;
Harald Welte4003d112017-12-09 22:35:39 +01001871 return dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001872}
1873
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001874/* 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 +06001875function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1876 BtsTrxIdx idx := {0, 0})
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001877runs on test_CT return DchanTuple {
1878 var BSSAP_N_CONNECT_ind rx_c_ind;
1879 var DchanTuple dt;
1880
1881 /* Send CHAN RQD */
1882 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001883 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001884
1885 /* The dyn TS first deactivates PDCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001886 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 +02001887 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001888 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001889
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001890 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001891 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1892
1893 /* Now activates the signalling channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001894 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10), idx);
1895 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001896
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001897 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 +02001898
1899 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1900 dt.sccp_conn_id := rx_c_ind.connectionId;
1901 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1902
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001903 dt.idx := idx;
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001904 return dt;
1905}
1906
Harald Welte641fcbe2018-06-14 10:58:35 +02001907/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001908private function f_exp_chan_rel_and_clear(DchanTuple dt)
1909runs on test_CT {
Harald Welte641fcbe2018-06-14 10:58:35 +02001910 var RSL_Message rx_rsl;
1911 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001912 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 +02001913 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001914 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), dt.idx);
Harald Welte641fcbe2018-06-14 10:58:35 +02001915
1916 /* expect Clear Complete from BSC */
1917 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
1918
1919 /* MSC disconnects as instructed. */
1920 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
1921}
1922
Harald Welte4003d112017-12-09 22:35:39 +01001923/* Test behavior of channel release after unilateral RLL REL IND (DISC from MS) */
1924testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001925 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01001926 var DchanTuple dt;
Harald Welte96c94412017-12-09 03:12:45 +01001927
Harald Welte89d42e82017-12-17 16:42:41 +01001928 f_init(1);
Harald Welte96c94412017-12-09 03:12:45 +01001929
Harald Welte4003d112017-12-09 22:35:39 +01001930 dt := f_est_dchan('23'O, 23, '00010203040506'O);
1931
1932 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001933 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Harald Welte4003d112017-12-09 22:35:39 +01001934
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001935 /* expect Clear Request on MSC side */
1936 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
1937
1938 /* Instruct BSC to clear channel */
1939 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
1940 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
1941
Harald Welte4003d112017-12-09 22:35:39 +01001942 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001943 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001944
1945 /* wait for SCCP emulation to do its job */
1946 f_sleep(1.0);
Harald Welte4003d112017-12-09 22:35:39 +01001947
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001948 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001949}
1950
1951/* Test behavior of channel release after CONN FAIL IND from BTS */
1952testcase TC_chan_rel_conn_fail() runs on test_CT {
1953 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01001954 var DchanTuple dt;
1955
Harald Welte89d42e82017-12-17 16:42:41 +01001956 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001957
1958 dt := f_est_dchan('23'O, 23, '00010203040506'O);
1959
1960 /* simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001961 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte4003d112017-12-09 22:35:39 +01001962 /* TODO: different cause values? */
1963
Harald Welte4003d112017-12-09 22:35:39 +01001964 /* expect Clear Request from BSC */
1965 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
1966
1967 /* Instruct BSC to clear channel */
1968 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
1969 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
1970
Harald Welte6ff76ea2018-01-28 13:08:01 +01001971 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001972 f_exp_chan_rel_and_clear(dt);
Harald Welte4003d112017-12-09 22:35:39 +01001973
1974 /* wait for SCCP emulation to do its job */
1975 f_sleep(1.0);
1976
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001977 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001978}
1979
Harald Welte99f3ca02018-06-14 13:40:29 +02001980/* Test behavior of early CONN FAIL IND from BTS (before EST IND!) */
1981/* See also https://www.osmocom.org/issues/3182 */
1982testcase TC_early_conn_fail() runs on test_CT {
1983 var RSL_Message rx_rsl;
1984 var DchanTuple dt;
1985
1986 f_init(1);
1987
1988 /* BTS->BSC: Send CHAN RQD and wait for allocation; acknowledge it */
Harald Weltec46ea3c2020-10-10 18:46:12 +02001989 dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_ra_cs(), 23);
Harald Welte99f3ca02018-06-14 13:40:29 +02001990
1991 /* BTS->BSC: simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001992 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02001993
1994 /* BTS->BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001995 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02001996
1997 /* BTS<-BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001998 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02001999
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002000 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002001}
2002
2003/* Test behavior of late CONN FAIL IND from BTS (ater REL IND!) */
2004/* See also https://www.osmocom.org/issues/3182 */
2005testcase TC_late_conn_fail() runs on test_CT {
2006 var RSL_Message rx_rsl;
2007 var DchanTuple dt;
2008
2009 f_init(1);
2010
2011 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2012
2013 /* BSC<-MSC: Instruct BSC to clear connection */
2014 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(0)));
2015
2016 /* BTS->BSC: expect BSC to deactivate SACCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002017 rx_rsl := f_exp_ipa_rx(tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002018
2019 /* BTS->BSC: simulate a late CONN FAIL IND from BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002020 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002021
2022 /* BTS<-BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002023 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002024 /* BTS->BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002025 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002026
2027 /* BSC->MSC: expect Clear Complete from BSC */
2028 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2029
2030 /* BSC<-MSC: MSC disconnects as requested. */
2031 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2032
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002033 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002034}
2035
Oliver Smithaf03bef2021-08-24 15:34:51 +02002036private function f_TC_stats_conn_fail(charstring id) runs on MSC_ConnHdlr {
2037 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
2038 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2039
2040 f_statsd_reset();
2041
2042 /* Establish SDCCH */
2043 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
2044 f_establish_fully(ass_cmd, exp_fail);
2045
2046 /* Expect stats to be 0 */
2047 var StatsDExpects expect := {
2048 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
2049 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
2050 };
2051 f_statsd_expect(expect);
2052
2053 /* Simulate CONN FAIL IND on SDCCH */
2054 RSL.send(ts_ASP_RSL_UD(
2055 ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
2056 IPAC_PROTO_RSL_TRX0));
2057
Neels Hofmeyr58be48a2021-09-07 18:39:21 +02002058 f_sleep(1.0);
2059
Oliver Smithaf03bef2021-08-24 15:34:51 +02002060 /* Expect stats to be 1 */
2061 expect := {
2062 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
2063 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
2064 };
2065 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002066 BSSAP.receive(tr_BSSMAP_ClearRequest);
2067 f_perform_clear();
Oliver Smithaf03bef2021-08-24 15:34:51 +02002068}
2069testcase TC_stats_conn_fail() runs on test_CT {
2070 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2071 var MSC_ConnHdlr vc_conn;
2072
2073 f_init(1, true);
2074 f_sleep(1.0);
2075
2076 vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
2077 vc_conn.done;
2078
2079 f_shutdown_helper();
2080}
2081
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002082function f_expect_chan_rel(RslChannelNr rsl_chan_nr,
2083 BtsTrxIdx idx := {0, 0},
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002084 boolean expect_deact_sacch := true,
2085 boolean expect_rr_chan_rel := true,
2086 boolean expect_rll_rel_req := true,
Harald Welte99787102019-02-04 10:41:36 +01002087 boolean handle_rll_rel := true,
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002088 template CellSelIndValue expect_cells := omit,
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002089 template (present) RR_Cause expect_rr_cause := ?
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002090 ) runs on test_CT {
Harald Welte91d54a52018-01-28 15:35:07 +01002091
2092 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002093 var boolean got_deact_sacch := false;
2094 var boolean got_rr_chan_rel := false;
2095 var boolean got_rll_rel_req := false;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002096 var ASP_RSL_Unitdata ud;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002097 var RSL_IE_Body l3_ie;
2098 var PDU_ML3_NW_MS l3;
2099 var RR_Cause got_cause;
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002100 log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
2101 " expect_rll_rel_req=", expect_rll_rel_req);
Harald Welte91d54a52018-01-28 15:35:07 +01002102 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002103 [] 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 +01002104 got_deact_sacch := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002105 repeat;
2106 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002107 [] 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 +01002108 got_rr_chan_rel := true;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002109
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002110 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2111 setverdict(fail, "cannot find L3");
2112 mtc.stop;
2113 }
2114 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2115
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002116 if (not istemplatekind(expect_cells, "omit")) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002117 var CellSelIndValue cells := dec_CellSelIndValue(
2118 l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
2119
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002120 log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
2121 if (match(cells, expect_cells)) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002122 setverdict(pass);
2123 } else {
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002124 log("EXPECTED CELLS: ", expect_cells);
2125 setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002126 }
2127 }
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002128
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002129 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2130 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2131 if (match(got_cause, expect_rr_cause)) {
2132 setverdict(pass);
2133 } else {
2134 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2135 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002136 }
Harald Welte99787102019-02-04 10:41:36 +01002137 repeat;
2138 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002139 [] 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 +01002140 got_rll_rel_req := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002141 /* FIXME: Why are we getting this for LinkID SACCH? */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002142 if (handle_rll_rel) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002143 f_ipa_tx(ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002144 }
Harald Welte91d54a52018-01-28 15:35:07 +01002145 repeat;
2146 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002147 [] 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 +01002148 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002149 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
Harald Welte91d54a52018-01-28 15:35:07 +01002150 }
2151 /* ignore any user data */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002152 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002153 repeat;
2154 }
2155 }
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002156
2157 log("f_expect_chan_rel() summary: got_deact_sacch=", got_deact_sacch, " got_rr_chan_rel=", got_rr_chan_rel,
2158 " got_rll_rel_req=", got_rll_rel_req);
2159
2160 if (expect_deact_sacch != got_deact_sacch) {
2161 setverdict(fail, "f_expect_chan_rel(): expect_deact_sacch=", expect_deact_sacch, " got_deact_sacch=", got_deact_sacch);
2162 }
2163 if (expect_rr_chan_rel != got_rr_chan_rel) {
2164 setverdict(fail, "f_expect_chan_rel(): expect_rr_chan_rel=", expect_rr_chan_rel, " got_rr_chan_rel=", got_rr_chan_rel);
2165 }
2166 if (expect_rll_rel_req != got_rll_rel_req) {
2167 setverdict(fail, "f_expect_chan_rel(): expect_rll_rel_req=", expect_rll_rel_req, " got_rll_rel_req=", got_rll_rel_req);
2168 }
Harald Welte91d54a52018-01-28 15:35:07 +01002169}
2170
Harald Welte4003d112017-12-09 22:35:39 +01002171/* Test behavior of channel release after hard Clear Command from MSC */
2172testcase TC_chan_rel_hard_clear() runs on test_CT {
2173 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002174 var DchanTuple dt;
Harald Welte4003d112017-12-09 22:35:39 +01002175
Harald Welte89d42e82017-12-17 16:42:41 +01002176 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002177
2178 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2179
2180 /* Instruct BSC to clear channel */
2181 var BssmapCause cause := 0;
2182 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2183
2184 /* expect Clear Complete from BSC on A */
2185 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2186 /* release the SCCP connection */
2187 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2188 }
2189
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002190 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002191 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002192}
2193
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002194function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
2195 var BSSAP_N_DATA_ind rx_di;
2196 var DchanTuple dt;
2197
2198 f_init(1);
2199
2200 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2201 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2202 /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
2203 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
2204
2205 /* Instruct BSC to clear channel */
2206 var BssmapCause cause := 0;
2207 if (tx_csfb_ind) {
2208 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2209 } else {
2210 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2211 }
2212
2213 /* expect Clear Complete from BSC on A */
2214 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2215 /* release the SCCP connection */
2216 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2217 }
2218
2219 /* 1 neighbor is added by default in osmo-bts.cfg and
2220 SystemInformationConfig_default, use that: */
2221 var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
2222
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002223 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 +02002224 f_shutdown_helper();
2225}
2226
2227/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
2228 from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
2229 PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2230 EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
2231 Indicator or not shouldn't matter at all. */
2232testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
2233 f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
2234}
2235
2236/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
2237 MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
2238 Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2239 EUTRAN neighbor list sent later on by BSC in RR Channel. */
2240testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
2241 f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
2242}
2243
2244/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
2245 MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
2246 Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
2247 CSFB Indicator should not be used anymore, and hence, there should be no
2248 EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
2249 Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
Harald Welte99787102019-02-04 10:41:36 +01002250testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
2251 var BSSAP_N_DATA_ind rx_di;
2252 var DchanTuple dt;
2253
2254 f_init(1);
2255
2256 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2257
2258 /* Instruct BSC to clear channel */
2259 var BssmapCause cause := 0;
2260 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2261
2262 /* expect Clear Complete from BSC on A */
2263 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2264 /* release the SCCP connection */
2265 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2266 }
2267
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002268 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002269 f_shutdown_helper();
Harald Welte99787102019-02-04 10:41:36 +01002270}
2271
Harald Welted8c36cd2017-12-09 23:05:31 +01002272/* Test behavior of channel release after hard RLSD from MSC */
2273testcase TC_chan_rel_hard_rlsd() runs on test_CT {
Harald Welted8c36cd2017-12-09 23:05:31 +01002274 var DchanTuple dt;
Harald Welted8c36cd2017-12-09 23:05:31 +01002275
Harald Welte89d42e82017-12-17 16:42:41 +01002276 f_init(1);
Harald Welted8c36cd2017-12-09 23:05:31 +01002277
2278 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2279
2280 /* release the SCCP connection */
2281 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2282
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002283 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002284 f_shutdown_helper();
Harald Welted8c36cd2017-12-09 23:05:31 +01002285}
2286
Harald Welte550daf92018-06-11 19:22:13 +02002287/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
2288testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
2289 var DchanTuple dt;
2290
2291 f_init(1);
2292
2293 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2294
2295 /* release the SCCP connection */
2296 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2297
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002298 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002299 f_shutdown_helper();
Harald Welte550daf92018-06-11 19:22:13 +02002300}
2301
Harald Welte85804d42017-12-10 14:11:58 +01002302/* Test behavior of channel release after BSSMAP RESET from MSC */
2303testcase TC_chan_rel_a_reset() runs on test_CT {
Harald Welte85804d42017-12-10 14:11:58 +01002304 var DchanTuple dt;
Harald Welte85804d42017-12-10 14:11:58 +01002305
Harald Welte89d42e82017-12-17 16:42:41 +01002306 f_init(1);
Harald Welte85804d42017-12-10 14:11:58 +01002307
2308 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2309
2310 /* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002311 IPA_RSL[0][0].clear;
Harald Welte85804d42017-12-10 14:11:58 +01002312
2313 /* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002314 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 +01002315 interleave {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002316 [] 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 +01002317 [] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
2318 }
2319
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002320 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002321 f_shutdown_helper();
Harald Welte85804d42017-12-10 14:11:58 +01002322}
2323
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002324/* Verify T(iar) triggers and releases the channel */
2325testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
2326 var DchanTuple dt;
2327
2328 /* Set T(iar) in BSC low enough that it will trigger before other side
2329 has time to keep alive with a T(ias). Keep recommended ratio of
2330 T(iar) >= T(ias)*2 */
2331 g_bsc_sccp_timer_ias := 2;
2332 g_bsc_sccp_timer_iar := 5;
2333
2334 f_init(1);
2335
2336 dt := f_est_dchan('23'O, 23, '00010203040506'O);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002337 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002338 f_shutdown_helper();
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002339}
2340
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002341private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause,
2342 template (present) RR_Cause expect_rr_cause)
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002343runs on test_CT
2344{
2345 var DchanTuple dt;
2346
2347 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2348 var BssmapCause cause := 0;
2349 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
2350 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2351 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2352 }
2353
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002354 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 +02002355}
2356
2357/* Test that Clear Command cause codes affect the RR Channel Release cause code */
2358testcase TC_chan_rel_rr_cause() runs on test_CT {
2359 f_init(1);
2360
2361 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
2362 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
2363 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
2364 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
2365 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
2366 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
Vadim Yanitskiye18aebb2021-01-03 13:10:43 +01002367
2368 f_shutdown_helper();
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002369}
2370
Harald Welte5cd20ed2017-12-13 21:03:20 +01002371/* Test behavior if RSL EST IND for non-active channel */
2372testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
2373 timer T := 2.0;
2374
Harald Welte89d42e82017-12-17 16:42:41 +01002375 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002376
2377 var octetstring l3 := '00010203040506'O;
2378 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002379 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002380
2381 T.start;
2382 alt {
2383 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2384 setverdict(fail, "MSC received COMPL L3 for non-active lchan");
2385 }
2386 [] BSSAP.receive {}
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002387 [] IPA_RSL[0][0].receive {}
Harald Welte5cd20ed2017-12-13 21:03:20 +01002388 [] T.timeout {}
2389 }
2390
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002391 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002392}
2393
2394/* Test behavior if RSL EST IND for invalid SAPI */
2395testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
2396 var RslChannelNr chan_nr;
2397
Harald Welte89d42e82017-12-17 16:42:41 +01002398 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002399
2400 chan_nr := f_chreq_act_ack()
2401
2402 var octetstring l3 := '00010203040506'O;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002403 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002404
2405 timer T := 2.0;
2406 T.start;
2407 alt {
2408 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2409 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
2410 }
2411 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002412 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002413 [] T.timeout {}
2414 }
2415
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002416 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002417}
2418
2419/* Test behavior if RSL EST IND for invalid SAPI */
2420testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
2421 timer T := 2.0;
2422
Harald Welte89d42e82017-12-17 16:42:41 +01002423 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002424
2425 var RslChannelNr chan_nr := f_chreq_act_ack();
2426
2427 var octetstring l3 := '00010203040506'O;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002428 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002429
2430 T.start;
2431 alt {
2432 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2433 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
2434 }
2435 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002436 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002437 [] T.timeout {}
2438 }
2439
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002440 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002441}
2442
2443/* Test behavior if RSL EST IND for invalid SACCH */
2444testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
2445 timer T := 2.0;
2446
Harald Welte89d42e82017-12-17 16:42:41 +01002447 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002448
2449 var RslChannelNr chan_nr := f_chreq_act_ack();
2450
2451 var octetstring l3 := '00010203040506'O;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002452 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002453
2454 T.start;
2455 alt {
2456 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2457 setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
2458 }
2459 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002460 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002461 [] T.timeout {}
2462 }
2463
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002464 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002465}
2466
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002467/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
2468private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
2469 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
2470 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2471
2472 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
2473 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
2474
2475 f_establish_fully(ass_cmd, exp_compl);
2476
2477 /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
2478 RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
2479 /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
2480 BSSAP.receive(PDU_BSSAP:{
2481 discriminator := '1'B,
2482 spare := '0000000'B,
2483 dlci := 'C3'O,
2484 lengthIndicator := ?,
2485 pdu := { dtap := '0904'O }
2486 });
2487
2488 /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
2489 for (var integer i := 0; i < 32; i := i + 1) {
2490 var octetstring l3 := '09'O & f_rnd_octstring(14);
2491 var template (value) RslLinkId link_id;
2492 var template (value) OCT1 dlci;
2493
2494 if (i mod 2 == 0) {
2495 /* SAPI0 on FACCH or SDCCH */
2496 link_id := ts_RslLinkID_DCCH(0);
2497 dlci := '80'O;
2498 } else {
2499 /* SAPI3 on SACCH */
2500 link_id := ts_RslLinkID_SACCH(3);
2501 dlci := 'C3'O;
2502 }
2503
2504 /* Send MO message: RSL -> BSSAP */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002505 f_mo_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002506 /* Send MT message: BSSAP -> RSL */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002507 f_mt_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002508 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002509 f_perform_clear();
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002510}
2511testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
2512 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2513 var MSC_ConnHdlr vc_conn;
2514
2515 f_init(1, true);
2516 f_sleep(1.0);
2517
2518 vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
2519 vc_conn.done;
2520
2521 f_shutdown_helper();
2522}
2523
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002524private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002525 template (present) myBSSMAP_Cause cause := ?,
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002526 template (present) BIT2 cc := ?,
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002527 float T_val := 2.0)
2528runs on test_CT {
2529 var BSSAP_N_DATA_ind rx_di;
2530 timer T;
2531
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002532 var template (present) BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
2533 var template (present) PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002534
2535 T.start(T_val);
2536 alt {
2537 [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
2538 var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
2539 if (not match(rx_cause, tr_cause)) {
2540 setverdict(fail, "Rx unexpected Cause IE: ",
2541 rx_cause, " vs expected ", tr_cause);
2542 }
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002543
2544 /* Who ever on the earth decided to define this field as two separate bits?!? */
2545 var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
2546 & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
2547 if (not match(rx_cc, cc)) {
2548 setverdict(fail, "Rx unexpected Control Channel type: ",
2549 rx_cc, " vs expected ", cc);
2550 }
2551
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002552 setverdict(pass);
2553 }
2554 [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
2555 setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
2556 }
2557 [] T.timeout {
2558 setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
2559 }
2560 }
2561}
2562
2563/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
2564testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
2565 var octetstring rnd_data := f_rnd_octstring(16);
2566 var RSL_Message rx_rsl;
2567 var DchanTuple dt;
2568
2569 f_init(1);
2570
2571 /* MS establishes a SAPI=0 link on DCCH */
2572 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2573
2574 /* MSC sends some data on (not yet established) SAPI=3 link */
2575 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2576 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002577 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 +07002578
2579 /* MS sends unexpected RELease INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002580 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002581 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2582 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
2583
2584 /* Clean up the connection */
2585 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002586 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002587
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002588 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002589}
2590
2591/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
2592testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
2593 var octetstring rnd_data := f_rnd_octstring(16);
2594 var RSL_Message rx_rsl;
2595 var DchanTuple dt;
2596
2597 f_init(1);
2598
2599 /* MS establishes a SAPI=0 link on DCCH */
2600 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2601
2602 /* MSC sends some data on (not yet established) SAPI=3 link */
2603 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2604 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002605 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 +07002606
2607 /* BTS sends unexpected ERROR INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002608 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002609 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2610 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
2611
2612 /* Clean up the connection */
2613 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002614 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002615
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002616 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002617}
2618
2619/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
2620testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
2621 var octetstring rnd_data := f_rnd_octstring(16);
2622 var RSL_Message rx_rsl;
2623 var DchanTuple dt;
2624
2625 f_init(1);
2626
2627 /* MS establishes a SAPI=0 link on DCCH */
2628 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2629
2630 /* MSC sends some data on (not yet established) SAPI=3 link */
2631 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2632 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002633 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 +07002634
2635 /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
2636 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
2637
2638 /* Clean up the connection */
2639 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002640 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002641
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002642 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002643}
2644
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002645/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
2646testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
2647 var octetstring rnd_data := f_rnd_octstring(16);
2648 var RSL_Message rx_rsl;
2649 var DchanTuple dt;
2650
2651 f_init(1);
2652
2653 /* MS establishes a SAPI=0 link on DCCH */
2654 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2655
2656 /* MSC sends some data on (not yet established) SAPI=3 link */
2657 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2658 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002659 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 +07002660
2661 /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002662 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Pau Espin Pedrol121f27f2022-01-12 12:02:10 +01002663 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, '10'B);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002664
2665 /* Clean up the connection */
2666 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002667 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002668
2669 f_shutdown_helper();
2670}
2671
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002672testcase TC_si_default() runs on test_CT {
2673 f_init(0);
2674 f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002675 f_shutdown_helper();
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002676}
Harald Welte4003d112017-12-09 22:35:39 +01002677
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002678/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
2679 * the entire value range. This function provides the same EARFCN numbers for the same earfcn_index */
2680private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uint16_t
2681{
2682 select (earfcn_index) {
2683 case (0) {
2684 /* E-ARFCN 111 is already added in the osmo-bsc.cfg */
2685 return 111;
2686 }
2687 case (1) {
2688 return 1;
2689 }
2690 case (2) {
2691 return 0;
2692 }
2693 case (3) {
2694 return 65535;
2695 }
2696 case else {
2697 return 23 * (earfcn_index - 3);
2698 }
2699 }
2700}
2701
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002702function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
2703 template CellSelIndValue expect_cells := omit) runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002704
2705 f_init(0);
2706
2707 /* E-ARFCN 111 is already added in the osmo-bsc.cfg, so only add more arfcns if total_earfcns > 1 */
2708 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002709 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2710 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002711 }
2712
2713 f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
2714
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002715 if (not istemplatekind(expect_cells, "omit")) {
2716 /* Also check that RR Channel Release contains these EARFCNs.
2717 * (copied code from TC_chan_rel_hard_clear_csfb) */
2718 var BSSAP_N_DATA_ind rx_di;
2719 var DchanTuple dt;
2720
2721 dt := f_est_dchan('23'O, 23, '00010203040506'O);
Pau Espin Pedrold0046312021-04-19 16:35:58 +02002722 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2723 * yet when generating the EUTRAN neigh list in RR CHannel Release) */
2724 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002725
2726 /* Instruct BSC to clear channel */
2727 var BssmapCause cause := 0;
2728 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2729
2730 /* expect Clear Complete from BSC on A */
2731 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2732 /* release the SCCP connection */
2733 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2734 }
2735
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002736 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := expect_cells);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002737 }
2738
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002739 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002740 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 +02002741 }
2742}
2743
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002744private function f_tr_si2quater_earfcns(integer count) return template SI2quaterRestOctetsList
2745{
2746 var template SI2quaterRestOctetsList si2quater := {};
2747 var integer si2quater_count := (count + 2) / 3;
2748
2749 for (var integer i := 0; i < count; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002750 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002751 var integer index := i / 3;
2752 var integer earfcn_index := i mod 3;
2753 if (index >= lengthof(si2quater)) {
2754 si2quater[index] := tr_SI2quaterRestOctets_EUTRAN(index := index, count := si2quater_count - 1);
2755 }
2756 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);
2757 }
2758
2759 return si2quater;
2760}
2761
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002762private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
2763{
2764 var template CellSelIndValue_EUTRAN_Descrs cells := {};
2765
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002766 /* the lte neighbors must match the config & vty to pass this test */
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002767 for (var integer i := 0; i < count; i := i + 1) {
2768 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002769 cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002770 }
2771
2772 return tr_CellSelIndValue_EUTRAN(cells);
2773}
2774
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002775private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
2776{
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002777 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrol8ab62e42020-12-18 16:19:11 +01002778 sic.si2quater := f_tr_si2quater_earfcns(n);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002779 var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
2780 f_test_si2quater(n, sic, cells);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002781}
2782
2783testcase TC_si2quater_2_earfcns() runs on test_CT {
2784 f_tc_si2quater_n_earfcns(2);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002785 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002786}
2787
2788testcase TC_si2quater_3_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002789 f_tc_si2quater_n_earfcns(3);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002790 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002791}
2792
2793testcase TC_si2quater_4_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002794 f_tc_si2quater_n_earfcns(4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002795 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002796}
2797
2798testcase TC_si2quater_5_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002799 f_tc_si2quater_n_earfcns(5);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002800 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002801}
2802
2803testcase TC_si2quater_6_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002804 f_tc_si2quater_n_earfcns(6);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002805 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002806}
2807
2808testcase TC_si2quater_12_earfcns() runs on test_CT {
2809 f_tc_si2quater_n_earfcns(12);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002810 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002811}
2812
2813testcase TC_si2quater_23_earfcns() runs on test_CT {
2814 f_tc_si2quater_n_earfcns(23);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002815 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002816}
2817
2818testcase TC_si2quater_32_earfcns() runs on test_CT {
2819 f_tc_si2quater_n_earfcns(32);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002820 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002821}
2822
2823testcase TC_si2quater_33_earfcns() runs on test_CT {
2824 f_tc_si2quater_n_earfcns(33);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002825 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002826}
2827
2828testcase TC_si2quater_42_earfcns() runs on test_CT {
2829 f_tc_si2quater_n_earfcns(42);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002830 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002831}
2832
2833testcase TC_si2quater_48_earfcns() runs on test_CT {
2834 f_tc_si2quater_n_earfcns(48);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002835 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002836}
2837
2838/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
2839 * 48 EARFCNs. */
2840testcase TC_si2quater_49_earfcns() runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002841 var template SystemInformationConfig sic := SystemInformationConfig_default;
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002842 sic.si2quater := f_tr_si2quater_earfcns(48); /* 48, not 49! */
2843 f_init(0);
2844
2845 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002846 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2847 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002848 }
2849
2850 /* The 49th EARFCN no longer fits, expect VTY error */
2851 f_vty_enter_cfg_bts(BSCVTY, 0);
2852 var charstring vty_error;
2853 vty_error := f_vty_transceive_ret(BSCVTY,
2854 "si2quater neighbor-list add earfcn 70 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3")
2855 f_vty_transceive(BSCVTY, "end");
2856
2857 if (f_strstr(vty_error, "Unable to add ARFCN 70") >= 0) {
2858 log("Got expected VTY error: ", vty_error);
2859 setverdict(pass);
2860 } else {
2861 setverdict(fail, "Expected the 49th EUTRAN ARFCN to be rejected by vty config, got: ", vty_error);
2862 }
2863
2864 f_init_bts_and_check_sysinfo(0, expect_si := sic);
2865
2866 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002867 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 +02002868 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002869 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002870}
2871
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002872private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
2873{
2874 var uint8_t count := 0;
2875 for (var integer i := 5; i < 16; i := i + 1) {
2876 if (acc[i] == '0'B) { /* the list marks barred, we count allowed */
2877 count := count + 1;
2878 }
2879 }
2880 return count;
2881}
2882
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002883private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return SystemInformationType1
2884{
2885 var ASP_RSL_Unitdata rx_rsl_ud;
2886 var SystemInformationType1 last_si1;
2887
2888 timer T := 30.0;
2889 T.start;
2890 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002891 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
2892 tr_RSL_BCCH_INFO,
2893 tr_RSL_NO_SACCH_FILL,
2894 tr_RSL_SACCH_FILL))) -> value rx_rsl_ud {
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002895 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
2896 if (g_system_information[rsl_idx].si1 == omit) {
2897 repeat;
2898 }
2899 last_si1 := g_system_information[rsl_idx].si1;
2900 g_system_information[rsl_idx].si1 := omit;
2901 T.stop;
2902 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002903 [] IPA_RSL[rsl_idx][0].receive { repeat; }
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002904 [] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
2905 }
2906 return last_si1;
2907}
2908
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002909/* verify ACC rotate feature */
2910testcase TC_si_acc_rotate() runs on test_CT {
2911 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002912 var SystemInformationType1 last_si1;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002913 var AccessControlClass acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002914 var uint8_t count;
2915 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2916
2917 f_init(0, guard_timeout := 60.0);
2918
2919 f_bts_0_cfg(BSCVTY, {"rach access-control-class 5 barred",
2920 "access-control-class-rotate 3",
2921 "access-control-class-rotate-quantum 1"});
2922
2923 /* Init and get first sysinfo */
2924 f_init_bts_and_check_sysinfo(0, expect_si := ?);
2925
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002926 for (var integer i:= 0; i < 20; i := i + 1) {
2927 last_si1 := f_recv_next_si1(0);
2928 acc := last_si1.rach_control.acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002929 count := f_acc09_count_allowed(acc);
2930 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
2931
2932 if (count != 3) {
2933 log("RSL: EXPECTED SI ACC len=3");
2934 setverdict(fail, "received SI does not match expectations");
2935 break;
2936 }
2937
2938 for (var integer j := 0; j < 10; j := j + 1) {
2939 if (acc[16 - 1 - j] == '0'B) { /* the list marks barred, we count allowed */
2940 times_allowed[j] := times_allowed[j] + 1;
2941 }
2942 }
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002943 }
2944
2945 for (var integer j := 0; j < 10; j := j + 1) {
2946 log("ACC", j, " allowed ", times_allowed[j], " times" );
2947 if (j != 5 and times_allowed[j] < 3) {
2948 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " < 1 times");
2949 } else if (j == 5 and times_allowed[j] > 0) {
2950 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " > 0 times");
2951 }
2952 }
2953
2954 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
2955 "rach access-control-class 5 allowed"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002956 f_shutdown_helper();
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002957}
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002958
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002959/* verify ACC startup ramp+rotate feature */
2960testcase TC_si_acc_ramp_rotate() runs on test_CT {
2961 var template SystemInformationConfig sic := SystemInformationConfig_default;
2962 var SystemInformationType1 last_si1;
2963 var AccessControlClass acc;
2964 var ASP_RSL_Unitdata rx_rsl_ud;
2965 var uint8_t count;
2966 var uint8_t prev_count;
2967 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2968
2969 f_init(0, guard_timeout := 80.0);
2970
2971 f_bts_0_cfg(BSCVTY, {"rach access-control-class 4 barred",
2972 "access-control-class-rotate 0",
2973 "access-control-class-rotate-quantum 1",
2974 "access-control-class-ramping",
2975 "access-control-class-ramping-step-interval 5",
2976 "access-control-class-ramping-step-size 5"});
2977
2978 /* Init and get first sysinfo */
2979 f_init_bts_and_check_sysinfo(0, expect_si := ?);
2980 last_si1 := g_system_information[0].si1;
2981 acc := last_si1.rach_control.acc;
2982 count := f_acc09_count_allowed(acc);
2983 /* Adm subset size was set to 0 above, so wait until all ACC are barred */
2984 while (count > 0) {
2985 last_si1 := f_recv_next_si1(0);
2986 acc := last_si1.rach_control.acc;
2987 count := f_acc09_count_allowed(acc);
2988 log("RSL: wait len()=0: GOT SI1 ACC len=", count, ": ", acc);
2989 }
2990
2991 /* Increase adm subset size, we should see ramping start up */
2992 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10"});
2993 prev_count := 0;
2994 while (true) {
2995 last_si1 := f_recv_next_si1(0);
2996 acc := last_si1.rach_control.acc;
2997 count := f_acc09_count_allowed(acc);
2998 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
2999
3000 if (prev_count > count) {
3001 setverdict(fail, "ACC allowed count dropped while expecting grow: ", prev_count, " -> ", count);
3002 break;
3003 }
3004
3005 if (count == 9) {
3006 break; /* Maximum reached (10 - 1 perm barred), done here */
3007 }
3008
3009 prev_count := count;
3010 }
3011
3012 setverdict(pass);
3013
3014 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3015 "rach access-control-class 4 allowed",
3016 "no access-control-class-ramping"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003017 f_shutdown_helper();
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003018}
3019
Harald Welte4003d112017-12-09 22:35:39 +01003020testcase TC_ctrl_msc_connection_status() runs on test_CT {
3021 var charstring ctrl_resp;
3022
Harald Welte89d42e82017-12-17 16:42:41 +01003023 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003024
3025 /* See https://osmocom.org/issues/2729 */
3026 f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003027 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01003028}
3029
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003030testcase TC_ctrl_msc0_connection_status() runs on test_CT {
3031 var charstring ctrl_resp;
3032
3033 f_init(1);
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003034
3035 f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003036 f_shutdown_helper();
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003037}
3038
Neels Hofmeyr0bc470d2021-08-21 13:37:13 +02003039/* Verify correct stats on the number of configured and connected MSCs */
3040private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
3041 g_pars := f_gen_test_hdlr_pars();
3042 var StatsDExpects expect := {
3043 { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
3044 { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
3045 };
3046 f_statsd_expect(expect);
3047}
3048
3049private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
3050{
3051 var MSC_ConnHdlr vc_conn;
3052
3053 f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
3054 f_sleep(1.0);
3055 vc_conn := f_start_handler(tc_fn);
3056 vc_conn.done;
3057
3058 /* Also verify stat exposed on CTRL interface */
3059 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
3060 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
3061
3062 f_shutdown_helper();
3063}
3064
3065/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
3066private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
3067 f_tc_stat_num_msc_connected_msc_connhdlr(1);
3068}
3069testcase TC_stat_num_msc_connected_1() runs on test_CT {
3070 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
3071}
3072
3073/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
3074private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
3075 f_tc_stat_num_msc_connected_msc_connhdlr(2);
3076}
3077testcase TC_stat_num_msc_connected_2() runs on test_CT {
3078 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
3079}
3080
3081/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
3082private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
3083 f_tc_stat_num_msc_connected_msc_connhdlr(3);
3084}
3085testcase TC_stat_num_msc_connected_3() runs on test_CT {
3086 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
3087}
3088
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003089/* Verify correct stats on the number of configured and connected MSCs */
3090private 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 +06003091 var integer num_trx_connected := 0;
3092 var integer num_trx_total := 0;
3093
3094 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3095 var integer trx_num := c_BtsParams[i].trx_num;
3096 num_trx_total := num_trx_total + trx_num;
3097 if (i < expect_num_bts_connected) {
3098 num_trx_connected := num_trx_connected + trx_num;
3099 }
3100 }
3101
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003102 var StatsDExpects expect := {
3103 { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
3104 { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3105 { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003106 { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := num_trx_connected, max := num_trx_connected },
3107 { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := num_trx_total, max := num_trx_total }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003108 };
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003109
3110 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003111 f_statsd_expect(expect);
3112}
3113
3114private 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 +06003115 var integer num_trx_connected := 0;
3116 var integer num_trx_total := 0;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003117 var MSC_ConnHdlr vc_conn;
3118
3119 f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
3120 f_sleep(1.0);
3121 vc_conn := f_start_handler(tc_fn);
3122 vc_conn.done;
3123
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003124 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3125 var integer trx_num := c_BtsParams[i].trx_num;
3126 num_trx_total := num_trx_total + trx_num;
3127 if (i < nr_bts) {
3128 num_trx_connected := num_trx_connected + trx_num;
3129 }
3130 }
3131
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003132 /* Also verify stat exposed on CTRL interface */
3133 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
3134 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 +06003135 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(num_trx_connected));
3136 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 +02003137
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003138 /* Verify rf_states exposed on CTRL interface */
3139 var charstring expect_net_rf_states := "";
3140 for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003141 var charstring expect_bts_rf_states := "";
3142
3143 for (var integer j := 0; j < c_BtsParams[i].trx_num; j := j + 1) {
3144 expect_bts_rf_states := expect_bts_rf_states &
3145 int2str(i) & "," & int2str(j) & ",";
3146 if (i < NUM_BTS) {
3147 /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
3148 expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
3149 } else {
3150 /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
3151 expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
3152 }
3153 /* The RF policy is still global in osmo-bsc, i.e. always "on" */
3154 expect_bts_rf_states := expect_bts_rf_states & "on,";
3155 if (i < nr_bts) {
3156 /* For BTS where RSL is connected, the RSL state will be "up" */
3157 expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
3158 } else {
3159 expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
3160 }
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003161 }
3162
3163 f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
3164 expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
3165 }
3166 f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
3167
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003168 f_shutdown_helper();
3169}
3170
3171/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
3172private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
3173 f_tc_stat_num_bts_connected_msc_connhdlr(1);
3174}
3175testcase TC_stat_num_bts_connected_1() runs on test_CT {
3176 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
3177}
3178
3179/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
3180private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
3181 f_tc_stat_num_bts_connected_msc_connhdlr(2);
3182}
3183testcase TC_stat_num_bts_connected_2() runs on test_CT {
3184 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
3185}
3186
3187/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
3188private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
3189 f_tc_stat_num_bts_connected_msc_connhdlr(3);
3190}
3191testcase TC_stat_num_bts_connected_3() runs on test_CT {
3192 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
3193}
3194
Harald Welte4003d112017-12-09 22:35:39 +01003195testcase TC_ctrl() runs on test_CT {
3196 var charstring ctrl_resp;
3197
Harald Welte89d42e82017-12-17 16:42:41 +01003198 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003199
3200 /* all below values must match the osmo-bsc.cfg config file used */
3201
Harald Welte6a129692018-03-17 17:30:14 +01003202 f_ctrl_get_exp(IPA_CTRL, "mcc", "001");
3203 f_ctrl_get_exp(IPA_CTRL, "mnc", "01");
Oliver Smith75aa0202019-08-19 14:17:50 +02003204 f_ctrl_get_exp(IPA_CTRL, "number-of-bts", "4");
Harald Welte4003d112017-12-09 22:35:39 +01003205
3206 var integer bts_nr := 0;
3207 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "location-area-code", "1");
3208 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "cell-identity", "0");
3209 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "oml-connection-state", "connected");
3210 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "gprs-mode", "gprs");
3211 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "rf_state", "operational,unlocked,on");
3212 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "arfcn", "871");
3213 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "max-power-reduction", "20");
3214
3215 var integer uptime := str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime"));
3216 f_sleep(2.0);
3217 if (str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime")) < uptime+1) {
3218 setverdict(fail, "oml-uptime not incrementing as expected");
3219 }
3220 /* TODO: Disconnect RSL, imply that OML is disconnected and check for uptime zero? */
3221
3222 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
3223
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003224 f_shutdown_helper();
Harald Welte96c94412017-12-09 03:12:45 +01003225}
3226
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003227/* Verify that Upon receival of SET "location", BSC forwards a TRAP
3228 "location-state" over the SCCPlite IPA conn */
3229testcase TC_ctrl_location() runs on test_CT {
3230 var MSC_ConnHdlr vc_conn;
3231 var integer bts_nr := 0;
3232
3233 f_init(1, true);
3234 f_sleep(1.0);
3235
3236 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234567,fix3d,0.340000,0.560000,0.780000");
3237 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3238 "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
3239
3240 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "1");
3241 f_sleep(2.0);
3242
3243 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234888,fix3d,0.350000,0.570000,0.790000");
3244 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3245 "1234888,fix3d,0.350000,0.570000,0.790000,operational,locked,off,001,01");
3246
3247 /* should match the one from config */
3248 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
3249
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003250 f_shutdown_helper();
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003251}
3252
Harald Welte6f521d82017-12-11 19:52:02 +01003253
3254/***********************************************************************
3255 * Paging Testing
3256 ***********************************************************************/
3257
3258type record Cell_Identity {
3259 GsmMcc mcc,
3260 GsmMnc mnc,
3261 GsmLac lac,
3262 GsmCellId ci
3263};
Harald Welte24135bd2018-03-17 19:27:53 +01003264private const Cell_Identity cid := { '001'H, '01'H, 1, 0 };
Stefan Sperling049a86e2018-03-20 15:51:00 +01003265private const Cell_Identity unknown_cid := { '678'H, 'f90'H, 1, 0 };
Harald Welte6f521d82017-12-11 19:52:02 +01003266
Harald Welte5d1a2202017-12-13 19:51:29 +01003267type set of integer BtsIdList;
3268
3269private function f_bts_in_list(integer bts_id, BtsIdList bts_ids) return boolean {
3270 for (var integer j := 0; j < sizeof(bts_ids); j := j + 1) {
3271 if (bts_id == bts_ids[j]) {
3272 return true;
3273 }
3274 }
3275 return false;
3276}
Harald Welte6f521d82017-12-11 19:52:02 +01003277
3278/* core paging test helper function; used by most paging test cases */
3279private function f_pageing_helper(hexstring imsi,
3280 template BSSMAP_FIELD_CellIdentificationList cid_list,
Harald Welte5d1a2202017-12-13 19:51:29 +01003281 BtsIdList bts_ids := { 0 },
Harald Welte6f521d82017-12-11 19:52:02 +01003282 template RSL_ChanNeeded rsl_chneed := omit,
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003283 template (omit) OCT4 tmsi := omit) runs on test_CT
Harald Welte6f521d82017-12-11 19:52:02 +01003284{
3285 var template BSSMAP_IE_ChannelNeeded bssmap_chneed;
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003286 var template MobileIdentityV mi;
Harald Welte6f521d82017-12-11 19:52:02 +01003287 var RSL_Message rx_rsl;
3288 var integer paging_group := hex2int(imsi[lengthof(imsi)-1]);
Harald Welte5d1a2202017-12-13 19:51:29 +01003289 var integer i;
Harald Welte6f521d82017-12-11 19:52:02 +01003290
3291 f_init();
Harald Welte6f521d82017-12-11 19:52:02 +01003292
3293 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Harald Weltec3068592018-03-17 19:55:31 +01003294 for (i := 0; i < NUM_BTS; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003295 IPA_RSL[i][0].clear;
Harald Welte5d1a2202017-12-13 19:51:29 +01003296 }
Harald Welte6f521d82017-12-11 19:52:02 +01003297
3298 if (isvalue(rsl_chneed)) {
3299 /* The values of 08.08 3.2.2.36 and 08.58 9.3.40 are luckily identical */
3300 bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
3301 } else {
3302 bssmap_chneed := omit;
3303 }
3304
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003305 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
3306 ts_BSSMAP_Paging(imsi, cid_list, tmsi, bssmap_chneed)));
Harald Welte6f521d82017-12-11 19:52:02 +01003307
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003308 if (not istemplatekind(tmsi, "omit")) {
3309 mi := t_MI_TMSI(tmsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003310 } else {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003311 mi := tr_MI_IMSI(imsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003312 }
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003313
Harald Welte5d1a2202017-12-13 19:51:29 +01003314 for (i := 0; i < sizeof(bts_ids); i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003315 rx_rsl := f_exp_ipa_rx(tr_RSL_PAGING_CMD(mi), idx := {bts_ids[i], 0});
Harald Welte5d1a2202017-12-13 19:51:29 +01003316 /* check channel type, paging group */
3317 if (rx_rsl.ies[1].body.paging_group != paging_group) {
3318 setverdict(fail, "Paging for wrong paging group");
3319 }
3320 if (ispresent(rsl_chneed) and
3321 rx_rsl.ies[3].body.chan_needed.chan_needed != valueof(rsl_chneed)) {
3322 setverdict(fail, "RSL Channel Needed != BSSMAP Channel Needed");
3323 }
Harald Welte6f521d82017-12-11 19:52:02 +01003324 }
Harald Welte2fccd982018-01-31 15:48:19 +01003325 f_sleep(2.0);
Harald Welte5d1a2202017-12-13 19:51:29 +01003326 /* do a quick check on all not-included BTSs if they received paging */
3327 for (i := 0; i < NUM_BTS; i := i + 1) {
3328 timer T := 0.1;
3329 if (f_bts_in_list(i, bts_ids)) {
3330 continue;
3331 }
3332 T.start;
3333 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003334 [] IPA_RSL[i][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003335 setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
3336 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003337 [] IPA_RSL[i][0].receive { repeat; }
Harald Welte5d1a2202017-12-13 19:51:29 +01003338 [] T.timeout { }
3339 }
Harald Welte6f521d82017-12-11 19:52:02 +01003340 }
3341
3342 setverdict(pass);
3343}
3344
Harald Welte5d1a2202017-12-13 19:51:29 +01003345const BtsIdList c_BtsId_all := { 0, 1, 2 };
Harald Welte751d3eb2018-01-31 15:51:06 +01003346const BtsIdList c_BtsId_none := { };
Harald Welte5d1a2202017-12-13 19:51:29 +01003347const BtsIdList c_BtsId_LAC1 := { 0, 1 };
3348const BtsIdList c_BtsId_LAC2 := { 2 };
3349
Harald Welte6f521d82017-12-11 19:52:02 +01003350/* PAGING by IMSI + TMSI */
3351testcase TC_paging_imsi_nochan() runs on test_CT {
3352 var BSSMAP_FIELD_CellIdentificationList cid_list;
3353 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Philipp Maier8c04b0a2018-02-23 13:48:48 +01003354 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, omit);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003355 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003356}
3357
3358/* PAGING by IMSI + TMSI */
3359testcase TC_paging_tmsi_nochan() runs on test_CT {
3360 var BSSMAP_FIELD_CellIdentificationList cid_list;
3361 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003362 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, 'A1B2C301'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003363 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003364}
3365
3366/* Paging with different "channel needed' values */
3367testcase TC_paging_tmsi_any() runs on test_CT {
3368 var BSSMAP_FIELD_CellIdentificationList cid_list;
3369 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003370 f_pageing_helper('001010100000002'H, cid_list, c_BtsId_all, RSL_CHANNEED_ANY, 'A1B2C302'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003371 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003372}
3373testcase TC_paging_tmsi_sdcch() runs on test_CT {
3374 var BSSMAP_FIELD_CellIdentificationList cid_list;
3375 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003376 f_pageing_helper('001010100000003'H, cid_list, c_BtsId_all, RSL_CHANNEED_SDCCH, 'A1B2C303'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003377 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003378}
3379testcase TC_paging_tmsi_tch_f() runs on test_CT {
3380 var BSSMAP_FIELD_CellIdentificationList cid_list;
3381 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003382 f_pageing_helper('001010000000004'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_F, 'A1B2C304'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003383 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003384}
3385testcase TC_paging_tmsi_tch_hf() runs on test_CT {
3386 var BSSMAP_FIELD_CellIdentificationList cid_list;
3387 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003388 f_pageing_helper('001010000000005'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_ForH, 'A1B2C305'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003389 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003390}
3391
3392/* Paging by CGI */
3393testcase TC_paging_imsi_nochan_cgi() runs on test_CT {
3394 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3395 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(cid.mcc, cid.mnc, cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003396 f_pageing_helper('001010000000006'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003397 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003398}
3399
3400/* Paging by LAC+CI */
3401testcase TC_paging_imsi_nochan_lac_ci() runs on test_CT {
3402 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3403 cid_list := { cIl_LAC_CI := { ts_BSSMAP_CI_LAC_CI(cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003404 f_pageing_helper('001010000000007'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003405 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003406}
3407
3408/* Paging by CI */
3409testcase TC_paging_imsi_nochan_ci() runs on test_CT {
3410 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3411 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003412 f_pageing_helper('001010000000008'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003413 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003414}
3415
3416/* Paging by LAI */
3417testcase TC_paging_imsi_nochan_lai() runs on test_CT {
3418 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3419 cid_list := { cIl_LAI := { ts_BSSMAP_CI_LAI(cid.mcc, cid.mnc, cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003420 f_pageing_helper('001010000000009'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003421 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003422}
3423
3424/* Paging by LAC */
3425testcase TC_paging_imsi_nochan_lac() runs on test_CT {
3426 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3427 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003428 f_pageing_helper('001010000000010'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003429 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003430}
3431
3432/* Paging by "all in BSS" */
3433testcase TC_paging_imsi_nochan_all() runs on test_CT {
3434 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3435 cid_list := { cIl_allInBSS := ''O };
Harald Welte5d1a2202017-12-13 19:51:29 +01003436 f_pageing_helper('001010000000011'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003437 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003438}
3439
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003440/* Paging by PLMN+LAC+RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003441testcase TC_paging_imsi_nochan_plmn_lac_rnc() runs on test_CT {
3442 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3443 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 +01003444 f_pageing_helper('001010000000012'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003445 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003446}
Harald Welte6f521d82017-12-11 19:52:02 +01003447
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003448/* Paging by RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003449testcase TC_paging_imsi_nochan_rnc() runs on test_CT {
3450 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3451 cid_list := { cIl_RNC := { int2oct(13, 2) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003452 f_pageing_helper('001010000000013'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003453 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003454}
3455
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003456/* Paging by LAC+RNC; We do not implement; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003457testcase TC_paging_imsi_nochan_lac_rnc() runs on test_CT {
3458 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3459 cid_list := { cIl_LAC_RNC := { ts_BSSMAP_CI_LAC_RNC(cid.lac, 14) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003460 f_pageing_helper('001010000000014'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003461 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003462}
3463
Harald Welte6f521d82017-12-11 19:52:02 +01003464/* Paging on multiple cells (multiple entries in list): Verify all of them page */
Harald Welte751d3eb2018-01-31 15:51:06 +01003465testcase TC_paging_imsi_nochan_lacs() runs on test_CT {
3466 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3467 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(1), ts_BSSMAP_CI_LAC(2) } };
3468 f_pageing_helper('001010000000015'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003469 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003470}
3471
3472/* Paging on empty list: Verify none of them page */
3473testcase TC_paging_imsi_nochan_lacs_empty() runs on test_CT {
3474 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3475 cid_list := { cIl_LAC := { } };
3476 f_pageing_helper('001010000000016'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003477 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003478}
3479
Stefan Sperling049a86e2018-03-20 15:51:00 +01003480/* Paging by CGI with unknown MCC/MNC: Verify nothing is paged. */
3481testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
3482 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3483 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(unknown_cid.mcc, unknown_cid.mnc, unknown_cid.lac, unknown_cid.ci) } };
3484 f_pageing_helper('001010000000006'H, cid_list, c_BtsId_none);
3485 f_shutdown_helper();
3486}
3487
Harald Welte6f521d82017-12-11 19:52:02 +01003488/* Verify paging retransmission interval + count */
3489/* Verify paging stops after channel establishment */
Harald Welte6f521d82017-12-11 19:52:02 +01003490/* Test behavior under paging overload */
Harald Welteae026692017-12-09 01:03:01 +01003491
Harald Weltee65d40e2017-12-13 00:09:06 +01003492/* Verify PCH load */
3493testcase TC_paging_imsi_load() runs on test_CT {
3494 var BSSMAP_FIELD_CellIdentificationList cid_list;
3495 timer T := 4.0;
Harald Welte2caa1062018-03-17 18:19:05 +01003496 timer T_retrans := 1.0;
Harald Weltee65d40e2017-12-13 00:09:06 +01003497 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003498 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Weltee65d40e2017-12-13 00:09:06 +01003499
3500 /* tell BSC there is no paging space anymore */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003501 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte3b57ab52018-03-17 18:01:10 +01003502 f_sleep(0.2);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003503 IPA_RSL[0][0].clear;
Harald Weltee65d40e2017-12-13 00:09:06 +01003504
3505 /* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
3506 * there would be 8 retransmissions during 4 seconds */
3507 T.start;
Harald Welte2caa1062018-03-17 18:19:05 +01003508 T_retrans.start;
Harald Weltee65d40e2017-12-13 00:09:06 +01003509 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003510 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Weltee65d40e2017-12-13 00:09:06 +01003511 setverdict(fail, "Received PAGING after LOAD_IND(0)");
Daniel Willmannafce8662018-07-06 23:11:32 +02003512 mtc.stop;
Harald Weltee65d40e2017-12-13 00:09:06 +01003513 }
Harald Welte2caa1062018-03-17 18:19:05 +01003514 [] T_retrans.timeout {
3515 /* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003516 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte2caa1062018-03-17 18:19:05 +01003517 T_retrans.start;
3518 repeat;
3519 }
Harald Weltee65d40e2017-12-13 00:09:06 +01003520 [] T.timeout {
3521 setverdict(pass);
3522 }
3523 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003524
3525 f_shutdown_helper();
Harald Weltee65d40e2017-12-13 00:09:06 +01003526}
3527
Harald Welte235ebf12017-12-15 14:18:16 +01003528/* Verify Paging Counter */
Harald Welte1ff69992017-12-14 12:31:17 +01003529testcase TC_paging_counter() runs on test_CT {
3530 var BSSMAP_FIELD_CellIdentificationList cid_list;
3531 timer T := 4.0;
3532 var integer i;
3533 var integer paging_attempted_bsc;
3534 var integer paging_attempted_bts[NUM_BTS];
Oliver Smith8b343d32021-11-26 13:01:42 +01003535 var integer paging_expired_bsc;
Harald Welte1ff69992017-12-14 12:31:17 +01003536 var integer paging_expired_bts[NUM_BTS];
3537 cid_list := valueof(ts_BSSMAP_CIL_noCell);
3538
3539 f_init();
3540
3541 /* read counters before paging */
3542 paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
Oliver Smith8b343d32021-11-26 13:01:42 +01003543 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.8.0 */
3544 paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
3545 }
Harald Welte1ff69992017-12-14 12:31:17 +01003546 for (i := 0; i < NUM_BTS; i := i+1) {
3547 paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
3548 paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
3549 }
3550
3551 f_pageing_helper('001230000000001'H, cid_list, c_BtsId_all);
3552
3553 /* expect the attempted pages on BSC and each BTSs to have incremented by one */
3554 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", paging_attempted_bsc+1);
3555 for (i := 0; i < NUM_BTS; i := i+1) {
3556 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted",
3557 paging_attempted_bts[i]+1);
3558 }
3559
3560 /* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
3561 f_sleep(12.0);
Oliver Smith8b343d32021-11-26 13:01:42 +01003562 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.8.0 */
3563 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
3564 }
Harald Welte1ff69992017-12-14 12:31:17 +01003565 for (i := 0; i < NUM_BTS; i := i+1) {
3566 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
3567 paging_expired_bts[i]+1);
3568 }
Harald Welte1ff69992017-12-14 12:31:17 +01003569
Philipp Maier282ca4b2018-02-27 17:17:00 +01003570 f_shutdown_helper();
Harald Welte1ff69992017-12-14 12:31:17 +01003571}
3572
3573
Harald Welte10985002017-12-12 09:29:15 +01003574/* Verify paging stops after A-RESET */
3575testcase TC_paging_imsi_a_reset() runs on test_CT {
3576 var BSSMAP_FIELD_CellIdentificationList cid_list;
3577 timer T := 3.0;
3578 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003579 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Welte10985002017-12-12 09:29:15 +01003580
3581 /* Perform a BSSMAP Reset and wait for ACK */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003582 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 +01003583 alt {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003584 [] 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 +01003585 [] BSSAP.receive { repeat; }
3586 }
3587
Daniel Willmanncbef3982018-07-30 09:22:40 +02003588 /* Wait to avoid a possible race condition if a paging message is
3589 * received right before the reset ACK. */
3590 f_sleep(0.2);
3591
Harald Welte10985002017-12-12 09:29:15 +01003592 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Philipp Maier1e6b4422018-02-23 14:02:13 +01003593 for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003594 IPA_RSL[i][0].clear;
Philipp Maier1e6b4422018-02-23 14:02:13 +01003595 }
Harald Welte10985002017-12-12 09:29:15 +01003596
3597 /* Wait for 3 seconds if any more PAGING CMD are received on RSL */
3598 T.start;
3599 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003600 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte10985002017-12-12 09:29:15 +01003601 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003602 mtc.stop;
Harald Welte10985002017-12-12 09:29:15 +01003603 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003604 [] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003605 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003606 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003607 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003608 [] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003609 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003610 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003611 }
Harald Welte10985002017-12-12 09:29:15 +01003612 [] T.timeout {
3613 setverdict(pass);
3614 }
3615 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003616
3617 f_shutdown_helper();
Harald Welte10985002017-12-12 09:29:15 +01003618}
Harald Welteae026692017-12-09 01:03:01 +01003619
Philipp Maierf45824a2019-08-14 14:44:10 +02003620/* Verify how we handle unsolicited Paging Response. In case of an unsolicit
3621 * paging response we can not know which MSC is in charge, so we will blindly
3622 * pick the first configured MSC. This behavior is required in order to make
3623 * MT-CSFB calls working because in those cases the BSC can not know that the
3624 * MSC has already paged the subscriver via SGs. So any MT-CSFB call will look
3625 * like an unsolicited Paging Response to the MSC.
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003626 */
3627testcase TC_paging_resp_unsol() runs on test_CT {
3628
3629 f_init(1);
Philipp Maierf45824a2019-08-14 14:44:10 +02003630 timer T := 5.0;
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003631
3632 var BSSAP_N_CONNECT_ind rx_c_ind;
3633 var DchanTuple dt;
3634 var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010008880018'H))));
Philipp Maierf45824a2019-08-14 14:44:10 +02003635 var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003636
3637 /* Send CHAN RQD and wait for allocation; acknowledge it */
3638 dt.rsl_chan_nr := f_chreq_act_ack();
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003639 dt.idx := {0, 0};
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003640
3641 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003642 f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), enc_PDU_ML3_MS_NW(l3)));
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003643
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003644
Philipp Maierf45824a2019-08-14 14:44:10 +02003645 /* Expevct a CR with a matching Paging response on the A-Interface */
3646 T.start;
3647 alt {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003648 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
Philipp Maierf45824a2019-08-14 14:44:10 +02003649 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003650 dt.sccp_conn_id := rx_c_ind.connectionId;
3651 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
Philipp Maierf45824a2019-08-14 14:44:10 +02003652 }
3653 [] BSSAP.receive {
3654 setverdict(fail, "Received unexpected message on A-Interface!");
3655 }
3656 [] T.timeout {
3657 setverdict(fail, "Received nothing on A-Interface!");
3658 }
3659 }
3660
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003661 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003662 f_shutdown_helper();
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003663}
3664
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003665/* Verify BSC can schedule N paging requests under one minute if BTS buffer is good enough */
3666function f_TC_paging_Nreq(integer num_subscribers, boolean send_pag_load_ind) runs on test_CT {
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003667 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003668 var Hexstrings imsis := {};
3669 var Booleans rx_paging_done := {};
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003670 var integer rx_paging_num := 0;
3671 var integer i;
3672 timer T_rx := 60.0;
3673 timer T_load_ind := 1.0;
3674
3675 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003676 imsis := imsis & {f_gen_imsi(i)};
3677 rx_paging_done := rx_paging_done & { false };
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003678 }
3679
3680 f_init(1, guard_timeout := 100.0);
3681
3682 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003683 IPA_RSL[0][0].clear;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003684 if (send_pag_load_ind) {
3685 /* Tell there's plenty of space at the BTS (UINT16_MAX): */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003686 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(65535));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003687 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003688
3689 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003690 /* Page on LAC-CI of BTS0: */
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003691 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 +02003692 ts_BSSMAP_Paging(imsis[i], valueof(ts_BSSMAP_CIL_LAC_CI({ts_BSSMAP_CI_LAC_CI(1, 0)})),
3693 omit, omit)));
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003694 }
3695
3696 T_rx.start;
3697 T_load_ind.start;
3698 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003699 [] 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 +02003700 var hexstring imsi := rx_rsl_ud.rsl.ies[2].body.ms_identity.mobileIdentityV.oddEvenInd_identity.imsi.digits;
3701 var hexstring imsi_suffix := substr(imsi, lengthof(imsi)-6, 6);
3702 var charstring imsi_str := hex2str(imsi_suffix);
3703 var integer imsi_idx := str2int(imsi_str);
3704 if (rx_paging_done[imsi_idx] == false) {
3705 rx_paging_done[imsi_idx] := true;
3706 rx_paging_num := rx_paging_num + 1;
Pau Espin Pedrolef7ef632022-04-25 13:34:57 +02003707 } else {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003708 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 +02003709 mtc.stop;
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003710 }
3711 if (rx_paging_num < num_subscribers) {
3712 repeat;
3713 }
3714 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003715 [] IPA_RSL[0][0].receive { repeat; }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003716 [] T_load_ind.timeout {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003717 log("[CCH Load Ind timer] received paging requests so far: ", rx_paging_num);
3718 if (send_pag_load_ind) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003719 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(40));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003720 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003721 T_load_ind.start;
3722 repeat;
3723 }
3724 [] T_rx.timeout {
3725 setverdict(fail, "Timeout expecting paging requests, so far ", rx_paging_num);
3726 mtc.stop;
3727 }
3728 }
3729
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003730 /* Drop OML connection to have all paging requests flushed: */
3731 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
3732
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003733 f_shutdown_helper();
3734}
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003735/* Verify BSC can schedule 500 paging requests under one minute if BTS buffer is good enough */
3736testcase TC_paging_500req() runs on test_CT {
3737 f_TC_paging_Nreq(500, true);
3738}
3739/* Same as TC_paging_500req, but without sending CCCH Load Indication, which
3740 * means BTS is always under CCH Load Threshold, aka capable of sending tons of requests.
3741 * Since No CCCH Load Ind, BSC uses a conservative estimation of BTS load, which
3742 * for current config yields ~8req/sec, so 480req/min maximum. */
3743testcase TC_paging_450req_no_paging_load_ind() runs on test_CT {
3744 f_TC_paging_Nreq(450, false);
3745}
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003746
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003747/* Test RSL link drop causes counter increment */
3748testcase TC_rsl_drop_counter() runs on test_CT {
3749 var integer rsl_fail;
3750
Harald Welte89d42e82017-12-17 16:42:41 +01003751 f_init(1);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003752
3753 rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
3754
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003755 f_ipa_rsl_stop(bts[0][0].rsl);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003756
3757 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
3758
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003759 f_shutdown_helper();
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003760}
3761
3762/* TODO: Test OML link drop causes counter increment */
3763
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003764/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
3765function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003766 var IPA_Client client;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003767 timer T := 10.0;
3768
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003769 client.id := "IPA-BTS0-TRX0-RSL";
3770 client.vc_IPA := IPA_Emulation_CT.create(client.id & "-IPA") alive;
3771 client.ccm_pars := c_IPA_default_ccm_pars;
3772 client.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
3773 client.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003774
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01003775 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003776
3777 f_init_mgcp("VirtMSC");
3778
3779 /* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003780 map(client.vc_IPA:IPA_PORT, system:IPA);
3781 connect(client.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0][0]);
3782 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 +01003783
3784 /* wait for IPA OML link to connect and then disconnect */
3785 T.start;
3786 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003787 [] IPA_RSL[0][0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003788 T.stop;
3789 return true;
3790 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003791 [] IPA_RSL[0][0].receive { repeat }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003792 [] T.timeout {
Daniel Willmannafce8662018-07-06 23:11:32 +02003793 return false;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003794 }
3795 }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003796 return false;
3797}
3798
3799/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3800testcase TC_rsl_unknown_unit_id() runs on test_CT {
3801 if (f_ipa_unknown_unit_id(mp_bsc_rsl_port)) {
3802 setverdict(pass);
3803 } else {
3804 setverdict(fail, "Timeout RSL waiting for connection to close");
3805 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003806 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003807}
3808
3809
3810/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3811testcase TC_oml_unknown_unit_id() runs on test_CT {
3812 if (f_ipa_unknown_unit_id(mp_bsc_oml_port)) {
3813 setverdict(pass);
3814 } else {
3815 setverdict(fail, "Timeout OML waiting for connection to close");
3816 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003817 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003818}
3819
3820
Harald Weltec1a2fff2017-12-17 11:06:19 +01003821/***********************************************************************
Harald Welte6811d102019-04-14 22:23:14 +02003822 * "New world" test cases using RSL_Emulation + RAN_Emulation
Harald Weltec1a2fff2017-12-17 11:06:19 +01003823 ***********************************************************************/
3824
Harald Welte6811d102019-04-14 22:23:14 +02003825import from RAN_Emulation all;
Harald Welte47cd0e32020-08-21 12:39:11 +02003826import from BSSAP_LE_Emulation all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01003827import from RSL_Emulation all;
3828import from MSC_ConnectionHandler all;
3829
3830type function void_fn(charstring id) runs on MSC_ConnHdlr;
3831
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003832/* helper function to create and connect a MSC_ConnHdlr component
3833 * TODO: allow connecting to TRX1..N, not only TRX0 */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003834private function f_connect_handler(inout MSC_ConnHdlr vc_conn, integer bssap_idx := 0) runs on test_CT {
3835 connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
Daniel Willmann191e0d92018-01-17 12:44:35 +01003836 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003837 connect(vc_conn:RSL, bts[0][0].rsl.vc_RSL:CLIENT_PT);
3838 connect(vc_conn:RSL_PROC, bts[0][0].rsl.vc_RSL:RSL_PROC);
3839 if (isvalue(bts[1][0])) {
3840 connect(vc_conn:RSL1, bts[1][0].rsl.vc_RSL:CLIENT_PT);
3841 connect(vc_conn:RSL1_PROC, bts[1][0].rsl.vc_RSL:RSL_PROC);
Philipp Maier956a92f2018-02-16 10:58:07 +01003842 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003843 if (isvalue(bts[2][0])) {
3844 connect(vc_conn:RSL2, bts[2][0].rsl.vc_RSL:CLIENT_PT);
3845 connect(vc_conn:RSL2_PROC, bts[2][0].rsl.vc_RSL:RSL_PROC);
Neels Hofmeyr91401012019-07-11 00:42:35 +02003846 }
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003847 connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02003848 if (mp_enable_lcs_tests) {
3849 connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
3850 connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
3851 }
Daniel Willmann191e0d92018-01-17 12:44:35 +01003852 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02003853 connect(vc_conn:MGCP_MULTI, vc_MGCP:MGCP_CLIENT_MULTI);
Daniel Willmannebdecc02020-08-12 15:30:17 +02003854 connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
Harald Welte336820c2018-05-31 20:34:52 +02003855}
3856
Neels Hofmeyrda436782021-07-20 22:09:06 +02003857function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
Harald Welte336820c2018-05-31 20:34:52 +02003858runs on test_CT return MSC_ConnHdlr {
3859 var charstring id := testcasename();
3860 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003861 var integer bssap_idx := 0;
3862 if (isvalue(pars)) {
3863 bssap_idx := valueof(pars).mscpool.bssap_idx;
3864 }
Harald Welte336820c2018-05-31 20:34:52 +02003865 vc_conn := MSC_ConnHdlr.create(id);
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003866 f_connect_handler(vc_conn, bssap_idx);
Neels Hofmeyrda436782021-07-20 22:09:06 +02003867 return vc_conn;
3868}
3869
3870function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
3871runs on test_CT return MSC_ConnHdlr {
3872 var charstring id := testcasename();
Harald Weltea0630032018-03-20 21:09:55 +01003873 vc_conn.start(f_handler_init(fn, id, pars));
Harald Weltec1a2fff2017-12-17 11:06:19 +01003874 return vc_conn;
3875}
3876
Neels Hofmeyrda436782021-07-20 22:09:06 +02003877function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
3878runs on test_CT return MSC_ConnHdlr {
3879 return f_start_handler_run(f_start_handler_create(pars), fn, pars);
3880}
3881
Harald Weltea0630032018-03-20 21:09:55 +01003882/* first function inside ConnHdlr component; sets g_pars + starts function */
3883private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
3884runs on MSC_ConnHdlr {
3885 if (isvalue(pars)) {
3886 g_pars := valueof(pars);
3887 }
3888 fn.apply(id);
3889}
3890
Oliver Smith26a3db72021-07-09 13:51:29 +02003891private function f_vty_encryption_a5(charstring options) runs on test_CT {
3892 f_vty_transceive(BSCVTY, "configure terminal");
3893 f_vty_transceive(BSCVTY, "network");
3894 f_vty_transceive(BSCVTY, "encryption a5 " & options);
3895 f_vty_transceive(BSCVTY, "exit");
3896 f_vty_transceive(BSCVTY, "exit");
3897}
3898
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01003899const charstring VTY_A5_DEFAULT := "0 1 3";
3900
Oliver Smith26a3db72021-07-09 13:51:29 +02003901private function f_vty_encryption_a5_reset() runs on test_CT {
3902 /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01003903 f_vty_encryption_a5(VTY_A5_DEFAULT);
Oliver Smith26a3db72021-07-09 13:51:29 +02003904}
3905
Harald Welte3c86ea02018-05-10 22:28:05 +02003906/* Establish signalling channel (non-assignment case) followed by cipher mode */
3907private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02003908 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
3909 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte3c86ea02018-05-10 22:28:05 +02003910 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Philipp Maier23000732018-05-18 11:25:37 +02003911 ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode := omit;
3912 ass_cmd.pdu.bssmap.assignmentRequest.aoIPTransportLayer := omit;
3913 exp_compl.pdu.bssmap.assignmentComplete.circuitIdentityCode := omit;
3914 exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
Harald Welte3c86ea02018-05-10 22:28:05 +02003915
Philipp Maier23000732018-05-18 11:25:37 +02003916 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003917 f_perform_clear();
Harald Welte3c86ea02018-05-10 22:28:05 +02003918}
3919testcase TC_ciph_mode_a5_0() runs on test_CT {
3920 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003921 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02003922 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
3923
3924 f_init(1, true);
3925 f_sleep(1.0);
3926 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3927 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003928 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02003929}
3930testcase TC_ciph_mode_a5_1() runs on test_CT {
3931 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003932 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02003933 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
3934
3935 f_init(1, true);
3936 f_sleep(1.0);
3937 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3938 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003939 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02003940}
Oliver Smith50b98122021-07-09 15:00:28 +02003941/* OS#4975: verify that A5/2 is preferred over A5/0 */
3942testcase TC_ciph_mode_a5_2_0() runs on test_CT {
3943 var MSC_ConnHdlr vc_conn;
3944 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3945
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01003946 pars.encr := f_encr_params('05'O, '04'O); /* A5/0 and A5/2 (0x01|0x04)*/
Oliver Smith50b98122021-07-09 15:00:28 +02003947
3948 f_init(1, true);
3949 f_vty_encryption_a5("0 1 2 3");
3950 f_sleep(1.0);
3951 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3952 vc_conn.done;
3953 f_vty_encryption_a5_reset();
3954 f_shutdown_helper();
3955}
Oliver Smith1dff88d2021-07-09 08:45:51 +02003956/* OS#4975: verify that A5/1 is preferred over A5/2 */
3957testcase TC_ciph_mode_a5_2_1() runs on test_CT {
3958 var MSC_ConnHdlr vc_conn;
3959 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3960
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01003961 pars.encr := f_encr_params('06'O, '02'O); /* A5/1 and A5/2 (0x02|0x04)*/
Oliver Smith1dff88d2021-07-09 08:45:51 +02003962
3963 f_init(1, true);
3964 f_vty_encryption_a5("1 2");
3965 f_sleep(1.0);
3966 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3967 vc_conn.done;
3968 f_vty_encryption_a5_reset();
3969 f_shutdown_helper();
3970}
Harald Welte3c86ea02018-05-10 22:28:05 +02003971testcase TC_ciph_mode_a5_3() runs on test_CT {
3972 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003973 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02003974 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
3975
3976 f_init(1, true);
3977 f_sleep(1.0);
3978 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3979 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003980 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02003981}
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003982/* Establish a Signalling channel with A5/4 encryption. */
3983testcase TC_ciph_mode_a5_4() runs on test_CT {
3984 var MSC_ConnHdlr vc_conn;
3985 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3986 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Harald Welte3c86ea02018-05-10 22:28:05 +02003987
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003988 f_init(1, true);
Oliver Smith26a3db72021-07-09 13:51:29 +02003989 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003990 f_sleep(1.0);
3991 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3992 vc_conn.done;
Oliver Smith26a3db72021-07-09 13:51:29 +02003993 f_vty_encryption_a5_reset();
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003994 f_shutdown_helper();
3995}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02003996/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
3997private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
3998 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
3999 var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
4000 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4001 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4002
4003 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004004 f_perform_clear();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004005}
4006testcase TC_assignment_aoip_tla_v6() runs on test_CT {
4007 var MSC_ConnHdlr vc_conn;
4008 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4009
4010 f_init(1, true);
4011 f_sleep(1.0);
4012 vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
4013 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004014 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004015}
4016
Harald Welte3c86ea02018-05-10 22:28:05 +02004017
4018/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
Harald Welte651fcdc2018-05-10 20:23:16 +02004019private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004020 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4021 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004022
Harald Welte552620d2017-12-16 23:21:36 +01004023 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4024 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte73cd2712017-12-17 00:44:52 +01004025
Harald Weltea0630032018-03-20 21:09:55 +01004026 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004027 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004028}
Harald Welte552620d2017-12-16 23:21:36 +01004029testcase TC_assignment_fr_a5_0() runs on test_CT {
4030 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004031 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004032 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
Harald Welte552620d2017-12-16 23:21:36 +01004033
Harald Welte89d42e82017-12-17 16:42:41 +01004034 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004035 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004036 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004037 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004038 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004039}
Harald Welte552620d2017-12-16 23:21:36 +01004040testcase TC_assignment_fr_a5_1() runs on test_CT {
Harald Weltec1a2fff2017-12-17 11:06:19 +01004041 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004042 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004043 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004044
Harald Welte89d42e82017-12-17 16:42:41 +01004045 f_init(1, true);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004046 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004047 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4048 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004049 f_shutdown_helper();
Harald Welte651fcdc2018-05-10 20:23:16 +02004050}
4051testcase TC_assignment_fr_a5_3() runs on test_CT {
4052 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004053 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004054 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004055
Harald Welte651fcdc2018-05-10 20:23:16 +02004056 f_init(1, true);
4057 f_sleep(1.0);
4058 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004059 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004060 f_shutdown_helper();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004061}
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004062/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
4063testcase TC_assignment_fr_a5_4() runs on test_CT {
4064 var MSC_ConnHdlr vc_conn;
4065 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4066 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
4067
4068 f_init(1, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02004069 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004070 f_sleep(1.0);
4071 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4072 vc_conn.done;
Oliver Smith7eabd312021-07-12 14:18:56 +02004073 f_vty_encryption_a5_reset();
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004074 f_shutdown_helper();
4075}
Harald Weltec1a2fff2017-12-17 11:06:19 +01004076
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +02004077/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
4078testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
4079 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4080 var MSC_ConnHdlr vc_conn;
4081
4082 f_init(1, true);
4083 f_sleep(1.0);
4084
4085 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
4086 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
4087 vc_conn.done;
4088 f_shutdown_helper();
4089}
4090
Harald Welte552620d2017-12-16 23:21:36 +01004091/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
4092private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004093 g_pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004094 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02004095 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004096
4097 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02004098 /* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
4099
Harald Weltea0630032018-03-20 21:09:55 +01004100 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004101 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004102}
Harald Welte552620d2017-12-16 23:21:36 +01004103testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
4104 var MSC_ConnHdlr vc_conn;
4105
Harald Welte89d42e82017-12-17 16:42:41 +01004106 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004107 f_sleep(1.0);
4108
Harald Welte8863fa12018-05-10 20:15:27 +02004109 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
Harald Welte552620d2017-12-16 23:21:36 +01004110 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004111 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004112}
4113
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004114private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
4115 var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
4116 var PDU_BSSAP exp_ass_req := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004117
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004118 exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4119 exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4120
4121 /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
4122
4123 var BSSMAP_FIELD_CodecType codecType;
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004124
4125 codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
4126 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
4127
4128 f_create_chan_and_exp();
4129 /* we should now have a COMPL_L3 at the MSC */
4130
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004131 /* Start ciphering, expect Cipher Mode Reject */
Neels Hofmeyr6c388f22021-06-11 02:36:56 +02004132 f_cipher_mode(g_pars.encr, exp_fail := true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004133 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004134}
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004135testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
4136 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004137 var MSC_ConnHdlr vc_conn;
4138
Harald Welte89d42e82017-12-17 16:42:41 +01004139 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004140 f_sleep(1.0);
4141
Neels Hofmeyr0588cad2021-06-11 01:38:18 +02004142 pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004143 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004144 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004145 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004146}
4147
4148
Harald Welte4532e0a2017-12-23 02:05:44 +01004149private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004150 g_pars := f_gen_test_hdlr_pars();
Harald Welte4532e0a2017-12-23 02:05:44 +01004151 var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
Philipp Maier48604732018-10-09 15:00:37 +02004152 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte4532e0a2017-12-23 02:05:44 +01004153 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004154
4155 f_statsd_reset();
Harald Weltea0630032018-03-20 21:09:55 +01004156 f_establish_fully(ass_cmd, exp_compl);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004157
4158 var StatsDExpects expect := {
Daniel Willmannc5398f72020-09-21 10:41:35 +02004159 { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
4160 { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
Daniel Willmannebdecc02020-08-12 15:30:17 +02004161 { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
4162 { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
4163 };
4164 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004165 f_perform_clear();
Harald Welte4532e0a2017-12-23 02:05:44 +01004166}
4167
4168testcase TC_assignment_sign() runs on test_CT {
4169 var MSC_ConnHdlr vc_conn;
4170
4171 f_init(1, true);
4172 f_sleep(1.0);
4173
Harald Welte8863fa12018-05-10 20:15:27 +02004174 vc_conn := f_start_handler(refers(f_tc_assignment_sign));
Harald Welte4532e0a2017-12-23 02:05:44 +01004175 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004176 f_shutdown_helper();
Harald Welte4532e0a2017-12-23 02:05:44 +01004177}
4178
Harald Welte60aa5762018-03-21 19:33:13 +01004179/***********************************************************************
4180 * Codec (list) testing
4181 ***********************************************************************/
4182
4183/* check if the given rsl_mode is compatible with the a_elem */
4184private function f_match_codec(BSSMAP_FIELD_CodecElement a_elem, RSL_IE_ChannelMode rsl_mode)
4185return boolean {
4186 select (a_elem.codecType) {
4187 case (GSM_FR) {
4188 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1))) {
4189 return true;
4190 }
4191 }
4192 case (GSM_HR) {
4193 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1))) {
4194 return true;
4195 }
4196 }
4197 case (GSM_EFR) {
4198 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2))) {
4199 return true;
4200 }
4201 }
4202 case (FR_AMR) {
4203 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3))) {
4204 return true;
4205 }
4206 }
4207 case (HR_AMR) {
4208 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3))) {
4209 return true;
4210 }
4211 }
4212 case else { }
4213 }
4214 return false;
4215}
4216
4217/* check if the given rsl_mode is compatible with the a_list */
4218private function f_match_codecs(BSSMAP_IE_SpeechCodecList a_list, RSL_IE_ChannelMode rsl_mode)
4219return boolean {
4220 for (var integer i := 0; i < sizeof(a_list); i := i+1) {
4221 if (f_match_codec(a_list.codecElements[i], rsl_mode)) {
4222 return true;
4223 }
4224 }
4225 return false;
4226}
4227
4228/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
Philipp Maier61f6b572018-07-06 14:03:38 +02004229function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
Harald Welte60aa5762018-03-21 19:33:13 +01004230return BSSMAP_IE_ChannelType {
4231 /* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
4232 var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
4233 select (a_elem.codecType) {
4234 case (GSM_FR) {
4235 ret.channelRateAndType := ChRate_TCHF;
4236 ret.speechId_DataIndicator := Spdi_TCHF_FR;
4237 }
4238 case (GSM_HR) {
4239 ret.channelRateAndType := ChRate_TCHH;
4240 ret.speechId_DataIndicator := Spdi_TCHH_HR;
4241 }
4242 case (GSM_EFR) {
4243 ret.channelRateAndType := ChRate_TCHF;
4244 ret.speechId_DataIndicator := Spdi_TCHF_EFR;
4245 }
4246 case (FR_AMR) {
4247 ret.channelRateAndType := ChRate_TCHF;
4248 ret.speechId_DataIndicator := Spdi_TCHF_AMR;
4249 }
4250 case (HR_AMR) {
4251 ret.channelRateAndType := ChRate_TCHH;
4252 ret.speechId_DataIndicator := Spdi_TCHH_AMR;
4253 }
4254 case else {
4255 setverdict(fail, "Unsupported codec ", a_elem);
Daniel Willmannafce8662018-07-06 23:11:32 +02004256 mtc.stop;
Harald Welte60aa5762018-03-21 19:33:13 +01004257 }
4258 }
4259 return ret;
4260}
4261
Harald Weltea63b9102018-03-22 20:36:16 +01004262private function f_rsl_chmod_tmpl_from_codec(BSSMAP_FIELD_CodecElement a_elem)
4263return template RSL_IE_Body {
4264 var template RSL_IE_Body mode_ie := {
4265 chan_mode := {
4266 len := ?,
4267 reserved := ?,
4268 dtx_d := ?,
4269 dtx_u := ?,
4270 spd_ind := RSL_SPDI_SPEECH,
4271 ch_rate_type := -,
4272 coding_alg_rate := -
4273 }
4274 }
4275
4276 select (a_elem.codecType) {
4277 case (GSM_FR) {
4278 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
4279 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM1;
4280 }
4281 case (GSM_HR) {
4282 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
4283 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM1;
4284 }
4285 case (GSM_EFR) {
4286 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
4287 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM2;
4288 }
4289 case (FR_AMR) {
4290 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
4291 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM3;
4292 }
4293 case (HR_AMR) {
4294 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
4295 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM3;
4296 }
4297 }
4298 return mode_ie;
4299}
4300
Harald Welte60aa5762018-03-21 19:33:13 +01004301type record CodecListTest {
4302 BSSMAP_IE_SpeechCodecList codec_list,
4303 charstring id
4304}
4305type record of CodecListTest CodecListTests
4306
4307private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004308 f_assignment_codec(id);
4309}
4310
4311private function f_assignment_codec(charstring id, boolean do_perform_clear := true) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02004312 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02004313 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welte60aa5762018-03-21 19:33:13 +01004314
4315 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004316 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte79f3f542018-05-25 20:02:37 +02004317 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4318 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
4319 g_pars.ass_codec_list.codecElements[0];
Philipp Maierd0e64b02019-03-13 14:15:23 +01004320 if (isvalue(g_pars.expect_mr_s0_s7)) {
4321 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
4322 g_pars.expect_mr_s0_s7;
4323 }
Harald Welte79f3f542018-05-25 20:02:37 +02004324 }
Harald Welte60aa5762018-03-21 19:33:13 +01004325 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4326 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
Harald Welte60aa5762018-03-21 19:33:13 +01004327 log("expecting ASS COMPL like this: ", exp_compl);
4328
4329 f_establish_fully(ass_cmd, exp_compl);
Harald Weltea63b9102018-03-22 20:36:16 +01004330
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004331 if (not g_pars.expect_channel_mode_modify) {
4332 /* Verify that the RSL-side activation actually matches our expectations */
4333 var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
Harald Weltea63b9102018-03-22 20:36:16 +01004334
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004335 var RSL_IE_Body mode_ie;
4336 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
4337 setverdict(fail, "Couldn't find CHAN_MODE IE");
Daniel Willmannafce8662018-07-06 23:11:32 +02004338 mtc.stop;
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004339 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004340 var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
4341 if (not match(mode_ie, t_mode_ie)) {
4342 log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
4343 setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004344 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004345
4346 var RSL_IE_Body mr_conf;
4347 if (g_pars.expect_mr_conf_ie != omit) {
4348 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
4349 setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
4350 mtc.stop;
4351 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004352 log("found RSL MR CONFIG IE: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004353
4354 if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
4355 setverdict(fail, "RSL MR CONFIG IE does not match expectation. Expected: ",
4356 g_pars.expect_mr_conf_ie);
4357 }
4358 } else {
4359 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
4360 log("found RSL MR CONFIG IE: ", mr_conf);
4361 setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
4362 mtc.stop;
4363 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004364 }
4365 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004366
4367 if (do_perform_clear) {
4368 f_perform_clear();
4369 }
Harald Welte60aa5762018-03-21 19:33:13 +01004370}
4371
Philipp Maierd0e64b02019-03-13 14:15:23 +01004372private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
4373
4374 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4375 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4376
4377 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004378 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maierd0e64b02019-03-13 14:15:23 +01004379 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4380 }
4381 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4382 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
4383 log("expecting ASS FAIL like this: ", exp_fail);
4384
4385 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004386 f_perform_clear();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004387}
4388
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004389const CounterNameVals counternames_bsc_bts_assignment := {
4390 { "assignment:attempted", 0 },
4391 { "assignment:completed", 0 },
4392 { "assignment:stopped", 0 },
4393 { "assignment:no_channel", 0 },
4394 { "assignment:timeout", 0 },
4395 { "assignment:failed", 0 },
4396 { "assignment:error", 0 }
4397};
4398
4399const CounterNameVals counternames_bts_assignment := {
4400 { "assignment:attempted_sign", 0 },
4401 { "assignment:attempted_speech", 0 },
4402 { "assignment:completed_sign", 0 },
4403 { "assignment:completed_speech", 0 },
4404 { "assignment:stopped_sign", 0 },
4405 { "assignment:stopped_speech", 0 },
4406 { "assignment:no_channel_sign", 0 },
4407 { "assignment:no_channel_speech", 0 },
4408 { "assignment:timeout_sign", 0 },
4409 { "assignment:timeout_speech", 0 },
4410 { "assignment:failed_sign", 0 },
4411 { "assignment:failed_speech", 0 },
4412 { "assignment:error_sign", 0 },
4413 { "assignment:error_speech", 0 }
4414};
4415
4416function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
4417 var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
4418 f_ctrs_bts_init(bts_count, bts_names);
4419 f_ctrs_bsc_init(counternames_bsc_bts_assignment);
4420}
4421
Harald Welte60aa5762018-03-21 19:33:13 +01004422testcase TC_assignment_codec_fr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004423 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004424 var MSC_ConnHdlr vc_conn;
4425
4426 f_init(1, true);
4427 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004428 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004429
4430 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004431 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004432 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004433
4434 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4435 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4436 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4437 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4438 f_ctrs_bts_verify();
4439
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004440 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004441}
4442
4443testcase TC_assignment_codec_hr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004444 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004445 var MSC_ConnHdlr vc_conn;
4446
4447 f_init(1, true);
4448 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004449 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004450
4451 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004452 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004453 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004454
4455 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4456 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4457 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4458 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4459 f_ctrs_bts_verify();
4460
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004461 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004462}
4463
4464testcase TC_assignment_codec_efr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004465 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004466 var MSC_ConnHdlr vc_conn;
4467
4468 f_init(1, true);
4469 f_sleep(1.0);
4470
4471 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004472 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004473 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004474 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004475}
4476
Philipp Maierd0e64b02019-03-13 14:15:23 +01004477/* Allow 5,90k only (current default config) */
4478private function f_allow_amr_rate_5_90k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004479 f_vty_cfg_msc(BSCVTY, 0, {
4480 "amr-config 12_2k forbidden",
4481 "amr-config 10_2k forbidden",
4482 "amr-config 7_95k forbidden",
4483 "amr-config 7_40k forbidden",
4484 "amr-config 6_70k forbidden",
4485 "amr-config 5_90k allowed",
4486 "amr-config 5_15k forbidden",
4487 "amr-config 4_75k forbidden"
4488 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004489}
4490
4491/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
4492 * ("Config-NB-Code = 1") */
4493private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004494 f_vty_cfg_msc(BSCVTY, 0, {
4495 "amr-config 12_2k allowed",
4496 "amr-config 10_2k forbidden",
4497 "amr-config 7_95k forbidden",
4498 "amr-config 7_40k allowed",
4499 "amr-config 6_70k forbidden",
4500 "amr-config 5_90k allowed",
4501 "amr-config 5_15k forbidden",
4502 "amr-config 4_75k allowed"
4503 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004504}
4505
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004506private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
4507 var charstring tch;
4508 if (fr) {
4509 tch := "tch-f";
4510 } else {
4511 tch := "tch-h";
4512 }
4513 f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
4514}
4515
4516/* Set the AMR start-mode for this TCH back to the default configuration. */
4517private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
4518 f_vty_amr_start_mode_set(fr, "auto");
4519}
4520
Harald Welte60aa5762018-03-21 19:33:13 +01004521testcase TC_assignment_codec_amr_f() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004522 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004523 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004524
4525 /* Note: This setups the codec configuration. The parameter payload in
4526 * mr_conf must be consistant with the parameter codecElements in pars
4527 * and also must match the amr-config in osmo-bsc.cfg! */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004528 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004529 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004530 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Pau Espin Pedrolf7634dc2022-09-02 17:56:00 +02004531 pars.expect_mr_conf_ie := mr_conf_amr_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004532
Harald Welte60aa5762018-03-21 19:33:13 +01004533 f_init(1, true);
4534 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004535 f_vty_amr_start_mode_set(true, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004536 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004537
Harald Welte8863fa12018-05-10 20:15:27 +02004538 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004539 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004540
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004541 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4542 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4543 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4544 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4545 f_ctrs_bts_verify();
4546
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004547 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004548 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004549}
4550
4551testcase TC_assignment_codec_amr_h() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004552 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004553 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004554
4555 /* See note above */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004556 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004557 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004558 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Pau Espin Pedrolf7634dc2022-09-02 17:56:00 +02004559 pars.expect_mr_conf_ie := mr_conf_amr_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004560
Harald Welte60aa5762018-03-21 19:33:13 +01004561 f_init(1, true);
4562 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004563 f_vty_amr_start_mode_set(false, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004564 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004565
Harald Welte8863fa12018-05-10 20:15:27 +02004566 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004567 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004568
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004569 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4570 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4571 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4572 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4573 f_ctrs_bts_verify();
4574
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004575 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004576 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004577}
4578
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004579/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
4580testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
4581 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4582 var MSC_ConnHdlr vc_conn;
4583
4584 f_init(1, true);
4585 f_sleep(1.0);
4586
4587 /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
4588 * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
4589 * expecting a Channel Mode Modify if the channel type is compatible. */
4590 f_disable_all_sdcch();
4591 f_disable_all_tch_h();
4592
4593 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4594 pars.expect_channel_mode_modify := true;
4595 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4596 vc_conn.done;
4597
4598 f_enable_all_sdcch();
4599 f_enable_all_tch();
4600 f_shutdown_helper();
4601}
4602
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004603/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
4604testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
4605 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4606 var MSC_ConnHdlr vc_conn;
4607
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004608 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4609 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
4610 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Pau Espin Pedrolf7634dc2022-09-02 17:56:00 +02004611 /* expect ICMI=0, smod=00: */
4612 pars.expect_mr_conf_ie := valueof(RSL_IE_Body:{multirate_cfg := ts_RSL_MultirateCfg(false, 0, '00000100'B /* 5,90k */)});
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004613
4614 f_init(1, true);
4615 f_sleep(1.0);
4616
4617 /* First set nonzero start mode bits */
4618 f_vty_amr_start_mode_set(true, "4");
4619 /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
4620 * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
4621 * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
4622 f_vty_amr_start_mode_set(true, "auto");
4623
4624 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4625 vc_conn.done;
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004626
4627 /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
4628 f_vty_amr_start_mode_set(true, "1");
4629 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004630 f_shutdown_helper();
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004631}
4632
Neels Hofmeyr21863562020-11-26 00:34:33 +00004633function f_TC_assignment_codec_amr(boolean fr, octetstring mrconf, bitstring s8_s0, bitstring exp_s8_s0,
4634 charstring start_mode := "1")
Philipp Maierd0e64b02019-03-13 14:15:23 +01004635runs on test_CT {
4636
4637 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4638 var MSC_ConnHdlr vc_conn;
4639
4640 /* See note above */
4641 var RSL_IE_Body mr_conf := {
4642 other := {
4643 len := lengthof(mrconf),
4644 payload := mrconf
4645 }
4646 };
4647
4648 if (fr) {
4649 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4650 } else {
4651 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4652 }
4653 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4654 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4655 pars.expect_mr_conf_ie := mr_conf;
4656 pars.expect_mr_s0_s7 := exp_s8_s0;
4657
4658 f_init(1, true);
4659 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004660 f_vty_amr_start_mode_set(fr, start_mode);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004661 f_sleep(1.0);
4662
4663 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4664 vc_conn.done;
4665 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004666 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004667}
4668
4669function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
4670runs on test_CT {
4671
4672 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4673 var MSC_ConnHdlr vc_conn;
4674
4675 if (fr) {
4676 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4677 } else {
4678 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4679 }
4680 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4681 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4682
4683 f_init(1, true);
4684 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004685 f_vty_amr_start_mode_set(fr, "1");
Philipp Maierd0e64b02019-03-13 14:15:23 +01004686 f_sleep(1.0);
4687
4688 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
4689 vc_conn.done;
4690 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004691 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004692}
4693
4694
4695/* Set S1, we expect an AMR multirate configuration IE with all four rates
4696 * set. */
4697testcase TC_assignment_codec_amr_f_S1() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004698 f_TC_assignment_codec_amr(true, '289520882208'O, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004699 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004700}
4701
4702/* Set S1, we expect an AMR multirate configuration IE with the lower three
4703 * rates set. */
4704testcase TC_assignment_codec_amr_h_S1() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004705 f_TC_assignment_codec_amr(false, '2815208820'O, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004706 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004707}
4708
4709/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4710 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4711testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004712 f_TC_assignment_codec_amr(true, '289520882208'O, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004713 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004714}
4715
4716/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4717 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4718testcase TC_assignment_codec_amr_h_S124() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004719 f_TC_assignment_codec_amr(false, '2815208820'O, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004720 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004721}
4722
4723/* The following block of tests selects more and more rates until all four
4724 * possible rates are in the active set (full rate) */
4725testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004726 f_TC_assignment_codec_amr(true, '2801'O, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004727 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004728}
4729
4730testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004731 f_TC_assignment_codec_amr(true, '28052080'O, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004732 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004733}
4734
4735testcase TC_assignment_codec_amr_f_S024() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004736 f_TC_assignment_codec_amr(true, '2815208820'O, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004737 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004738}
4739
4740testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004741 f_TC_assignment_codec_amr(true, '289520882208'O, '10010101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004742 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004743}
4744
4745/* The following block of tests selects more and more rates until all three
4746 * possible rates are in the active set (half rate) */
4747testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004748 f_TC_assignment_codec_amr(false, '2801'O, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004749 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004750}
4751
4752testcase TC_assignment_codec_amr_h_S02() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004753 f_TC_assignment_codec_amr(false, '28052080'O, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004754 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004755}
4756
4757testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004758 f_TC_assignment_codec_amr(false, '2815208820'O, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004759 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004760}
4761
4762/* The following block tests what happens when the MSC does offer rate
4763 * configurations that are not supported by the BSC. Normally such situations
4764 * should not happen because the MSC gets informed by the BSC in advance via
4765 * the L3 COMPLETE message which rates are applicable. The MSC should not try
4766 * to offer rates that are not applicable anyway. */
4767
4768testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004769 /* Try to include 12,2k in into the active set even though the channel
4770 * is half rate only. The BSC is expected to remove the 12,0k */
4771 f_TC_assignment_codec_amr(false, '2815208820'O, '10010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004772 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004773}
4774
4775testcase TC_assignment_codec_amr_f_S01234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004776 /* See what happens when all rates are selected at once. Since then
4777 * Also S1 is selected, this setting will be prefered and we should
4778 * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
4779 f_TC_assignment_codec_amr(true, '289520882208'O, '11111111'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004780 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004781}
4782
4783testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004784 /* Same as above, but with S1 missing, the MSC is then expected to
4785 * select the currently supported rates, which are also 12.2k, 7,40k,
4786 * 5,90k, and 4,75k, into the active set. */
4787 f_TC_assignment_codec_amr(true, '289520882208'O, '11111101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004788 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004789}
4790
4791testcase TC_assignment_codec_amr_f_zero() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004792 /* Try to select no rates at all */
4793 f_TC_assignment_codec_amr_fail(true, '00000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004794 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004795}
4796
4797testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004798 /* Try to select only unsupported rates */
4799 f_TC_assignment_codec_amr_fail(true, '01101000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004800 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004801}
4802
4803testcase TC_assignment_codec_amr_h_S7() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004804 /* Try to select 12,2k for half rate */
4805 f_TC_assignment_codec_amr_fail(false, '10000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004806 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004807}
4808
Neels Hofmeyr21863562020-11-26 00:34:33 +00004809testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
4810 f_TC_assignment_codec_amr(true, '209520882208'O, '11111111'B, '00000010'B,
4811 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004812 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004813}
4814
4815testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
4816 f_TC_assignment_codec_amr(false, '2015208820'O, '10010101'B, '00010101'B,
4817 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004818 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004819}
4820
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004821testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004822 /* "amr tch-f modes 0 2 4 7" => total 4 modes and start mode 4 => '11'B on the wire */
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004823 f_TC_assignment_codec_amr(true, '2b9520882208'O, '11111111'B, '00000010'B,
4824 start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004825 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004826}
4827
4828testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004829 /* "amr tch-h modes 0 2 4" => total 3 modes and start mode 4 => '10'B on the wire */
4830 f_TC_assignment_codec_amr(false, '2a15208820'O, '10010101'B, '00010101'B,
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004831 start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004832 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004833}
4834
Philipp Maierac09bfc2019-01-08 13:41:39 +01004835private function f_disable_all_tch_f() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004836 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 borken");
4837 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 borken");
4838 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 borken");
4839 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004840}
4841
4842private function f_disable_all_tch_h() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004843 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 borken");
4844 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004845}
4846
4847private function f_enable_all_tch() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004848 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 unused");
4849 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 unused");
4850 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 unused");
4851 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 unused");
4852 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 unused");
4853 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004854}
4855
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004856private function f_disable_all_sdcch() runs on test_CT {
4857 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
4858 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
4859 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
4860 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
4861}
4862
4863private function f_enable_all_sdcch() runs on test_CT {
4864 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
4865 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
4866 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
4867 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
4868}
4869
Philipp Maierac09bfc2019-01-08 13:41:39 +01004870/* Allow HR only */
4871private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs on MSC_ConnHdlr {
4872 g_pars := f_gen_test_hdlr_pars();
4873 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4874 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4875 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4876 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
4877 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
4878 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
4879 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004880 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004881}
4882
4883/* Allow FR only */
4884private function f_TC_assignment_codec_xr_exhausted_req_fr(charstring id) runs on MSC_ConnHdlr {
4885 g_pars := f_gen_test_hdlr_pars();
4886 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4887 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4888 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4889 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
4890 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
4891 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4892 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004893 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004894}
4895
4896/* Allow HR only (expect assignment failure) */
4897private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) runs on MSC_ConnHdlr {
4898 g_pars := f_gen_test_hdlr_pars();
4899 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4900 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4901 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4902 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
4903 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
4904 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
4905 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004906 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004907}
4908
4909/* Allow FR only (expect assignment failure) */
4910private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) runs on MSC_ConnHdlr {
4911 g_pars := f_gen_test_hdlr_pars();
4912 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4913 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4914 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4915 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
4916 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
4917 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4918 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004919 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004920}
4921
4922/* Allow FR and HR, but prefer FR */
4923private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
4924 g_pars := f_gen_test_hdlr_pars();
4925 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4926 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4927 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4928 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
4929 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
4930 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
4931 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
4932 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004933 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004934}
4935
4936/* Allow FR and HR, but prefer HR */
4937private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
4938 g_pars := f_gen_test_hdlr_pars();
4939 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4940 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4941 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4942 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
4943 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
4944 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
4945 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
4946 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004947 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004948}
4949
4950/* Allow FR and HR, but prefer FR */
4951private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
4952 g_pars := f_gen_test_hdlr_pars();
4953 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4954 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4955 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4956 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
4957 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
4958 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
4959 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
4960 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004961 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004962}
4963
4964/* Allow FR and HR, but prefer HR */
4965private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
4966 g_pars := f_gen_test_hdlr_pars();
4967 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4968 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4969 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4970 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
4971 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
4972 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
4973 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
4974 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004975 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004976}
4977
4978/* Request a HR channel while all FR channels are exhausted, this is expected
4979 * to work without conflicts */
4980testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
4981 var MSC_ConnHdlr vc_conn;
4982 f_init(1, true);
4983 f_sleep(1.0);
4984 f_enable_all_tch();
4985 f_disable_all_tch_f();
4986 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
4987 vc_conn.done;
4988 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004989 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004990}
4991
4992/* Request a FR channel while all FR channels are exhausted, this is expected
4993 * to fail. */
4994testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
4995 var MSC_ConnHdlr vc_conn;
4996 f_init(1, true);
4997 f_sleep(1.0);
4998 f_enable_all_tch();
4999 f_disable_all_tch_f();
5000 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
5001 vc_conn.done;
5002 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005003 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005004}
5005
5006/* Request a FR (prefered) or alternatively a HR channel while all FR channels
5007 * are exhausted, this is expected to be resolved by selecting a HR channel. */
5008testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
5009 var MSC_ConnHdlr vc_conn;
5010 f_init(1, true);
5011 f_sleep(1.0);
5012 f_enable_all_tch();
5013 f_disable_all_tch_f();
5014 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
5015 vc_conn.done;
5016 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005017 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005018}
5019
5020/* Request a HR (prefered) or alternatively a FR channel while all FR channels
5021 * are exhausted, this is expected to work without conflicts. */
5022testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
5023 var MSC_ConnHdlr vc_conn;
5024 f_init(1, true);
5025 f_sleep(1.0);
5026 f_enable_all_tch();
5027 f_disable_all_tch_f();
5028 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
5029 vc_conn.done;
5030 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005031 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005032}
5033
5034/* Request a FR channel while all HR channels are exhausted, this is expected
5035 * to work without conflicts */
5036testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
5037 var MSC_ConnHdlr vc_conn;
5038 f_init(1, true);
5039 f_sleep(1.0);
5040 f_enable_all_tch();
5041 f_disable_all_tch_h();
5042 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
5043 vc_conn.done;
5044 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005045 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005046}
5047
5048/* Request a HR channel while all HR channels are exhausted, this is expected
5049 * to fail. */
5050testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
5051 var MSC_ConnHdlr vc_conn;
5052 f_init(1, true);
5053 f_sleep(1.0);
5054 f_enable_all_tch();
5055 f_disable_all_tch_h();
5056 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
5057 vc_conn.done;
5058 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005059 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005060}
5061
5062/* Request a HR (prefered) or alternatively a FR channel while all HR channels
5063 * are exhausted, this is expected to be resolved by selecting a FR channel. */
5064testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
5065 var MSC_ConnHdlr vc_conn;
5066 f_init(1, true);
5067 f_sleep(1.0);
5068 f_enable_all_tch();
5069 f_disable_all_tch_h();
5070 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
5071 vc_conn.done;
5072 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005073 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005074}
5075
5076/* Request a FR (prefered) or alternatively a HR channel while all HR channels
5077 * are exhausted, this is expected to work without conflicts. */
5078testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
5079 var MSC_ConnHdlr vc_conn;
5080 f_init(1, true);
5081 f_sleep(1.0);
5082 f_enable_all_tch();
5083 f_disable_all_tch_h();
5084 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
5085 vc_conn.done;
5086 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005087 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005088}
5089
5090/* Allow FR and HR, but prefer HR */
5091private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5092 g_pars := f_gen_test_hdlr_pars();
5093 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5094 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5095 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5096 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5097 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5098 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5099 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5100 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005101 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005102}
5103
5104/* Allow FR and HR, but prefer FR */
5105private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5106 g_pars := f_gen_test_hdlr_pars();
5107 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5108 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5109 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5110 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5111 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5112 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5113 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5114 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005115 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005116}
5117
5118/* Request a HR (prefered) or alternatively a FR channel, it is expected that
5119 * HR, which is the prefered type, is selected. */
5120testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
5121 var MSC_ConnHdlr vc_conn;
5122 f_init(1, true);
5123 f_sleep(1.0);
5124 f_enable_all_tch();
5125 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
5126 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005127 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005128}
5129
5130/* Request a FR (prefered) or alternatively a HR channel, it is expected that
5131 * FR, which is the prefered type, is selected. */
5132testcase TC_assignment_codec_req_fr_hr() runs on test_CT {
5133 var MSC_ConnHdlr vc_conn;
5134 f_init(1, true);
5135 f_sleep(1.0);
5136 f_enable_all_tch();
5137 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_fr_hr));
5138 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005139 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005140}
5141
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005142/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
5143private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
5144 g_pars := f_gen_test_hdlr_pars();
5145 g_pars.ra := '02'O; /* RA containing reason=LU */
5146
5147 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5148 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5149 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5150 var template uint3_t tsc := ?;
5151
5152 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5153 f_create_bssmap_exp(l3_enc);
5154 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5155 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5156
5157 /* we should now have a COMPL_L3 at the MSC */
5158 timer T := 10.0;
5159 T.start;
5160 alt {
5161 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5162 [] T.timeout {
5163 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5164 }
5165 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005166
5167 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005168}
5169testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
5170 var MSC_ConnHdlr vc_conn;
5171 f_init(1, true);
5172 f_sleep(1.0);
5173 f_disable_all_sdcch();
5174 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
5175 vc_conn.done;
5176 f_enable_all_sdcch();
5177 f_shutdown_helper();
5178}
5179
5180/* Request a signalling channel with all SDCCH exhausted, it is
5181 expected that no TCH will be selected for signalling and assigment will fail
5182 because it's dictated by VTY config */
5183testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
5184 var RSL_Message rsl_unused, rsl_msg;
5185 var GsmRrMessage rr;
5186 f_init(1, false);
5187 f_sleep(1.0);
5188 f_vty_allow_tch_for_signalling(false, 0);
5189 f_disable_all_sdcch();
5190
5191 /* RA containing reason=LU */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005192 f_ipa_tx(ts_RSL_CHAN_RQD('02'O, 2342));
5193 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005194 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
5195 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
5196 setverdict(fail, "Expected reject");
5197 }
5198
5199 f_vty_allow_tch_for_signalling(true, 0);
5200 f_enable_all_sdcch();
5201 f_shutdown_helper();
5202}
5203
5204/* Request a voice channel with all SDCCH exhausted, it is
5205 * expected that TCH channel will be allocated since the VTY option is only
5206 * aimed at signalling requests */
5207private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
5208 g_pars := f_gen_test_hdlr_pars();
5209 g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
5210
5211 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5212 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5213 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5214 var template uint3_t tsc := ?;
5215
5216 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5217 f_create_bssmap_exp(l3_enc);
5218 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5219 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5220
5221 /* we should now have a COMPL_L3 at the MSC */
5222 timer T := 10.0;
5223 T.start;
5224 alt {
5225 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5226 [] T.timeout {
5227 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5228 }
5229 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005230 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005231}
5232testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
5233 var MSC_ConnHdlr vc_conn;
5234 f_init(1, true);
5235 f_sleep(1.0);
5236 f_vty_allow_tch_for_signalling(false, 0);
5237 f_disable_all_sdcch();
5238
5239 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
5240 vc_conn.done;
5241
5242 f_vty_allow_tch_for_signalling(true, 0);
5243 f_enable_all_sdcch();
5244 f_shutdown_helper();
5245}
5246
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005247/* Test Osmux setup BSC<->MSC */
5248testcase TC_assignment_osmux_cn() runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005249 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5250 var MSC_ConnHdlr vc_conn;
5251
5252 /* See note above */
5253 var RSL_IE_Body mr_conf := {
5254 other := {
5255 len := 2,
5256 payload := '2804'O
5257 }
5258 };
5259
5260 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5261 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5262 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
5263 pars.expect_mr_conf_ie := mr_conf;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02005264 pars.use_osmux_cn := true;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005265
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02005266 g_osmux_enabled_cn := true;
5267 f_init(1, true);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005268 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005269 f_vty_amr_start_mode_set(false, "1");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005270
5271 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5272 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005273
5274 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01005275 f_shutdown_helper();
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005276}
5277
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005278/* Test Osmux setup BTS<->BSC */
5279testcase TC_assignment_osmux_bts() runs on test_CT {
5280 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5281 var MSC_ConnHdlr vc_conn;
5282
5283 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5284 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5285 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
5286 pars.expect_mr_conf_ie := mr_conf_amr_5_90;
5287 pars.use_osmux_bts := true;
5288
5289 g_osmux_enabled_bts := true;
5290 f_init(1, true);
5291 f_sleep(1.0);
5292 f_vty_amr_start_mode_set(false, "1");
5293
5294 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5295 vc_conn.done;
5296
5297 f_vty_amr_start_mode_restore(false);
5298 f_shutdown_helper();
5299}
5300
5301/* Test Osmux setup BTS<->BSC<->MSC */
5302testcase TC_assignment_osmux() runs on test_CT {
5303 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5304 var MSC_ConnHdlr vc_conn;
5305
5306 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5307 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5308 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
5309 pars.expect_mr_conf_ie := mr_conf_amr_5_90;
5310 pars.use_osmux_cn := true;
5311 pars.use_osmux_bts := true;
5312
5313 g_osmux_enabled_cn := true;
5314 g_osmux_enabled_bts := true;
5315 f_init(1, true);
5316 f_sleep(1.0);
5317 f_vty_amr_start_mode_set(false, "1");
5318
5319 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5320 vc_conn.done;
5321
5322 f_vty_amr_start_mode_restore(false);
5323 f_shutdown_helper();
5324}
5325
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005326/* test the procedure of the MSC requesting a Classmark Update:
5327 * a) BSSMAP Classmark Request should result in RR CLASSMARK ENQUIRY,
5328 * b) L3 RR CLASSMARK CHANGE should result in BSSMAP CLASSMARK UPDATE */
Harald Welte898113b2018-01-31 18:32:21 +01005329private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005330 g_pars := f_gen_test_hdlr_pars();
5331
Harald Weltea0630032018-03-20 21:09:55 +01005332 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005333 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005334
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005335 BSSAP.send(ts_BSSMAP_ClassmarkRequest);
5336 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
5337
Harald Welte898113b2018-01-31 18:32:21 +01005338 f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
5339 BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
5340 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005341
5342 f_perform_clear();
Harald Welte898113b2018-01-31 18:32:21 +01005343}
5344testcase TC_classmark() runs on test_CT {
5345 var MSC_ConnHdlr vc_conn;
5346 f_init(1, true);
5347 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005348 vc_conn := f_start_handler(refers(f_tc_classmark));
Harald Welte898113b2018-01-31 18:32:21 +01005349 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005350 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005351}
5352
Harald Welteeddf0e92020-06-21 19:42:15 +02005353/* Send a CommonID from the simulated MSC and verify that the information is used to
5354 * fill BSC-internal data structures (specifically, bsc_subscr associated with subscr_conn) */
5355private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
5356 g_pars := f_gen_test_hdlr_pars();
5357 f_MscConnHdlr_init_vty();
5358
5359 f_create_chan_and_exp();
5360 /* we should now have a COMPL_L3 at the MSC */
Harald Welteeddf0e92020-06-21 19:42:15 +02005361
5362 /* Send CommonID */
5363 BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
5364
5365 /* Use VTY to verify that the IMSI of the subscr_conn is set */
5366 var charstring regex := "*(IMSI: " & hex2str(g_pars.imsi) & ")*";
5367 f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
5368
5369 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005370
5371 f_perform_clear();
Harald Welteeddf0e92020-06-21 19:42:15 +02005372}
5373testcase TC_common_id() runs on test_CT {
5374 var MSC_ConnHdlr vc_conn;
5375 f_init(1, true);
5376 f_sleep(1.0);
5377 vc_conn := f_start_handler(refers(f_tc_common_id));
5378 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005379 f_shutdown_helper();
Harald Welteeddf0e92020-06-21 19:42:15 +02005380}
5381
Harald Weltee3bd6582018-01-31 22:51:25 +01005382private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005383 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005384 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005385 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005386
Harald Weltee3bd6582018-01-31 22:51:25 +01005387 /* send the single message we want to send */
5388 f_rsl_send_l3(l3);
5389}
5390
5391private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr {
5392 timer T := sec;
5393 var PDU_BSSAP bssap;
Harald Welte898113b2018-01-31 18:32:21 +01005394 T.start;
5395 alt {
Harald Weltee3bd6582018-01-31 22:51:25 +01005396 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap {
5397 setverdict(fail, "Unexpected BSSMAP ", bssap);
Daniel Willmannafce8662018-07-06 23:11:32 +02005398 mtc.stop;
Harald Welte898113b2018-01-31 18:32:21 +01005399 }
5400 [] T.timeout {
5401 setverdict(pass);
5402 }
5403 }
5404}
5405
Harald Weltee3bd6582018-01-31 22:51:25 +01005406/* unsolicited ASSIGNMENT FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5407private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
5408 f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
5409 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005410 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005411}
Harald Welte898113b2018-01-31 18:32:21 +01005412testcase TC_unsol_ass_fail() runs on test_CT {
5413 var MSC_ConnHdlr vc_conn;
5414 f_init(1, true);
5415 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005416 vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
Harald Welte898113b2018-01-31 18:32:21 +01005417 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005418 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005419}
Harald Welte552620d2017-12-16 23:21:36 +01005420
Harald Welteea99a002018-01-31 20:46:43 +01005421
5422/* unsolicited ASSIGNMENT COMPLETE (without ASSIGN) from MS shouldn't bring BSC down */
5423private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005424 f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
5425 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005426 f_perform_clear();
Harald Welteea99a002018-01-31 20:46:43 +01005427}
5428testcase TC_unsol_ass_compl() runs on test_CT {
5429 var MSC_ConnHdlr vc_conn;
5430 f_init(1, true);
5431 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005432 vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
Harald Welteea99a002018-01-31 20:46:43 +01005433 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005434 f_shutdown_helper();
Harald Welteea99a002018-01-31 20:46:43 +01005435}
5436
5437
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005438/* unsolicited HANDOVER FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5439private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005440 f_est_single_l3(ts_RRM_HandoverFailure('00'O));
5441 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005442 f_perform_clear();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005443}
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005444testcase TC_unsol_ho_fail() runs on test_CT {
5445 var MSC_ConnHdlr vc_conn;
5446 f_init(1, true);
5447 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005448 vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005449 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005450 f_shutdown_helper();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005451}
5452
5453
Harald Weltee3bd6582018-01-31 22:51:25 +01005454/* short message from MS should be ignored */
5455private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005456 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005457 f_create_chan_and_exp();
Harald Weltee3bd6582018-01-31 22:51:25 +01005458 /* we should now have a COMPL_L3 at the MSC */
Harald Weltee3bd6582018-01-31 22:51:25 +01005459
5460 /* send short message */
5461 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
5462 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005463 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005464}
5465testcase TC_err_82_short_msg() runs on test_CT {
5466 var MSC_ConnHdlr vc_conn;
5467 f_init(1, true);
5468 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005469 vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
Harald Weltee3bd6582018-01-31 22:51:25 +01005470 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005471 f_shutdown_helper();
Harald Weltee3bd6582018-01-31 22:51:25 +01005472}
5473
5474
Harald Weltee9e02e42018-01-31 23:36:25 +01005475/* 24.008 8.4 Unknown message must trigger RR STATUS */
5476private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
5477 f_est_single_l3(ts_RRM_UL_REL('00'O));
5478 timer T := 3.0
5479 alt {
5480 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
5481 setverdict(pass);
5482 }
5483 [] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
Harald Welte458fd372018-03-21 11:26:23 +01005484 [] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
Harald Weltee9e02e42018-01-31 23:36:25 +01005485 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005486 f_perform_clear();
Harald Weltee9e02e42018-01-31 23:36:25 +01005487}
5488testcase TC_err_84_unknown_msg() runs on test_CT {
5489 var MSC_ConnHdlr vc_conn;
5490 f_init(1, true);
5491 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005492 vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
Harald Weltee9e02e42018-01-31 23:36:25 +01005493 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005494 f_shutdown_helper();
Harald Weltee9e02e42018-01-31 23:36:25 +01005495}
5496
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005497/***********************************************************************
5498 * Handover
5499 ***********************************************************************/
5500
Harald Welte94e0c342018-04-07 11:33:23 +02005501/* execute a "bts <0-255> trx <0-255> timeslot <0-7> " command on given Dchan */
5502private function f_vty_ts_action(charstring suffix, integer bts_nr, integer trx_nr, integer ts_nr)
5503runs on test_CT {
5504 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5505 " timeslot "&int2str(ts_nr)&" ";
5506 f_vty_transceive(BSCVTY, cmd & suffix);
5507}
5508
Harald Welte261af4b2018-02-12 21:20:39 +01005509/* 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 +07005510private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
5511 uint8_t bts_nr, uint8_t trx_nr,
5512 in RslChannelNr chan_nr)
5513{
Harald Welte261af4b2018-02-12 21:20:39 +01005514 /* FIXME: resolve those from component-global state */
5515 var integer ts_nr := chan_nr.tn;
5516 var integer ss_nr;
5517 if (ischosen(chan_nr.u.ch0)) {
5518 ss_nr := 0;
5519 } else if (ischosen(chan_nr.u.lm)) {
5520 ss_nr := chan_nr.u.lm.sub_chan;
5521 } else if (ischosen(chan_nr.u.sdcch4)) {
5522 ss_nr := chan_nr.u.sdcch4.sub_chan;
5523 } else if (ischosen(chan_nr.u.sdcch8)) {
5524 ss_nr := chan_nr.u.sdcch8.sub_chan;
5525 } else {
5526 setverdict(fail, "Invalid ChanNr ", chan_nr);
Daniel Willmannafce8662018-07-06 23:11:32 +02005527 mtc.stop;
Harald Welte261af4b2018-02-12 21:20:39 +01005528 }
5529
5530 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5531 " timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005532 f_vty_transceive(pt, cmd & suffix);
Harald Welte261af4b2018-02-12 21:20:39 +01005533}
5534
Neels Hofmeyr91401012019-07-11 00:42:35 +02005535/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
5536 * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor
5537 * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
5538 * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
5539 * pair, not really to a specific BTS number. */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005540private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
5541 in RslChannelNr chan_nr, uint8_t new_bts_nr)
5542{
5543 f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
Harald Welte261af4b2018-02-12 21:20:39 +01005544}
5545
5546/* intra-BSC hand-over between BTS0 and BTS1 */
5547private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02005548 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5549 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte261af4b2018-02-12 21:20:39 +01005550
5551 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5552 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5553
Harald Weltea0630032018-03-20 21:09:55 +01005554 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005555 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Harald Welte261af4b2018-02-12 21:20:39 +01005556
5557 var HandoverState hs := {
5558 rr_ho_cmpl_seen := false,
5559 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005560 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005561 expect_target_tsc := c_BtsParams[1].tsc
Harald Welte261af4b2018-02-12 21:20:39 +01005562 };
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005563 /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005564 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
Harald Welte261af4b2018-02-12 21:20:39 +01005565 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5566 f_rslem_suspend(RSL1_PROC);
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005567
5568 /* From the MGW perspective, a handover is is characterized by
5569 * performing one MDCX operation with the MGW. So we expect to see
5570 * one more MDCX during handover. */
5571 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5572
Harald Welte261af4b2018-02-12 21:20:39 +01005573 alt {
5574 [] as_handover(hs);
Harald Welte261af4b2018-02-12 21:20:39 +01005575 }
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005576
Philipp Maier4dae0652018-11-12 12:03:26 +01005577 /* Since this is an internal handover we expect the BSC to inform the
5578 * MSC about the event */
5579 BSSAP.receive(tr_BSSMAP_HandoverPerformed);
5580
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005581 /* Check the amount of MGCP transactions is still consistant with the
5582 * test expectation */
5583 f_check_mgcp_expectations()
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005584
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005585 var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
5586
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005587 /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
5588 * 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 +02005589 f_verify_encr_info(chan_act);
5590
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005591 f_chan_act_verify_tsc(chan_act, c_BtsParams[1].tsc);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005592
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005593 f_perform_clear(RSL1, RSL1_PROC);
5594
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005595 f_sleep(0.5);
Harald Welte261af4b2018-02-12 21:20:39 +01005596}
5597
5598testcase TC_ho_int() runs on test_CT {
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005599 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte261af4b2018-02-12 21:20:39 +01005600 var MSC_ConnHdlr vc_conn;
5601 f_init(2, true);
5602 f_sleep(1.0);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005603
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005604 pars.expect_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005605
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005606 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005607
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005608 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
Harald Welte261af4b2018-02-12 21:20:39 +01005609 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005610
5611 /* from f_establish_fully() */
5612 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5613 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5614 /* from handover */
5615 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5616 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5617 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5618 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005619 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5620 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005621 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005622 f_shutdown_helper();
Harald Welte261af4b2018-02-12 21:20:39 +01005623}
Harald Weltee9e02e42018-01-31 23:36:25 +01005624
Oliver Smith7eabd312021-07-12 14:18:56 +02005625function 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 +02005626 var MSC_ConnHdlr vc_conn;
5627 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5628 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
5629
5630 f_init(2, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02005631 f_vty_encryption_a5(enc_a5);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005632 f_sleep(1.0);
5633
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005634 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005635
5636 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
5637 vc_conn.done;
5638
5639 /* from f_establish_fully() */
5640 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5641 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5642 /* from handover */
5643 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5644 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5645 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5646 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005647 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5648 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005649 f_ctrs_bsc_and_bts_verify();
Oliver Smith7eabd312021-07-12 14:18:56 +02005650 f_vty_encryption_a5_reset();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005651 f_shutdown_helper();
5652}
5653
5654testcase TC_ho_int_a5_0() runs on test_CT {
5655 f_tc_ho_int_a5('01'O);
5656}
5657
5658testcase TC_ho_int_a5_1() runs on test_CT {
5659 f_tc_ho_int_a5('02'O);
5660}
5661
5662testcase TC_ho_int_a5_3() runs on test_CT {
5663 f_tc_ho_int_a5('08'O);
5664}
5665
5666testcase TC_ho_int_a5_4() runs on test_CT {
Oliver Smith7eabd312021-07-12 14:18:56 +02005667 f_tc_ho_int_a5('10'O, "0 1 3 4");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005668}
5669
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005670/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
5671private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
5672 g_pars := f_gen_test_hdlr_pars();
5673 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5674 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005675
5676 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5677 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5678
5679 f_establish_fully(ass_cmd, exp_compl);
5680 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
5681
5682 var HandoverState hs := {
5683 rr_ho_cmpl_seen := false,
5684 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005685 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005686 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005687 };
5688 /* issue hand-over command on VTY */
5689 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
5690 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5691 f_rslem_suspend(RSL1_PROC);
5692
5693 /* From the MGW perspective, a handover is is characterized by
5694 * performing one MDCX operation with the MGW. So we expect to see
5695 * one more MDCX during handover. */
5696 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5697
5698 var RSL_Message rsl;
5699 var PDU_ML3_NW_MS l3;
5700 var RslChannelNr new_chan_nr;
5701 var GsmArfcn arfcn;
5702 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
5703 l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
5704 if (not ischosen(l3.msgs.rrm.handoverCommand)) {
5705 setverdict(fail, "Expected handoverCommand");
5706 mtc.stop;
5707 }
5708 }
5709 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
5710 new_chan_nr, arfcn);
5711
5712 f_rslem_register(0, new_chan_nr, RSL1_PROC);
5713
5714 /* resume processing of RSL DChan messages, which was temporarily suspended
5715 * before performing a hand-over */
5716 f_rslem_resume(RSL1_PROC);
5717 RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
5718
5719 f_sleep(1.0);
5720
5721 /* Handover fails because no HANDO DET appears on the new lchan,
5722 * and the old lchan reports a Radio Link Failure. */
5723 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
5724
5725 var PDU_BSSAP rx_clear_request;
5726 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5727 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5728 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5729
5730 var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
5731
5732 var MgcpCommand mgcp;
5733 interleave {
5734 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
5735 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005736 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005737 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005738 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005739 }
5740 [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005741 [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005742 RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005743 f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005744 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005745 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5746 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5747 }
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005748 }
5749
5750 f_sleep(0.5);
5751 setverdict(pass);
5752}
5753testcase TC_ho_int_radio_link_failure() runs on test_CT {
5754 var MSC_ConnHdlr vc_conn;
5755 f_init(2, true);
5756 f_sleep(1.0);
5757
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005758 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005759
5760 vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
5761 vc_conn.done;
5762
5763 /* from f_establish_fully() */
5764 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5765 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5766 /* from handover */
5767 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5768 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
5769 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5770 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005771 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5772 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005773 f_ctrs_bsc_and_bts_verify();
5774 f_shutdown_helper();
5775}
5776
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005777/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005778private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005779 var MgcpCommand mgcp;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005780 var template MgcpResponse mgcp_resp;
5781 var MGCP_RecvFrom mrf;
5782 var template MgcpMessage msg_resp;
5783 var template MgcpMessage msg_dlcx := {
5784 command := tr_DLCX()
5785 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005786
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005787 if (g_pars.aoip) {
5788 MGCP.receive(tr_DLCX()) -> value mgcp {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005789 log("Got first DLCX: ", mgcp);
5790 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005791 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005792
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005793 MGCP.receive(tr_DLCX()) -> value mgcp {
5794 log("Got second DLCX: ", mgcp);
5795 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
5796 };
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005797 } else {
5798 /* For SCCPLite, BSC doesn't handle the MSC-side */
5799 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
5800 log("Got first DLCX: ", mrf.msg.command);
5801 msg_resp := {
5802 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
5803 }
5804 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
5805 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005806 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005807}
5808
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005809private function f_ho_out_of_this_bsc(template (omit) BSSMAP_oldToNewBSSIEs exp_oldToNewBSSIEs := omit) runs on MSC_ConnHdlr {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005810
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01005811 var NcellReports neighbor_rep := {
5812 { rxlev := 20, bcch_freq := 0, bsic := 11 }
5813 };
5814 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
5815 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
5816 l3_mr, 0));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005817
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005818 BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005819
5820 f_sleep(0.5);
5821 /* The MSC negotiates Handover Request and Handover Request Ack with
5822 * the other BSS and comes back with a BSSMAP Handover Command
5823 * containing an RR Handover Command coming from the target BSS... */
5824
5825 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5826 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
5827 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5828 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
5829 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
5830
5831 /* expect the Handover Command to go out on RR */
5832 var RSL_Message rsl_ho_cmd
5833 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
5834 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
5835 var RSL_IE_Body rsl_ho_cmd_l3;
5836 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
5837 log("RSL message contains no L3 Info IE, expected RR Handover Command");
5838 setverdict(fail);
5839 } else {
5840 log("Found L3 Info: ", rsl_ho_cmd_l3);
5841 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
5842 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
5843 setverdict(fail);
5844 } else {
5845 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
5846 setverdict(pass);
5847 }
5848 }
5849
5850 /* When the other BSS has reported a completed handover, this side is
5851 * torn down. */
5852
5853 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_HANDOVER_SUCCESSFUL;
5854 var BssmapCause cause := enum2int(cause_val);
5855 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5856
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005857 f_expect_dlcx_conns();
Pau Espin Pedrol06199952021-06-15 11:30:00 +02005858
5859 interleave {
5860 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
5861 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
5862 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005863 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5864 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5865 }
Pau Espin Pedrol06199952021-06-15 11:30:00 +02005866 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005867 setverdict(pass);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005868}
5869
5870private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
5871 g_pars := f_gen_test_hdlr_pars();
5872 var PDU_BSSAP ass_req := f_gen_ass_req();
5873 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5874 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5875 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5876 f_establish_fully(ass_req, exp_compl);
5877
5878 f_ho_out_of_this_bsc();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005879}
5880testcase TC_ho_out_of_this_bsc() runs on test_CT {
5881 var MSC_ConnHdlr vc_conn;
5882
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01005883 f_init_vty();
5884 f_bts_0_cfg(BSCVTY,
5885 {"neighbor-list mode automatic",
5886 "handover 1",
5887 "handover algorithm 2",
5888 "handover2 window rxlev averaging 1",
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01005889 "no neighbors",
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01005890 "neighbor lac 99 arfcn 123 bsic any"});
5891 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
5892
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005893 f_init(1, true);
5894 f_sleep(1.0);
5895
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005896 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005897
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005898 vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
5899 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005900
5901 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5902 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5903 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5904 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5905 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
5906 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
5907 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005908 f_shutdown_helper();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005909}
5910
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005911private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
5912 template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
Vadim Yanitskiy2ef6a2f2020-10-08 23:17:32 +07005913 template (present) OCT1 dlci := ?,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07005914 octetstring l3 := '0123456789'O)
5915runs on MSC_ConnHdlr {
Neels Hofmeyr43654812020-09-25 01:35:35 +02005916 /* The old lchan and conn should still be active. See that arbitrary L3
5917 * is still going through. */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005918 rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
Neels Hofmeyr43654812020-09-25 01:35:35 +02005919 var template PDU_BSSAP exp_data := {
5920 discriminator := '1'B,
5921 spare := '0000000'B,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07005922 dlci := dlci,
5923 lengthIndicator := lengthof(l3),
Neels Hofmeyr43654812020-09-25 01:35:35 +02005924 pdu := {
5925 dtap := l3
5926 }
5927 };
5928 BSSAP.receive(exp_data);
5929 setverdict(pass);
5930}
5931
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005932private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
5933 template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07005934 template (value) OCT1 dlci := '00'O,
5935 octetstring l3 := '0123456789'O)
5936runs on MSC_ConnHdlr {
5937 BSSAP.send(PDU_BSSAP:{
5938 discriminator := '1'B,
5939 spare := '0000000'B,
5940 dlci := dlci,
5941 lengthIndicator := lengthof(l3),
5942 pdu := {
5943 dtap := l3
5944 }
5945 });
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005946 rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07005947 setverdict(pass);
5948}
5949
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005950/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
5951 * simply never sends a BSSMAP Handover Command. */
5952private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01005953 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005954
5955 var PDU_BSSAP ass_req := f_gen_ass_req();
5956 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5957 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5958 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5959 f_establish_fully(ass_req, exp_compl);
5960
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01005961 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005962 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
5963
5964 BSSAP.receive(tr_BSSMAP_HandoverRequired);
5965
5966 /* osmo-bsc should time out 10 seconds after the handover started.
5967 * Let's give it a bit extra. */
5968 f_sleep(15.0);
5969
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07005970 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005971 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005972 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005973}
5974testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
5975 var MSC_ConnHdlr vc_conn;
5976
5977 f_init(1, true);
5978 f_sleep(1.0);
5979
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005980 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005981
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005982 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
5983 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005984
5985 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5986 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5987 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5988 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
5989 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
5990 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
5991 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005992 f_shutdown_helper();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005993}
5994
5995/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
5996 * RR Handover Failure. */
5997private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01005998 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005999
6000 var PDU_BSSAP ass_req := f_gen_ass_req();
6001 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6002 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6003 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6004 f_establish_fully(ass_req, exp_compl);
6005
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006006 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006007 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6008
6009 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6010
6011 f_sleep(0.5);
6012 /* The MSC negotiates Handover Request and Handover Request Ack with
6013 * the other BSS and comes back with a BSSMAP Handover Command
6014 * containing an RR Handover Command coming from the target BSS... */
6015
6016 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6017 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6018 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6019 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6020 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6021
6022 /* expect the Handover Command to go out on RR */
6023 var RSL_Message rsl_ho_cmd
6024 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6025 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6026 var RSL_IE_Body rsl_ho_cmd_l3;
6027 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6028 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6029 setverdict(fail);
6030 } else {
6031 log("Found L3 Info: ", rsl_ho_cmd_l3);
6032 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6033 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6034 setverdict(fail);
6035 } else {
6036 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6037 setverdict(pass);
6038 }
6039 }
6040
6041 f_sleep(0.2);
6042 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
6043
6044 /* Should tell the MSC about the failure */
6045 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6046
6047 f_sleep(1.0);
6048
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006049 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006050 f_sleep(1.0);
6051
6052 setverdict(pass);
6053 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006054 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006055}
6056testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
6057 var MSC_ConnHdlr vc_conn;
6058
6059 f_init(1, true);
6060 f_sleep(1.0);
6061
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006062 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006063
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006064 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
6065 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006066
6067 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6068 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6069 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6070 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6071 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6072 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
6073 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006074 f_shutdown_helper();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006075}
6076
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006077/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
6078 * (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 +02006079 * and the lchan is released. */
6080private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006081 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006082
6083 var PDU_BSSAP ass_req := f_gen_ass_req();
6084 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6085 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6086 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6087 f_establish_fully(ass_req, exp_compl);
6088
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006089 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006090 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6091
6092 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6093
6094 f_sleep(0.5);
6095 /* The MSC negotiates Handover Request and Handover Request Ack with
6096 * the other BSS and comes back with a BSSMAP Handover Command
6097 * containing an RR Handover Command coming from the target BSS... */
6098
6099 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6100 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6101 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6102 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6103 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6104
6105 /* expect the Handover Command to go out on RR */
6106 var RSL_Message rsl_ho_cmd
6107 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6108 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6109 var RSL_IE_Body rsl_ho_cmd_l3;
6110 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6111 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6112 setverdict(fail);
6113 } else {
6114 log("Found L3 Info: ", rsl_ho_cmd_l3);
6115 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6116 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6117 setverdict(fail);
6118 } else {
6119 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6120 setverdict(pass);
6121 }
6122 }
6123
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006124 /* We get neither success nor failure report from the remote BSS. Eventually T8 times out and we run into 3GPP
6125 * TS 48.008 3.1.5.3.3 "Abnormal Conditions": Clear Request should go to the MSC, and RR should be released
6126 * after Clear Command */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006127
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006128 var PDU_BSSAP rx_clear_request;
Neels Hofmeyre1797aa2019-07-09 19:34:04 +02006129 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
6130 log("Got BSSMAP Clear Request");
6131 /* Instruct BSC to clear channel */
6132 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6133 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6134
6135 var MgcpCommand mgcp;
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006136 interleave {
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01006137 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
6138 log("Got Deact SACCH");
6139 }
Harald Welte924b6ea2019-02-04 01:05:34 +01006140 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
Neels Hofmeyr211169d2018-11-07 00:37:29 +01006141 log("Got RR Release");
6142 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02006143 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006144 log("Got RF Chan Rel");
6145 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02006146 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006147 }
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006148 }
6149
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006150 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006151 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006152 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006153
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006154 setverdict(pass);
6155 f_sleep(1.0);
6156}
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006157testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006158 var MSC_ConnHdlr vc_conn;
6159
6160 f_init(1, true);
6161 f_sleep(1.0);
6162
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006163 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006164
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006165 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006166 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006167
6168 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6169 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6170 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6171 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6172 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6173 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6174 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006175 f_shutdown_helper();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006176}
6177
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006178private 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 +01006179 var PDU_BSSAP rx_bssap;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006180 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6181 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6182 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6183 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6184 * before we get started. */
6185 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6186 f_rslem_register(0, new_chan_nr);
6187 g_chan_nr := new_chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06006188 var uint3_t expect_target_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006189 f_sleep(1.0);
6190
6191 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6192 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006193 var default as_media := activate(as_Media());
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006194
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01006195 var PDU_BSSAP ho_req := f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
6196 cell_id_source := g_pars.cell_id_source,
6197 oldToNewBSSIEs := oldToNewBSSIEs,
6198 enc := g_pars.encr);
6199 if (g_pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr) {
6200 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, ho_req));
6201 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6202 } else {
6203 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, omit));
6204 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6205 BSSAP.send(ho_req);
6206 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006207
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006208 alt {
6209 [] BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap {
6210 if (g_pars.expect_ho_fail) {
6211 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6212 "Expected Handover Request to fail, but got Handover Request Ack")
6213 }
6214 }
6215 [] BSSAP.receive(tr_BSSMAP_HandoverFailure) -> value rx_bssap {
6216 if (not g_pars.expect_ho_fail) {
6217 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6218 "Expected Handover Request to succeed, but got Handover Failure")
6219 }
6220 // TODO: evaluate correct cause value. But osmo-bsc doesn't seem to send meaningful causes yet!
6221 // For now just accept any cause.
6222 BSSAP.receive(tr_BSSMAP_ClearRequest);
6223 setverdict(pass);
6224 return;
6225 }
6226 }
6227
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006228 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6229
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006230 /* we're sure that the channel activation is done now, verify the parameters in it */
6231 var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
6232 f_verify_encr_info(chan_act);
6233 f_chan_act_verify_tsc(chan_act, expect_target_tsc);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006234
Neels Hofmeyr46e16e52022-02-23 17:04:00 +01006235 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.codecList)) {
6236 if (not g_pars.aoip) {
6237 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6238 "handoverRequestAck: Expected no Speech Codec List (BSS Supported), because this is not AoIP");
6239 }
6240 /* TODO: check actual codecs? */
6241 } else {
6242 if (g_pars.aoip) {
6243 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6244 "handoverRequestAck: Expected Speech Codec List (BSS Supported), but none found");
6245 }
6246 }
6247
6248 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.speechCodec)) {
6249 if (not g_pars.aoip) {
6250 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6251 "handoverRequestAck: Expected no Speech Codec (Chosen), because this is not AoIP");
6252 }
6253 /* TODO: check actual codec? */
6254 } else {
6255 if (g_pars.aoip) {
6256 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6257 "handoverRequestAck: Expected Speech Codec (Chosen), but none found");
6258 }
6259 }
6260
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006261 var octetstring ho_command_str;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006262 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6263 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6264 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6265 log("L3 Info in HO Request Ack is ", ho_command);
6266
6267 var GsmArfcn arfcn;
6268 var RslChannelNr actual_new_chan_nr;
6269 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6270 actual_new_chan_nr, arfcn);
6271
6272 if (actual_new_chan_nr != new_chan_nr) {
6273 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6274 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6275 setverdict(fail);
6276 return;
6277 }
6278 log("Handover Command chan_nr is", actual_new_chan_nr);
6279
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006280 var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
6281 if (not match(got_tsc, expect_target_tsc)) {
6282 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6283 expect_target_tsc, " got ", got_tsc);
6284 mtc.stop;
6285 } else {
6286 log("handoverCommand: verified TSC = ", got_tsc);
6287 }
6288
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006289 /* Check the Cipher Mode Setting IE (shall be present during inter-RAT handover) */
6290 if (ispresent(ho_command.msgs.rrm.handoverCommand.cipherModeSetting)) {
6291 var CipherModeSetting_TV cms := ho_command.msgs.rrm.handoverCommand.cipherModeSetting;
6292 var template (present) CipherModeSetting_TV tr_cms := {
6293 sC := '0'B, /* no ciphering by default */
6294 algorithmIdentifier := '000'B,
6295 elementIdentifier := ?
6296 };
6297 if (ispresent(g_pars.encr) and g_pars.encr.enc_alg_expect != '01'O) { /* A5/N */
6298 tr_cms.algorithmIdentifier := f_cipher_mode_bssmap_to_rr(g_pars.encr.enc_alg_expect);
6299 tr_cms.sC := '1'B;
6300 }
6301 if (not match(cms, tr_cms)) {
6302 setverdict(fail, "RR Handover Command: unexpected Cipher Mode Setting IE: ",
6303 cms, ", expected: ", tr_cms);
6304 }
6305 } else {
6306 setverdict(fail, "RR Handover Command: Cipher Mode Setting IE is not present");
6307 }
6308
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006309 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6310 * tells the MS to handover to the new lchan. Here comes the new MS on
6311 * the new lchan with a Handover RACH: */
6312
6313 /* send handover detect */
6314
6315 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6316
6317 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6318
6319 /* send handover complete over the new channel */
6320
6321 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_HandoverComplete('00'O));
6322 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
6323 enc_PDU_ML3_MS_NW(l3_tx)));
6324
6325 BSSAP.receive(tr_BSSMAP_HandoverComplete);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006326 deactivate(as_media);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006327 setverdict(pass);
6328}
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006329
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006330private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006331 var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006332 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
6333 if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
6334 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006335 }
6336 if (g_pars.exp_fast_return) {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006337 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006338 } else {
6339 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006340 }
6341 f_ho_into_this_bsc(id, oldToNewBSSIEs);
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006342 if (g_pars.expect_ho_fail) {
6343 f_perform_clear_no_lchan();
6344 } else {
6345 f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
6346 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006347 setverdict(pass);
6348}
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006349function 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 +01006350 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006351
6352 f_init(1, true);
6353 f_sleep(1.0);
6354
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006355 f_vty_encryption_a5(vty_a5_cfg);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006356 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006357
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006358 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6359 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006360
6361 vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
6362 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006363
6364 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006365 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006366 if (pars.expect_ho_fail) {
6367 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6368 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:failed");
6369 } else {
6370 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6371 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
6372 }
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006373 f_ctrs_bsc_and_bts_verify();
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006374
6375 f_vty_encryption_a5_reset();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006376}
6377
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006378testcase TC_ho_into_this_bsc() runs on test_CT {
6379 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6380 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006381 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006382}
6383
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006384function f_tc_ho_into_this_bsc_a5(TestHdlrEncrParams encr, charstring vty_a5_cfg := VTY_A5_DEFAULT,
6385 boolean expect_fail := false) runs on test_CT {
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006386 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006387 pars.encr := encr;
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006388 pars.expect_ho_fail := expect_fail;
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006389 f_tc_ho_into_this_bsc_main(pars, vty_a5_cfg);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006390 f_shutdown_helper();
6391}
6392
6393testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006394 f_tc_ho_into_this_bsc_a5(f_encr_params('01'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006395}
6396
6397testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006398 f_tc_ho_into_this_bsc_a5(f_encr_params('02'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006399}
6400
6401testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006402 f_tc_ho_into_this_bsc_a5(f_encr_params('08'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006403}
6404
6405testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006406 f_tc_ho_into_this_bsc_a5(f_encr_params('10'O, kc128 := true), "3 4");
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006407}
6408
Neels Hofmeyr1951be22022-02-16 16:21:07 +01006409/* Report: in inter-BSC incoming handover, when the MSC omits the Chosen Encryption Algorithm IE in the Handover Request
6410 * message, then osmo-bsc starts an unencrypted lchan even if A5/0 is not permitted.
6411 *
6412 * This test verifies that the Encryption Information is present in the Channel Activation when the Chosen Enc Alg is
6413 * omitted.
6414 *
6415 * Related: SYS#5839
6416 */
6417testcase TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() runs on test_CT {
6418 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O, alg_chosen := omit));
6419}
6420
6421testcase TC_ho_into_this_bsc_a5_1_3() runs on test_CT {
6422 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O));
6423}
6424
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006425/* Send a permitted algo mask that does not intersect with osmo-bsc.cfg */
6426testcase TC_ho_into_this_bsc_a5_mismatch() runs on test_CT {
6427 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '18'O, alg_expect := '10'O), "0 1",
6428 expect_fail := true); // 0x18 = A5/3 and A5/4
6429}
6430
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006431testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
6432 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6433 pars.host_aoip_tla := "::6";
6434 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006435 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006436}
6437
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006438/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006439 to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006440 channel is later released (RR CHannel Release), should trigger inclusion of
6441 IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
6442 neighbors. */
6443testcase TC_srvcc_eutran_to_geran() runs on test_CT {
6444 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6445 pars.last_used_eutran_plmn := '323454'O;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006446 pars.exp_fast_return := true;
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006447 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006448
6449 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6450 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6451 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006452 f_shutdown_helper();
6453}
6454
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006455/* Same as TC_srvcc_eutran_to_geran, but enables ciphering on the target channel. */
6456testcase TC_srvcc_eutran_to_geran_a5_3() runs on test_CT {
6457 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6458 pars.encr := f_encr_params('08'O); /* only A5/3 */
6459 pars.last_used_eutran_plmn := '323454'O;
6460 pars.exp_fast_return := true;
6461 f_tc_ho_into_this_bsc_main(pars);
6462
6463 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6464 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6465 f_ctrs_bsc_and_bts_verify();
6466 f_shutdown_helper();
6467}
6468
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006469/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
6470 on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
6471 list when the channel is released. */
6472testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
6473 f_init_vty();
6474 f_vty_allow_srvcc_fast_return(true, 0)
6475
6476 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6477 pars.last_used_eutran_plmn := '323454'O;
6478 pars.exp_fast_return := false;
6479 f_tc_ho_into_this_bsc_main(pars);
6480 f_vty_allow_srvcc_fast_return(false, 0);
6481 f_shutdown_helper();
6482}
6483
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01006484/* Same as TC_srvcc_eutran_to_geran, but using SAI as serving Cell Identifier. SYS#5838 */
6485testcase TC_srvcc_eutran_to_geran_src_sai() runs on test_CT {
6486 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6487 pars.last_used_eutran_plmn := '323454'O;
6488 pars.cell_id_source := valueof(ts_CellID_SAI('123456'O, 300, 444));
6489 f_tc_ho_into_this_bsc_main(pars);
6490
6491 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6492 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6493 f_ctrs_bsc_and_bts_verify();
6494 f_shutdown_helper();
6495}
6496
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006497private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
6498 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
6499 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
6500 f_ho_into_this_bsc(id, oldToNewBSSIEs);
6501 f_ho_out_of_this_bsc(oldToNewBSSIEs);
6502 setverdict(pass);
6503}
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006504
6505private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
6506 runs on test_CT {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006507 var MSC_ConnHdlr vc_conn;
6508 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6509
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006510 f_init_vty();
6511 f_bts_0_cfg(BSCVTY,
6512 {"neighbor-list mode automatic",
6513 "handover 1",
6514 "handover algorithm 2",
6515 "handover2 window rxlev averaging 1",
6516 "no neighbors",
6517 "neighbor lac 99 arfcn 123 bsic any"});
6518 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6519
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006520 f_init(1, true);
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006521 if (disable_fast_return) {
6522 f_vty_allow_srvcc_fast_return(true, 0);
6523 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006524 f_sleep(1.0);
6525
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006526 f_ctrs_bsc_and_bts_handover_init();
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006527
6528 pars.last_used_eutran_plmn := '323454'O;
6529 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6530 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
6531
6532 vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
6533 vc_conn.done;
6534
6535 f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
6536 f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
6537 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
6538 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
6539 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
6540 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006541
6542 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
6543 f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006544 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006545
6546 if (disable_fast_return) {
6547 f_vty_allow_srvcc_fast_return(false, 0);
6548 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006549 f_shutdown_helper();
6550}
6551
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006552/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
6553 BSS Information" IE with "Last Used E-UTRAN PLMN Id".
6554 Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
6555 IE with "Last Used E-UTRAN PLMN Id" from first step. */
6556testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
6557 f_tc_srvcc_eutran_to_geran_ho_out_main(false);
6558}
6559/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
6560 * independently of fast-reture allowed/forbidden in local BTS */
6561testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
6562 f_tc_srvcc_eutran_to_geran_ho_out_main(true);
6563}
6564
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006565private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
6566 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6567 f_rslem_register(0, new_chan_nr);
6568 g_chan_nr := new_chan_nr;
6569 f_sleep(1.0);
6570
6571 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6572 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6573 activate(as_Media());
6574
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006575 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006576 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006577 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006578
6579 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6580
6581 var PDU_BSSAP rx_bssap;
6582 var octetstring ho_command_str;
6583
6584 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6585
6586 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6587 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6588 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6589 log("L3 Info in HO Request Ack is ", ho_command);
6590
6591 var GsmArfcn arfcn;
6592 var RslChannelNr actual_new_chan_nr;
6593 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6594 actual_new_chan_nr, arfcn);
6595
6596 if (actual_new_chan_nr != new_chan_nr) {
6597 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6598 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6599 setverdict(fail);
6600 return;
6601 }
6602 log("Handover Command chan_nr is", actual_new_chan_nr);
6603
Neels Hofmeyr61ca08d2019-05-06 23:52:22 +02006604 /* For deterministic test results, give some time for the MGW endpoint to be configured */
6605 f_sleep(1.0);
6606
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006607 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6608 * tells the MS to handover to the new lchan. In this case, the MS
6609 * reports a Handover Failure to the old BSS, which forwards a BSSMAP
6610 * Handover Failure to the MSC. The procedure according to 3GPP TS
6611 * 48.008 3.1.5.3.2 "Handover Failure" is then that the MSC sends a
6612 * BSSMAP Clear Command: */
6613
6614 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6615 var BssmapCause cause := enum2int(cause_val);
6616 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6617
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006618 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006619 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006620 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006621
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006622 setverdict(pass);
6623 f_sleep(1.0);
6624
6625 setverdict(pass);
6626}
6627testcase TC_ho_in_fail_msc_clears() runs on test_CT {
6628 var MSC_ConnHdlr vc_conn;
6629 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6630
6631 f_init(1, true);
6632 f_sleep(1.0);
6633
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006634 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006635
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006636 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6637 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006638
6639 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
6640 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006641
6642 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6643 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6644 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6645 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6646 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006647 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006648}
6649
6650private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
6651 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6652 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6653 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6654 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6655 * before we get started. */
6656 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6657 f_rslem_register(0, new_chan_nr);
6658 g_chan_nr := new_chan_nr;
6659 f_sleep(1.0);
6660
6661 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6662 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6663 activate(as_Media());
6664
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006665 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006666 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006667 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006668
6669 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6670
6671 var PDU_BSSAP rx_bssap;
6672 var octetstring ho_command_str;
6673
6674 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6675
6676 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6677 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6678 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6679 log("L3 Info in HO Request Ack is ", ho_command);
6680
6681 var GsmArfcn arfcn;
6682 var RslChannelNr actual_new_chan_nr;
6683 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6684 actual_new_chan_nr, arfcn);
6685
6686 if (actual_new_chan_nr != new_chan_nr) {
6687 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6688 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6689 setverdict(fail);
6690 return;
6691 }
6692 log("Handover Command chan_nr is", actual_new_chan_nr);
6693
6694 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6695 * tells the MS to handover to the new lchan. Here comes the new MS on
6696 * the new lchan with a Handover RACH: */
6697
6698 /* send handover detect */
6699
6700 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6701
6702 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6703
6704 /* The MSC chooses to clear the connection now, maybe we got the
6705 * Handover RACH on the new cell but the MS still signaled Handover
6706 * Failure to the old BSS? */
6707
6708 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6709 var BssmapCause cause := enum2int(cause_val);
6710 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6711
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006712 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006713 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006714 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006715
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006716 f_sleep(1.0);
6717}
6718testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
6719 var MSC_ConnHdlr vc_conn;
6720 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6721
6722 f_init(1, true);
6723 f_sleep(1.0);
6724
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006725 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006726
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006727 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6728 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006729
6730 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
6731 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006732
6733 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6734 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6735 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6736 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6737 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006738 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006739}
6740
6741/* The new BSS's lchan times out before the MSC decides that handover failed. */
6742private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
6743 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6744 f_rslem_register(0, new_chan_nr);
6745 g_chan_nr := new_chan_nr;
6746 f_sleep(1.0);
6747
6748 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6749 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr9b320c12022-04-07 00:19:01 +02006750 activate(as_Media(fail_on_dlcx := false));
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006751
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006752 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006753 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006754 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006755
6756 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6757
6758 var PDU_BSSAP rx_bssap;
6759 var octetstring ho_command_str;
6760
6761 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6762
6763 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6764 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6765 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6766 log("L3 Info in HO Request Ack is ", ho_command);
6767
6768 var GsmArfcn arfcn;
6769 var RslChannelNr actual_new_chan_nr;
6770 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6771 actual_new_chan_nr, arfcn);
6772
6773 if (actual_new_chan_nr != new_chan_nr) {
6774 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6775 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6776 setverdict(fail);
6777 return;
6778 }
6779 log("Handover Command chan_nr is", actual_new_chan_nr);
6780
6781 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6782 * tells the MS to handover to the new lchan. But the MS never shows up
6783 * on the new lchan. */
6784
6785 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6786
6787 /* Did osmo-bsc also send a Clear Request? */
6788 timer T := 0.5;
6789 T.start;
6790 alt {
6791 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
6792 [] T.timeout { }
6793 }
6794
6795 /* MSC plays along with a Clear Command (no matter whether osmo-bsc
6796 * asked for it, this is a Handover Failure after all). */
6797
6798 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6799 var BssmapCause cause := enum2int(cause_val);
6800 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6801
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006802 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006803 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006804 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006805
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006806 f_sleep(1.0);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006807}
6808testcase TC_ho_in_fail_no_detect() runs on test_CT {
6809 var MSC_ConnHdlr vc_conn;
6810 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6811
6812 f_init(1, true);
6813 f_sleep(1.0);
6814
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006815 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006816
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006817 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6818 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006819
6820 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect), pars);
6821 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006822
6823 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6824 f_ctrs_bsc_and_bts_add(0, "handover:error");
6825 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6826 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
6827 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006828 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006829}
6830
6831/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
6832private function f_tc_ho_in_fail_no_detect2(charstring id) runs on MSC_ConnHdlr {
6833 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6834 f_rslem_register(0, new_chan_nr);
6835 g_chan_nr := new_chan_nr;
6836 f_sleep(1.0);
6837
6838 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6839 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr9b320c12022-04-07 00:19:01 +02006840 activate(as_Media(fail_on_dlcx := false));
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006841
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006842 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006843 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006844 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006845
6846 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6847
6848 var PDU_BSSAP rx_bssap;
6849 var octetstring ho_command_str;
6850
6851 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6852
6853 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6854 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6855 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6856 log("L3 Info in HO Request Ack is ", ho_command);
6857
6858 var GsmArfcn arfcn;
6859 var RslChannelNr actual_new_chan_nr;
6860 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6861 actual_new_chan_nr, arfcn);
6862
6863 if (actual_new_chan_nr != new_chan_nr) {
6864 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6865 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6866 setverdict(fail);
6867 return;
6868 }
6869 log("Handover Command chan_nr is", actual_new_chan_nr);
6870
6871 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6872 * tells the MS to handover to the new lchan. But the MS never shows up
6873 * on the new lchan. */
6874
6875 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6876
6877 /* MSC plays dumb and sends no Clear Command */
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006878 var PDU_BSSAP rx_clear_request;
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006879
6880 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request {
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006881 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6882 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6883 };
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006884 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006885 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006886 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006887
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006888 f_sleep(1.0);
6889}
6890testcase TC_ho_in_fail_no_detect2() runs on test_CT {
6891 var MSC_ConnHdlr vc_conn;
6892 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6893
6894 f_init(1, true);
6895 f_sleep(1.0);
6896
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006897 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006898
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006899 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6900 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006901
6902 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
6903 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006904
6905 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6906 f_ctrs_bsc_and_bts_add(0, "handover:error");
6907 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6908 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
6909 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006910 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006911}
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006912
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01006913/* An incoming inter-BSC HO can either issue the Handover Request message attached to the initial SCCP N-Connect (as in
6914 * the other tests we have so far), or the first CR can be "empty" with the BSSAP request following later. Test the
6915 * empty N-Connect case. */
6916testcase TC_ho_into_this_bsc_sccp_cr_without_bssap() runs on test_CT {
6917 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6918 pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr := false;
6919 f_tc_ho_into_this_bsc_main(pars);
6920 f_shutdown_helper();
6921}
6922
Neels Hofmeyr91401012019-07-11 00:42:35 +02006923type record of charstring Commands;
6924
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006925private function f_bts_0_cfg(TELNETasp_PT pt, Commands cmds := {})
Neels Hofmeyr91401012019-07-11 00:42:35 +02006926{
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006927 f_vty_enter_cfg_bts(pt, 0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006928 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006929 f_vty_transceive(pt, cmds[i]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006930 }
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006931 f_vty_transceive(pt, "end");
Neels Hofmeyr91401012019-07-11 00:42:35 +02006932}
6933
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01006934private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
6935{
6936 f_vty_enter_cfg_cs7_inst(pt, 0);
6937 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
6938 f_vty_transceive(pt, cmds[i]);
6939 }
6940 f_vty_transceive(pt, "end");
6941}
6942
Neels Hofmeyr91401012019-07-11 00:42:35 +02006943private function f_probe_for_handover(charstring log_label,
6944 charstring log_descr,
6945 charstring handover_vty_cmd,
6946 boolean expect_handover,
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006947 boolean is_inter_bsc_handover := false,
6948 template uint3_t expect_target_tsc := ?)
Neels Hofmeyr91401012019-07-11 00:42:35 +02006949runs on MSC_ConnHdlr
6950{
Neels Hofmeyrb3fc8982020-05-11 00:16:42 +02006951 /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
6952 * lchans to be established on bts 1 or bts 2. */
6953 f_rslem_suspend(RSL1_PROC);
6954 f_rslem_suspend(RSL2_PROC);
6955
Neels Hofmeyr91401012019-07-11 00:42:35 +02006956 var RSL_Message rsl;
6957
6958 var charstring log_msg := " (expecting handover)"
6959 if (not expect_handover) {
6960 log_msg := " (expecting NO handover)";
6961 }
6962 log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg);
6963 f_vty_transceive(BSCVTY, handover_vty_cmd);
6964
Neels Hofmeyr91401012019-07-11 00:42:35 +02006965 timer T := 2.0;
6966 T.start;
6967
6968 alt {
6969 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
6970 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
6971 log("Rx L3 from net: ", l3);
6972 if (ischosen(l3.msgs.rrm.handoverCommand)) {
6973 var RslChannelNr new_chan_nr;
6974 var GsmArfcn arfcn;
6975 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
6976 new_chan_nr, arfcn);
6977 log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
6978 log(l3.msgs.rrm.handoverCommand);
6979
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006980 /* Verify correct TSC in handoverCommand */
6981 var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
6982 if (not match(got_tsc, expect_target_tsc)) {
6983 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6984 expect_target_tsc, " got ", got_tsc);
6985 mtc.stop;
6986 } else {
6987 log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
6988 expect_target_tsc, ")");
6989 }
6990
Neels Hofmeyr91401012019-07-11 00:42:35 +02006991 /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
6992 * matter on which BTS it really is, we're not going to follow through an entire handover
6993 * anyway. */
6994 f_rslem_register(0, new_chan_nr, RSL1_PROC);
6995 f_rslem_resume(RSL1_PROC);
6996 f_rslem_register(0, new_chan_nr, RSL2_PROC);
6997 f_rslem_resume(RSL2_PROC);
6998
6999 if (expect_handover and not is_inter_bsc_handover) {
7000 setverdict(pass);
7001 log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected.");
7002 } else {
7003 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. "
7004 & log_label & ": " & log_descr);
7005 }
7006
7007 log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
7008 /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with
7009 * Handover Failure. */
7010 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
7011
7012 /* target BTS is told to release lchan again; don't care which BTS nor what messages. */
7013 f_sleep(0.5);
7014 RSL1.clear;
7015 RSL2.clear;
7016 log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)");
7017 break;
7018 } else {
7019 repeat;
7020 }
7021 }
7022 [] BSSAP.receive(tr_BSSMAP_HandoverRequired) {
7023 if (expect_handover and is_inter_bsc_handover) {
7024 setverdict(pass);
7025 log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected.");
7026 } else {
7027 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. "
7028 & log_label & ": " & log_descr);
7029 }
7030
7031 log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)");
7032
7033 /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to
7034 * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required,
7035 * setting a short timeout and waiting is the only way. */
7036 log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out...");
7037 f_sleep(1.5);
7038 log("f_probe_for_handover(" & log_label & "): ...done");
7039
7040 break;
7041 }
7042 [] T.timeout {
7043 if (expect_handover) {
7044 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. "
7045 & log_label & ": " & log_descr);
7046 } else {
7047 setverdict(pass);
7048 log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected.");
7049 }
7050 log("f_probe_for_handover(" & log_label & "): done (got no Handover)");
7051 break;
7052 }
7053 }
7054
7055 f_rslem_resume(RSL1_PROC);
7056 f_rslem_resume(RSL2_PROC);
7057 f_sleep(3.0);
7058 RSL.clear;
7059
7060 log("f_probe_for_handover(" & log_label & "): done clearing");
7061}
7062
7063/* Test the effect of various neighbor configuration scenarios:
7064 *
7065 * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0.
7066 * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO.
7067 */
7068private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
7069 g_pars := f_gen_test_hdlr_pars();
7070 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
7071 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007072
7073 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
7074 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
7075
7076 /* Establish lchan at bts 0 */
7077 f_establish_fully(ass_cmd, exp_compl);
7078
7079 /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */
7080 f_vty_enter_cfg_network(BSCVTY);
7081 f_vty_transceive(BSCVTY, "timer T7 1");
7082 f_vty_transceive(BSCVTY, "end");
7083}
7084
7085private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
7086 f_tc_ho_neighbor_config_start();
7087
7088 /*
7089 * bts 0 ARFCN 871 BSIC 10
7090 * bts 1 ARFCN 871 BSIC 11
7091 * bts 2 ARFCN 871 BSIC 12
7092 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7093 */
7094
7095 log("f_tc_ho_neighbor_config: 1. No 'neighbor' config");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007096 f_bts_0_cfg(BSCVTY, {"no neighbors"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007097 f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
7098 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007099 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007100
7101 f_probe_for_handover("1.b", "HO to unknown cell does not start",
7102 "handover any to arfcn 13 bsic 39",
7103 false);
7104
7105 f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error",
7106 "handover any to arfcn 871 bsic 12",
7107 false);
7108
7109 f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
7110 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007111 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007112
7113 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007114}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007115testcase TC_ho_neighbor_config_1() runs on test_CT {
7116 var MSC_ConnHdlr vc_conn;
7117 f_init(3, true, guard_timeout := 60.0);
7118 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007119 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007120 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
7121 vc_conn.done;
7122
7123 /* f_tc_ho_neighbor_config_start() */
7124 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7125 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7126
7127 /* 1.a */
7128 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7129 * handover quickly by sending a Handover Failure message. */
7130 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7131 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7132 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7133 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007134 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7135 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007136
7137 /* 1.b */
7138 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7139 f_ctrs_bsc_and_bts_add(0, "handover:error");
7140
7141 /* 1.c */
7142 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7143 f_ctrs_bsc_and_bts_add(0, "handover:error");
7144
7145 /* 1.d */
7146 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7147 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7148 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7149 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007150 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7151 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007152
7153 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007154 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007155}
7156
Neels Hofmeyr91401012019-07-11 00:42:35 +02007157private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
7158 f_tc_ho_neighbor_config_start();
7159
7160 /*
7161 * bts 0 ARFCN 871 BSIC 10
7162 * bts 1 ARFCN 871 BSIC 11
7163 * bts 2 ARFCN 871 BSIC 12
7164 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7165 */
7166
7167 log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007168 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007169 f_sleep(0.5);
7170
7171 f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
7172 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007173 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007174
7175 f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
7176 "handover any to arfcn 871 bsic 12",
7177 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007178 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007179}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007180testcase TC_ho_neighbor_config_2() runs on test_CT {
7181 var MSC_ConnHdlr vc_conn;
7182 f_init(3, true, guard_timeout := 50.0);
7183 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007184 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007185 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
7186 vc_conn.done;
7187
7188 /* f_tc_ho_neighbor_config_start() */
7189 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7190 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7191
7192 /* 2.a */
7193 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7194 * handover quickly by sending a Handover Failure message. */
7195 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7196 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7197 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7198 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007199 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7200 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007201
7202 /* 2.b */
7203 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7204 f_ctrs_bsc_and_bts_add(0, "handover:error");
7205
7206 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007207 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007208}
7209
Neels Hofmeyr91401012019-07-11 00:42:35 +02007210private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
7211 f_tc_ho_neighbor_config_start();
7212
7213 /*
7214 * bts 0 ARFCN 871 BSIC 10
7215 * bts 1 ARFCN 871 BSIC 11
7216 * bts 2 ARFCN 871 BSIC 12
7217 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7218 */
7219
7220 log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007221 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007222 f_sleep(0.5);
7223
7224 f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor",
7225 "handover any to arfcn 871 bsic 11",
7226 false);
7227 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",
7228 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007229 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007230 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007231}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007232testcase TC_ho_neighbor_config_3() runs on test_CT {
7233 var MSC_ConnHdlr vc_conn;
7234 f_init(3, true, guard_timeout := 50.0);
7235 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007236 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007237 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
7238 vc_conn.done;
7239
7240 /* f_tc_ho_neighbor_config_start() */
7241 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7242 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7243
7244 /* 3.a */
7245 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7246 f_ctrs_bsc_and_bts_add(0, "handover:error");
7247
7248 /* 3.b */
7249 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7250 * handover quickly by sending a Handover Failure message. */
7251 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7252 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7253 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7254 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007255 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7256 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007257
7258 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007259 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007260}
7261
Neels Hofmeyr91401012019-07-11 00:42:35 +02007262private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
7263 f_tc_ho_neighbor_config_start();
7264
7265 /*
7266 * bts 0 ARFCN 871 BSIC 10
7267 * bts 1 ARFCN 871 BSIC 11
7268 * bts 2 ARFCN 871 BSIC 12
7269 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7270 */
7271
7272 log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007273 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007274 f_sleep(0.5);
7275
7276 f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor",
7277 "handover any to arfcn 871 bsic 11",
7278 false);
7279 f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor",
7280 "handover any to arfcn 871 bsic 12",
7281 false);
7282 f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
7283 "handover any to arfcn 123 bsic 45",
7284 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007285 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007286}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007287testcase TC_ho_neighbor_config_4() runs on test_CT {
7288 var MSC_ConnHdlr vc_conn;
7289 f_init(3, true, guard_timeout := 50.0);
7290 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007291 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007292 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
7293 vc_conn.done;
7294
7295 /* f_tc_ho_neighbor_config_start() */
7296 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7297 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7298
7299 /* 4.a */
7300 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7301 f_ctrs_bsc_and_bts_add(0, "handover:error");
7302
7303 /* 4.b */
7304 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7305 f_ctrs_bsc_and_bts_add(0, "handover:error");
7306
7307 /* 4.c */
7308 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7309 * handover quickly by timing out after the Handover Required message */
7310 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7311 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7312 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7313 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7314
7315 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007316 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007317}
7318
Neels Hofmeyr91401012019-07-11 00:42:35 +02007319private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
7320 f_tc_ho_neighbor_config_start();
7321
7322 /*
7323 * bts 0 ARFCN 871 BSIC 10
7324 * bts 1 ARFCN 871 BSIC 11
7325 * bts 2 ARFCN 871 BSIC 12
7326 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7327 */
7328
7329 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 +02007330 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007331 f_sleep(0.5);
7332
7333 f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
7334 "handover any to arfcn 871 bsic 12",
7335 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007336 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007337}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007338testcase TC_ho_neighbor_config_5() runs on test_CT {
7339 var MSC_ConnHdlr vc_conn;
7340 f_init(3, true);
7341 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007342 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007343 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
7344 vc_conn.done;
7345
7346 /* f_tc_ho_neighbor_config_start() */
7347 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7348 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7349
7350 /* 5 */
7351 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7352 * handover quickly by timing out after the Handover Required message */
7353 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7354 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7355 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7356 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7357
7358 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007359 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007360}
7361
Neels Hofmeyr91401012019-07-11 00:42:35 +02007362private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
7363 f_tc_ho_neighbor_config_start();
7364
7365 /*
7366 * bts 0 ARFCN 871 BSIC 10
7367 * bts 1 ARFCN 871 BSIC 11
7368 * bts 2 ARFCN 871 BSIC 12
7369 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7370 */
7371
7372 log("f_tc_ho_neighbor_config: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:"
7373 & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007374 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007375 f_sleep(0.5);
7376
7377 f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
7378 "handover any to arfcn 871 bsic 12",
7379 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007380 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007381}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007382testcase TC_ho_neighbor_config_6() runs on test_CT {
7383 var MSC_ConnHdlr vc_conn;
7384 f_init(3, true);
7385 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007386 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007387 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
7388 vc_conn.done;
7389
7390 /* f_tc_ho_neighbor_config_start() */
7391 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7392 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7393
7394 /* 6.a */
7395 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7396 * handover quickly by timing out after the Handover Required message */
7397 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7398 f_ctrs_bsc_and_bts_add(0, "handover:error");
7399
7400 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007401 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007402}
7403
Neels Hofmeyr91401012019-07-11 00:42:35 +02007404private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
7405 f_tc_ho_neighbor_config_start();
7406
7407 /*
7408 * bts 0 ARFCN 871 BSIC 10
7409 * bts 1 ARFCN 871 BSIC 11
7410 * bts 2 ARFCN 871 BSIC 12
7411 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7412 */
7413
7414 log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:"
7415 & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007416 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007417 f_sleep(0.5);
7418
7419 f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
7420 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007421 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007422 f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
7423 "handover any to arfcn 123 bsic 45",
7424 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007425 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007426}
Neels Hofmeyr91401012019-07-11 00:42:35 +02007427testcase TC_ho_neighbor_config_7() runs on test_CT {
7428 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf2b88032020-06-16 00:35:04 +02007429 f_init(3, true, guard_timeout := 50.0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007430 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007431 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007432 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
7433 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007434
7435 /* f_tc_ho_neighbor_config_start() */
7436 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7437 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7438
7439 /* 7.a */
7440 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7441 * handover quickly by sending a Handover Failure message. */
7442 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7443 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7444 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7445 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007446 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7447 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007448
7449 /* 7.b */
7450 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7451 * handover quickly by timing out after the Handover Required message */
7452 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7453 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7454 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7455 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7456
7457 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007458 f_shutdown_helper();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007459}
7460
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007461/* OS#3041: Open and close N connections in a normal fashion, and expect no
7462 * BSSMAP Reset just because of that. */
7463testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
7464 var default d;
7465 var integer i;
7466 var DchanTuple dt;
7467
7468 f_init();
7469
7470 /* Wait for initial BSSMAP Reset to pass */
7471 f_sleep(4.0);
7472
7473 d := activate(no_bssmap_reset());
7474
7475 /* Setup up a number of connections and RLSD them again from the MSC
7476 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7477 * Let's do it some more times for good measure. */
Harald Weltec3260d92018-06-11 17:48:16 +02007478 for (i := 0; i < 4; i := i+1) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007479 /* Since we're doing a lot of runs, give each one a fresh
7480 * T_guard from the top. */
7481 T_guard.start;
7482
7483 /* Setup a BSSAP connection and clear it right away. This is
7484 * the MSC telling the BSC about a planned release, it's not an
7485 * erratic loss of a connection. */
Harald Weltea1897182018-06-11 13:53:09 +02007486 dt := f_est_dchan(int2oct(i,1), 23+i, '00010203040506'O);
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007487
7488 /* MSC disconnects (RLSD). */
7489 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
7490 }
7491
7492 /* In the buggy behavior, a timeout of 2 seconds happens between above
7493 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7494 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7495 f_sleep(4.0);
7496
7497 deactivate(d);
7498 f_shutdown_helper();
7499}
Harald Welte552620d2017-12-16 23:21:36 +01007500
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007501/* OS#3041: Open and close N connections in a normal fashion, and expect no
7502 * BSSMAP Reset just because of that. Invoke the release by a BSSMAP Clear from
7503 * the MSC. */
7504testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
7505 var default d;
7506 var integer i;
7507 var DchanTuple dt;
7508 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007509 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
7510 var BssmapCause cause := enum2int(cause_val);
7511
7512 f_init();
7513
7514 /* Wait for initial BSSMAP Reset to pass */
7515 f_sleep(4.0);
7516
7517 d := activate(no_bssmap_reset());
7518
7519 /* Setup up a number of connections and RLSD them again from the MSC
7520 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7521 * Let's do it some more times for good measure. */
7522 for (i := 0; i < 8; i := i+1) {
7523 /* Since we're doing a lot of runs, give each one a fresh
7524 * T_guard from the top. */
7525 T_guard.start;
7526
7527 /* Setup a BSSAP connection and clear it right away. This is
7528 * the MSC telling the BSC about a planned release, it's not an
7529 * erratic loss of a connection. */
Harald Weltea1897182018-06-11 13:53:09 +02007530 dt := f_est_dchan(int2oct(i,1), 23+i, '00010203040506'O);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007531
7532 /* Instruct BSC to clear channel */
7533 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7534
7535 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007536 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007537 }
7538
7539 /* In the buggy behavior, a timeout of 2 seconds happens between above
7540 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7541 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7542 f_sleep(4.0);
7543
7544 deactivate(d);
7545 f_shutdown_helper();
7546}
7547
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007548/* OS#3041: Open and close N connections in a normal fashion, and expect no
7549 * BSSMAP Reset just because of that. Close connections from the MS side with a
7550 * Release Ind on RSL. */
7551testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
7552 var default d;
7553 var integer i;
7554 var DchanTuple dt;
7555 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007556 var integer j;
7557
7558 f_init();
7559
7560 /* Wait for initial BSSMAP Reset to pass */
7561 f_sleep(4.0);
7562
7563 d := activate(no_bssmap_reset());
7564
7565 /* Setup up a number of connections and RLSD them again from the MSC
7566 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7567 * Let's do it some more times for good measure. */
7568 for (i := 0; i < 8; i := i+1) {
7569 /* Since we're doing a lot of runs, give each one a fresh
7570 * T_guard from the top. */
7571 T_guard.start;
7572
7573 /* Setup a BSSAP connection and clear it right away. This is
7574 * the MSC telling the BSC about a planned release, it's not an
7575 * erratic loss of a connection. */
7576 dt := f_est_dchan('23'O, 23, '00010203040506'O);
7577
7578 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007579 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007580
7581 /* expect Clear Request on MSC side */
7582 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
7583
7584 /* Instruct BSC to clear channel */
7585 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
7586 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7587
7588 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007589 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007590 }
7591
7592 /* In the buggy behavior, a timeout of 2 seconds happens between above
7593 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7594 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7595 f_sleep(4.0);
7596
7597 deactivate(d);
7598 f_shutdown_helper();
7599}
7600
Harald Welte94e0c342018-04-07 11:33:23 +02007601/***********************************************************************
7602 * IPA style dynamic PDCH
7603 ***********************************************************************/
7604
7605private function f_dyn_ipa_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7606 template (omit) RSL_Cause nack := omit)
7607runs on test_CT {
7608 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7609 var RSL_Message rsl_unused;
7610 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7611 f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
7612 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007613 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007614 if (istemplatekind(nack, "omit")) {
7615 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007616 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007617 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007618 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007619 }
7620}
7621
7622private function f_dyn_ipa_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7623 template (omit) RSL_Cause nack := omit)
7624runs on test_CT {
7625 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7626 var RSL_Message rsl_unused;
7627 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7628 f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
7629 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007630 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_DEACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007631 if (istemplatekind(nack, "omit")) {
7632 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007633 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007634 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007635 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007636 }
7637}
7638
7639private function f_ts_dyn_mode_get(integer bts_nr, integer trx_nr, integer ts_nr)
7640runs on test_CT return charstring {
7641 var charstring cmd, resp;
7642 cmd := "show timeslot "&int2str(bts_nr)&" "&int2str(trx_nr)&" "&int2str(ts_nr);
Stefan Sperlingcff13562018-11-13 15:24:06 +01007643 return f_vty_transceive_match_regexp_retry(BSCVTY, cmd, "*\((*)\)*", 0, 4, 1.0);
Harald Welte94e0c342018-04-07 11:33:23 +02007644}
7645
7646private function f_ts_dyn_mode_assert(integer bts_nr, integer trx_nr, integer ts_nr,
7647 template charstring exp)
7648runs on test_CT {
7649 var charstring mode := f_ts_dyn_mode_get(bts_nr, trx_nr, ts_nr);
7650 if (not match(mode, exp)) {
7651 setverdict(fail, "Unexpected TS Mode: ", mode);
Daniel Willmannafce8662018-07-06 23:11:32 +02007652 mtc.stop;
Harald Welte94e0c342018-04-07 11:33:23 +02007653 }
7654}
7655
7656private function f_ts_set_chcomb(integer bts_nr, integer trx_nr, integer ts_nr, charstring chcomb)
7657runs on test_CT {
7658 f_vty_enter_cfg_ts(BSCVTY, bts_nr, trx_nr, ts_nr);
7659 f_vty_transceive(BSCVTY, "phys_chan_config " & chcomb);
7660 f_vty_transceive(BSCVTY, "end");
7661}
7662
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007663
7664private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
7665 var integer i;
7666 for (i := 0; i < 8; i := i + 1) {
7667 f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
7668 }
7669}
7670
Harald Welte94e0c342018-04-07 11:33:23 +02007671private const charstring TCHF_MODE := "TCH/F mode";
7672private const charstring TCHH_MODE := "TCH/H mode";
7673private const charstring PDCH_MODE := "PDCH mode";
7674private const charstring NONE_MODE := "NONE mode";
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007675private const charstring SDCCH8_MODE := "SDCCH8 mode";
Harald Welte94e0c342018-04-07 11:33:23 +02007676
7677/* Test IPA PDCH activation / deactivation triggered by VTY */
7678testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
7679 var RSL_Message rsl_unused;
7680
7681 /* change Timeslot 6 before f_init() starts RSL */
7682 f_init_vty();
7683 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7684 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7685
7686 f_init(1, false);
7687 f_sleep(1.0);
7688
7689 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7690
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007691 log("TCH/F_PDCH pchan starts out in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007692 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7693 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007694 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7695 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007696 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007697 log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007698 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7699
7700 /* De-activate it via VTY */
7701 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7702 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007703 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007704 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7705
7706 /* re-activate it via VTY */
7707 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn);
7708 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007709 log("TCH/F_PDCH pchan, PDCH ACT via VTY, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007710 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7711
7712 /* and finally de-activate it again */
7713 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7714 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007715 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007716 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7717
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007718 /* clean up config */
7719 f_ts_set_chcomb(0, 0, 6, "PDCH");
7720
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007721 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007722}
7723
7724/* Test IPA PDCH activation NACK */
7725testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
7726 var RSL_Message rsl_unused;
7727
7728 /* change Timeslot 6 before f_init() starts RSL */
7729 f_init_vty();
7730 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7731 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7732
7733 f_init(1, false);
7734 f_sleep(1.0);
7735
7736 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7737
7738 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7739 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007740 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7741 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007742 f_sleep(1.0);
7743 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7744
7745 /* De-activate it via VTY */
7746 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7747 f_sleep(1.0);
7748 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7749
7750 /* re-activate it via VTY, but fail that; check BSC still assumes TCH/F mode */
7751 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn, RSL_ERR_EQUIPMENT_FAIL);
7752 f_sleep(1.0);
7753 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7754
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007755 /* clean up config */
7756 f_ts_set_chcomb(0, 0, 6, "PDCH");
7757
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007758 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007759}
7760
7761
7762/***********************************************************************
7763 * Osmocom style dynamic PDCH
7764 ***********************************************************************/
7765
7766private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7767 template (omit) RSL_Cause nack := omit)
7768runs on test_CT {
7769 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7770 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007771 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007772 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7773 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007774 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT(chan_nr, ?));
Harald Welte94e0c342018-04-07 11:33:23 +02007775 if (istemplatekind(nack, "omit")) {
7776 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007777 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02007778 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007779 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007780 }
7781}
7782
7783private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7784 template (omit) RSL_Cause nack := omit)
7785runs on test_CT {
7786 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7787 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007788 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007789 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7790 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007791 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007792 if (istemplatekind(nack, "omit")) {
7793 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007794 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007795 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007796 //f_ipa_tx(ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007797 }
7798}
7799
7800/* Test Osmocom dyn PDCH activation / deactivation triggered by VTY */
7801testcase TC_dyn_pdch_osmo_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_TCH/H_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_PDCH(6));
7813
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007814 log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007815 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_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_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007818
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007819 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02007820 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007821 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 +02007822 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7823
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007824 /* clean up config */
7825 f_ts_set_chcomb(0, 0, 6, "PDCH");
7826
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007827 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007828}
7829
7830/* Test Osmocom dyn PDCH activation NACK behavior */
7831testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
7832 var RSL_Message rsl_unused;
7833
7834 /* change Timeslot 6 before f_init() starts RSL */
7835 f_init_vty();
7836 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
7837 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7838
7839 f_init(1, false);
7840 f_sleep(1.0);
7841
7842 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
7843
7844 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
7845 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007846 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007847
7848 /* NACK this activation and expect the "show timeslot" mode still to be NONE */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007849 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte94e0c342018-04-07 11:33:23 +02007850 f_sleep(1.0);
7851 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
7852
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007853 /* clean up config */
7854 f_ts_set_chcomb(0, 0, 6, "PDCH");
7855
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007856 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007857}
7858
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007859/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
7860testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
7861 var RSL_Message rsl_unused, rsl_msg;
7862 var DchanTuple dt;
7863 var BSSAP_N_CONNECT_ind rx_c_ind;
7864
7865 /* change Timeslot 6 before f_init() starts RSL */
7866 f_init_vty();
7867 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
7868 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7869
7870 f_init(1, false);
7871 f_sleep(1.0);
7872
7873 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
7874
7875 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
7876 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
7877 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007878 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007879
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007880 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007881 f_sleep(1.0);
7882 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
7883 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7884
7885 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
7886 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007887 var DchanTuples sdcch_cleanup := {};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007888 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02007889 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007890 dt := f_est_dchan('23'O, i, '00010203040506'O);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007891 sdcch_cleanup := sdcch_cleanup & { dt };
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007892 }
7893
7894 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007895 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
7896 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
7897 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007898
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007899 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007900 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007901 dt.idx := {0, 0};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007902
7903 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007904 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
7905 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007906 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
7907
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007908 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 +02007909 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
7910 dt.sccp_conn_id := rx_c_ind.connectionId;
7911 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
7912
7913 /* Instruct BSC to clear channel */
7914 var BssmapCause cause := 0;
7915 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007916 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007917
7918 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007919 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
7920 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007921 f_sleep(1.0);
7922 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7923
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007924 /* Clean up SDCCH lchans */
7925 for (i := 0; i < lengthof(sdcch_cleanup); i := i + 1) {
7926 f_perform_clear_test_ct(sdcch_cleanup[i]);
7927 }
7928
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007929 /* clean up config */
7930 f_ts_set_chcomb(0, 0, 6, "PDCH");
7931
7932 f_shutdown_helper();
7933}
7934
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007935/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
7936testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
7937 var ASP_RSL_Unitdata rsl_ud;
7938 var integer i;
7939 var integer chreq_total, chreq_nochan;
7940
7941 f_init_vty();
7942 for (i := 1; i < 8; i := i + 1) {
7943 if (i == 2) {
7944 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
7945 } else {
7946 f_ts_set_chcomb(0, 0, i, "PDCH");
7947 }
7948 }
7949 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7950
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007951 f_init(1, guard_timeout := 60.0);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007952
7953 /* The dyn TS want to activate PDCH mode, ACK that. */
7954 var RslChannelNr chan_nr;
7955 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007956 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
7957 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007958
7959 f_sleep(1.0);
7960
7961 /* Exhaust all dedicated SDCCH lchans.
7962 /* GSM 44.018 Table 9.1.8.2:
7963 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
7964 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007965 var DchanTuples chan_cleanup := {};
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007966 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007967 chan_cleanup := chan_cleanup & { f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007968 }
7969
7970 /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007971 chan_cleanup := chan_cleanup & { f_est_dchan_dyn('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007972 /* Also occupy the seven other SDCCH of the dyn TS */
7973 for (i := 0; i < 7; i := i+1) {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007974 chan_cleanup := chan_cleanup & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
7975 }
7976
7977 /* Clean up SDCCH lchans */
7978 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
7979 f_perform_clear_test_ct(chan_cleanup[i]);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007980 }
7981
7982 /* clean up config */
7983 f_ts_reset_chcomb(0);
7984
7985 f_shutdown_helper();
7986}
7987
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007988/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
7989 SDCCH8 would end up in having no free TCH, then BSC should decide to activate
7990 it as TCH directly instead. SYS#5309. */
7991testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
7992 var RSL_Message rsl_unused, rsl_msg;
7993 var DchanTuple dt;
7994 var BSSAP_N_CONNECT_ind rx_c_ind;
7995 var integer i;
7996
7997 /* change Timeslot 6 before f_init() starts RSL */
7998 f_init_vty();
7999 for (i := 1; i < 8; i := i + 1) {
8000 if (i == 6) {
8001 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8002 } else {
8003 f_ts_set_chcomb(0, 0, i, "PDCH");
8004 }
8005 }
8006 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8007
8008 f_init(1, false);
8009 f_sleep(1.0);
8010
8011 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8012
8013 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8014 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8015 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008016 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008017
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008018 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008019 f_sleep(1.0);
8020 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8021 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8022
8023 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8024 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008025 var DchanTuples chan_cleanup := {};
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02008026 var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008027 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02008028 dt := f_est_dchan(ra, i, '00010203040506'O);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008029 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008030 }
8031
8032 /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008033 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
8034 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8035 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008036
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008037 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008038 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008039 dt.idx := {0, 0};
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008040
8041 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008042 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8043 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008044 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
8045
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008046 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 +02008047 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8048 dt.sccp_conn_id := rx_c_ind.connectionId;
8049 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8050
8051 /* Instruct BSC to clear channel */
8052 var BssmapCause cause := 0;
8053 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008054 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008055
8056 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008057 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8058 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008059 f_sleep(1.0);
8060 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8061
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008062 /* Clean up SDCCH lchans */
8063 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8064 f_perform_clear_test_ct(chan_cleanup[i]);
8065 }
8066
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008067 /* clean up config */
8068 f_ts_reset_chcomb(0);
8069 /* TODO: clean up other channels? */
8070
8071 f_shutdown_helper();
8072}
8073
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008074/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
8075testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
8076 var RSL_Message rsl_unused, rsl_msg;
8077 var DchanTuple dt;
8078 var BSSAP_N_CONNECT_ind rx_c_ind;
8079 var GsmRrMessage rr;
8080
8081 /* change Timeslot 6 before f_init() starts RSL */
8082 f_init_vty();
8083 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8084 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8085
8086 f_init(1, false);
8087 f_sleep(1.0);
8088
8089 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8090
8091 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8092 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8093 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008094 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008095
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008096 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008097 f_sleep(1.0);
8098 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8099 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8100
8101 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8102 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008103 var DchanTuples chan_cleanup := {};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008104 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008105 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008106 dt := f_est_dchan('23'O, i, '00010203040506'O);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008107 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008108 }
8109
8110 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008111 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8112 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8113 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008114
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008115 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008116 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008117 dt.idx := {0, 0};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008118
8119 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008120 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
8121 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008122 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
8123 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
8124 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
8125 }
8126
8127 /* FIXME? Currently the TS stays in state BORKEN: */
8128
8129 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008130 /* rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8131 * f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008132 * f_sleep(1.0);
8133 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
8134 */
8135
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008136 /* Clean up SDCCH lchans */
8137 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8138 f_perform_clear_test_ct(chan_cleanup[i]);
8139 }
8140
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008141 /* clean up config */
8142 f_ts_set_chcomb(0, 0, 6, "PDCH");
8143
8144 f_shutdown_helper();
8145}
8146
Stefan Sperling0796a822018-10-05 13:01:39 +02008147testcase TC_chopped_ipa_ping() runs on test_CT {
Stefan Sperling554123f2018-10-09 14:12:30 +02008148 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port, mp_bsc_ctrl_port};
Stefan Sperling0796a822018-10-05 13:01:39 +02008149 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8150 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8151 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008152 f_shutdown_helper();
Stefan Sperling0796a822018-10-05 13:01:39 +02008153}
8154
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008155testcase TC_chopped_ipa_payload() runs on test_CT {
8156 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port
8157 /* TODO: mp_bsc_ctrl_port does not work yet */};
8158 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8159 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8160 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008161 f_shutdown_helper();
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008162}
8163
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008164/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
8165 the BTS does autonomous MS power control loop */
8166testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
8167 var MSC_ConnHdlr vc_conn;
8168 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8169 //pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
8170 pars.exp_ms_power_params := true;
8171
8172 f_init(1, true);
8173 f_sleep(1.0);
8174 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
8175 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008176 f_shutdown_helper();
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008177}
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008178
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008179/* Verify activation and deactivation of the BCCH carrier power reduction mode */
8180testcase TC_c0_power_red_mode() runs on test_CT {
8181 f_init(1);
8182
8183 for (var integer red := 6; red >= 0; red := red - 2) {
8184 /* Configure BCCH carrier power reduction mode via the VTY */
8185 f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
8186
8187 /* Expect Osmocom specific BS Power Control message on the RSL */
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03008188 var template (present) RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008189 chan_nr := t_RslChanNr_BCCH(0),
8190 bs_power := tr_RSL_IE_BS_Power(red / 2));
8191 tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008192 var RSL_Message unused := f_exp_ipa_rx(tr_rsl_pdu);
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008193
8194 /* Additionally verify the applied value over the CTRL interface */
8195 var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
8196 if (cred != int2str(red)) {
8197 setverdict(fail, "Unexpected BCCH carrier power reduction value ",
8198 cred, " (expected ", red, ")");
8199 }
8200 }
8201
8202 f_shutdown_helper();
8203}
8204
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008205/***********************************************************************
8206 * MSC Pooling
8207 ***********************************************************************/
8208
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008209template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
Harald Weltebf397612021-01-14 20:39:46 +01008210 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 +02008211
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008212private 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 +02008213runs on MSC_ConnHdlr {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008214 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008215 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008216 f_logp(BSCVTY, "Got RSL RR Release");
8217 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008218 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008219 f_logp(BSCVTY, "Got RSL Deact SACCH");
8220 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008221 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008222 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008223 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8224 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008225 break;
8226 }
8227 }
8228}
8229
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008230private altstep as_mgcp_ack_all_dlcx() runs on MSC_ConnHdlr {
8231 var MgcpCommand mgcp_cmd;
8232 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
8233 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
8234 repeat;
8235 }
8236}
8237
8238private altstep as_rsl_ack_all_rel_req() runs on MSC_ConnHdlr {
8239 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
8240 [] RSL.receive(tr_RSL_REL_REQ(g_chan_nr, ?)) {
8241 RSL.send(ts_RSL_REL_CONF(g_chan_nr, main_dcch));
8242 repeat;
8243 }
8244}
8245
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008246friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
8247 template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02008248runs on MSC_ConnHdlr {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008249 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8250 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008251 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008252 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8253 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008254 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008255 f_logp(BSCVTY, "Got RSL RR Release");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008256 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008257 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008258 f_logp(BSCVTY, "Got RSL Deact SACCH");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008259 }
8260 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008261 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008262 /* Also drop the SCCP connection */
8263 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8264 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008265 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008266 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008267 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8268 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008269 }
8270 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008271 deactivate(ack_dlcx);
8272 deactivate(ack_rel_req);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008273}
8274
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01008275friend function f_perform_clear_no_rr_rel(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC)
8276runs on MSC_ConnHdlr {
8277 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8278 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
8279 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8280 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8281 interleave {
8282 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
8283 f_logp(BSCVTY, "Got RSL Deact SACCH");
8284 }
8285 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
8286 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8287 /* Also drop the SCCP connection */
8288 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8289 }
8290 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
8291 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
8292 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8293 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
8294 }
8295 }
8296 deactivate(ack_dlcx);
8297 deactivate(ack_rel_req);
8298}
8299
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01008300friend function f_perform_clear_no_lchan()
8301runs on MSC_ConnHdlr {
8302 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8303 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8304 BSSAP.receive(tr_BSSMAP_ClearComplete);
8305 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8306 /* Also drop the SCCP connection */
8307 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8308}
8309
Vadim Yanitskiy65d879d2022-06-23 18:15:39 +07008310friend function f_perform_clear_test_ct(DchanTuple dt)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008311 runs on test_CT
8312{
8313 /* Instruct BSC to clear channel */
8314 var BssmapCause cause := 0;
8315 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008316 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008317}
8318
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008319private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
8320 template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008321runs on MSC_ConnHdlr {
8322 timer T := 10.0;
8323 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
8324
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008325 f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008326 f_create_bssmap_exp(l3_enc);
8327
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008328 /* RSL_Emulation.f_chan_est() on rsl_pt:
8329 * This is basically code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008330 * RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
8331 */
8332 var RSL_Message rx_rsl;
8333 var GsmRrMessage rr;
8334
8335 /* request a channel to be established */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008336 rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008337 /* expect immediate assignment.
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008338 * Code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008339 * rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
8340 */
8341 timer Tt := 10.0;
8342
8343 /* request a channel to be established */
8344 Tt.start;
8345 alt {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008346 [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008347 Tt.stop;
8348 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008349 [] rsl_pt.receive {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008350 setverdict(fail, "Unexpected RSL message on DCHAN");
8351 mtc.stop;
8352 }
8353 [] Tt.timeout {
8354 setverdict(fail, "Timeout waiting for RSL on DCHAN");
8355 mtc.stop;
8356 }
8357 }
8358 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
8359 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008360 rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008361
8362
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008363 if (expect_bssmap_l3) {
8364 f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
8365 var template PDU_BSSAP exp_l3_compl;
8366 exp_l3_compl := tr_BSSMAP_ComplL3()
8367 if (g_pars.aoip == false) {
8368 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
8369 } else {
8370 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
8371 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008372
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008373 var PDU_BSSAP bssap;
8374 T.start;
8375 alt {
8376 [] BSSAP.receive(exp_l3_compl) -> value bssap {
8377 f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
8378 log("rx exp_l3_compl = ", bssap);
8379 }
8380 [] BSSAP.receive(tr_BSSMAP_ComplL3) {
8381 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
8382 }
8383 [] T.timeout {
8384 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
8385 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008386 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008387
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008388 /* start ciphering, if requested */
8389 if (ispresent(g_pars.encr)) {
8390 f_logp(BSCVTY, "start ciphering");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008391 f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008392 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008393 }
8394
8395 if (do_clear) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008396 f_perform_clear(rsl_pt, rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008397 }
8398 setverdict(pass);
8399 f_sleep(1.0);
8400}
8401
8402private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
8403 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8404 if (g_pars.mscpool.rsl_idx == 0) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008405 f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008406 } else if (g_pars.mscpool.rsl_idx == 1) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008407 f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008408 } else if (g_pars.mscpool.rsl_idx == 2) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008409 f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008410 }
8411}
8412
8413/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
8414private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
8415 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008416 f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
8417 f_perform_compl_l3(RSL, RSL_PROC, ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_IMSI_LV('001010000000002'H))) );
8418 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))) );
8419 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 +02008420}
8421testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
8422
8423 f_init(1, true);
8424 f_sleep(1.0);
8425 var MSC_ConnHdlr vc_conn;
8426 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008427
8428 f_ctrs_msc_init();
8429
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008430 vc_conn := f_start_handler(refers(f_tc_mscpool_L3Compl_on_1_msc), pars);
8431 vc_conn.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008432
8433 f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008434 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008435}
8436
8437/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
8438/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8439 * just as well using only RSL. */
8440testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
8441
8442 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8443 f_sleep(1.0);
8444
8445 /* Control which MSC gets chosen next by the round-robin, otherwise
8446 * would be randomly affected by which other tests ran before this. */
8447 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8448
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008449 f_ctrs_msc_init();
8450
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008451 var MSC_ConnHdlr vc_conn1;
8452 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8453 pars1.mscpool.rsl_idx := 0;
8454 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8455 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8456 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008457 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008458
8459 var MSC_ConnHdlr vc_conn2;
8460 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8461 pars2.mscpool.rsl_idx := 1;
8462 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8463 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8464 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008465 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008466
8467 /* Test round-robin wrap to the first MSC */
8468 var MSC_ConnHdlr vc_conn3;
8469 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8470 pars3.mscpool.rsl_idx := 2;
8471 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
8472 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8473 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008474 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008475 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008476}
8477
8478/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 0
8479 * (configured in osmo-bsc.cfg). */
8480/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8481 * just as well using only RSL. */
8482testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
8483
8484 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8485 f_sleep(1.0);
8486
8487 /* Control which MSC gets chosen next by the round-robin, otherwise
8488 * would be randomly affected by which other tests ran before this. */
8489 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8490
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008491 f_ctrs_msc_init();
8492
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008493 var MSC_ConnHdlr vc_conn1;
8494 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8495 pars1.mscpool.rsl_idx := 0;
8496 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8497 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8498 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008499 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008500
8501 var MSC_ConnHdlr vc_conn2;
8502 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8503 pars2.mscpool.rsl_idx := 1;
8504 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8505 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8506 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008507 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008508
8509 /* Test round-robin wrap to the first MSC */
8510 var MSC_ConnHdlr vc_conn3;
8511 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8512 pars3.mscpool.rsl_idx := 2;
8513 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8514 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8515 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008516 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008517 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008518}
8519
8520/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
8521 * (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
8522 * NULL-NRI setting is stronger than that. */
8523/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8524 * just as well using only RSL. */
8525testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
8526
8527 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8528 f_sleep(1.0);
8529
8530 /* Control which MSC gets chosen next by the round-robin, otherwise
8531 * would be randomly affected by which other tests ran before this. */
8532 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8533
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008534 f_ctrs_msc_init();
8535
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008536 var MSC_ConnHdlr vc_conn1;
8537 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8538 pars1.mscpool.rsl_idx := 0;
8539 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8540 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8541 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008542 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008543
8544 var MSC_ConnHdlr vc_conn2;
8545 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8546 pars2.mscpool.rsl_idx := 1;
8547 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8548 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8549 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008550 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008551
8552 /* Test round-robin wrap to the first MSC */
8553 var MSC_ConnHdlr vc_conn3;
8554 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8555 pars3.mscpool.rsl_idx := 2;
8556 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8557 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8558 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008559 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008560 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008561}
8562
8563/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
8564 * assigned to any MSC (configured in osmo-bsc.cfg). */
8565/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8566 * just as well using only RSL. */
8567testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test_CT {
8568
8569 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8570 f_sleep(1.0);
8571
8572 /* Control which MSC gets chosen next by the round-robin, otherwise
8573 * would be randomly affected by which other tests ran before this. */
8574 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8575
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008576 f_ctrs_msc_init();
8577
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008578 var MSC_ConnHdlr vc_conn1;
8579 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8580 pars1.mscpool.rsl_idx := 0;
8581 /* An NRI that is not assigned to any MSC */
8582 pars1.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(1023))));
8583 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8584 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008585 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008586
8587 var MSC_ConnHdlr vc_conn2;
8588 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8589 pars2.mscpool.rsl_idx := 1;
8590 /* An NRI that is not assigned to any MSC */
8591 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(768)), '00F110'O));
8592 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8593 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008594 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008595
8596 /* Test round-robin wrap to the first MSC */
8597 var MSC_ConnHdlr vc_conn3;
8598 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8599 pars3.mscpool.rsl_idx := 2;
8600 /* An NRI that is not assigned to any MSC */
8601 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, valueof(ts_MI_TMSI_NRI_LV(819))));
8602 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8603 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008604 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008605 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008606}
8607
8608/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
8609 * assigned to an MSC that is currently not connected (configured in osmo-bsc.cfg). */
8610/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8611 * just as well using only RSL. */
8612testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
8613
8614 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8615 f_sleep(1.0);
8616
8617 /* Control which MSC gets chosen next by the round-robin, otherwise
8618 * would be randomly affected by which other tests ran before this. */
8619 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8620
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008621 f_ctrs_msc_init();
8622
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008623 var MSC_ConnHdlr vc_conn1;
8624 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8625 pars1.mscpool.rsl_idx := 0;
8626 /* An NRI that is assigned to an unconnected MSC */
8627 pars1.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(512))));
8628 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8629 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008630 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8631 f_ctrs_msc_add(0, "mscpool:subscr:new");
8632 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008633
8634 var MSC_ConnHdlr vc_conn2;
8635 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8636 pars2.mscpool.rsl_idx := 1;
8637 /* An NRI that is assigned to an unconnected MSC */
8638 pars2.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(767))));
8639 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8640 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008641 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8642 f_ctrs_msc_add(1, "mscpool:subscr:new");
8643 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008644
8645 /* Test round-robin wrap to the first MSC */
8646 var MSC_ConnHdlr vc_conn3;
8647 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8648 pars3.mscpool.rsl_idx := 2;
8649 /* An NRI that is assigned to an unconnected MSC */
8650 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(750)), '00F110'O));
8651 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8652 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008653 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8654 f_ctrs_msc_add(0, "mscpool:subscr:new");
8655 f_ctrs_msc_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008656 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008657}
8658
8659/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
8660 * osmo-bsc.cfg). */
8661/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8662 * just as well using only RSL. */
8663testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
8664
8665 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8666 f_sleep(1.0);
8667
8668 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
8669 * this is not using round-robin. */
8670 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8671
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008672 f_ctrs_msc_init();
8673
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008674 var MSC_ConnHdlr vc_conn1;
8675 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8676 pars1.mscpool.rsl_idx := 0;
8677 /* An NRI of the second MSC's range (256-511) */
8678 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(256))));
8679 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8680 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008681 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008682
8683 var MSC_ConnHdlr vc_conn2;
8684 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8685 pars2.mscpool.rsl_idx := 1;
8686 /* An NRI of the second MSC's range (256-511) */
8687 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(260))));
8688 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8689 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008690 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008691
8692 var MSC_ConnHdlr vc_conn3;
8693 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8694 pars3.mscpool.rsl_idx := 2;
8695 /* An NRI of the second MSC's range (256-511) */
8696 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(511)), '00F110'O));
8697 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8698 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008699 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008700 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008701}
8702
8703/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
8704 * while a round-robin remains unaffected by that. */
8705/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8706 * just as well using only RSL. */
8707testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
8708
8709 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8710 f_sleep(1.0);
8711
8712 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
8713 * this is not using round-robin. */
8714 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8715
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008716 f_ctrs_msc_init();
8717
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008718 var MSC_ConnHdlr vc_conn1;
8719 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 2);
8720 pars1.mscpool.rsl_idx := 0;
8721 /* An NRI of the third MSC's range (512-767) */
8722 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(512))));
8723 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8724 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008725 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008726
8727 var MSC_ConnHdlr vc_conn2;
8728 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8729 pars2.mscpool.rsl_idx := 1;
8730 /* An NRI of the third MSC's range (512-767) */
8731 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(678))));
8732 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8733 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008734 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008735
8736 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
8737 var MSC_ConnHdlr vc_conn3;
8738 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8739 pars3.mscpool.rsl_idx := 2;
8740 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000013'H)), '00F110'O));
8741 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8742 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008743 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008744 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008745}
8746
8747/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
8748/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8749 * just as well using only RSL. */
8750testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
8751
8752 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8753 f_sleep(1.0);
8754
8755 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
8756 * instead, and hits msc 0. */
8757 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8758
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008759 f_ctrs_msc_init();
8760
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008761 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-bsc.cfg */
8762 var MSC_ConnHdlr vc_conn1;
8763 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8764 pars1.mscpool.rsl_idx := 0;
8765 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(260)), '99F999'O));
8766 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8767 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008768 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008769
8770 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
8771 var MSC_ConnHdlr vc_conn2;
8772 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8773 pars2.mscpool.rsl_idx := 1;
8774 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(555)), '00F110'O));
8775 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8776 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008777 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008778 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008779}
8780
8781/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
8782 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
8783private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
8784 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
8785 //cid_list := { cIl_allInBSS := ''O };
8786 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
8787 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
8788 var BSSAP_N_UNITDATA_req paging;
8789 var hexstring imsi := '001010000000123'H;
8790
8791 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8792
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008793 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008794 valueof(ts_BSSMAP_Paging(imsi, cid_list, omit, bssmap_chneed))));
8795 BSSAP.send(paging);
8796
8797 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
8798 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
8799 * channel number is picked here. */
8800 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
8801 f_rslem_register(0, new_chan_nr);
8802 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(imsi)));
8803 f_rslem_unregister(0, new_chan_nr);
8804
8805 /* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
8806 * causes this Paging Response to go to the first MSC (bssap_idx := 0). */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008807 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV(imsi))) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008808 f_sleep(1.0);
8809}
8810testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
8811 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
8812 f_sleep(1.0);
8813
8814 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
8815 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
8816 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8817
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008818 f_ctrs_msc_init();
8819
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008820 var MSC_ConnHdlr vc_conn1;
8821 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8822 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008823 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
8824 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008825 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
8826 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008827 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008828 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008829}
8830
8831/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
8832 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
8833private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
8834 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
8835 //cid_list := { cIl_allInBSS := ''O };
8836 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
8837 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
8838 var integer nri_v := 300; /* <-- second MSC's NRI */
Harald Weltebf397612021-01-14 20:39:46 +01008839 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008840 var BSSAP_N_UNITDATA_req paging;
8841
8842 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8843
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008844 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008845 valueof(ts_BSSMAP_Paging('001010000000011'H, cid_list, tmsi, bssmap_chneed))));
8846 BSSAP.send(paging);
8847
8848 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
8849 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
8850 * channel number is picked here. */
8851 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
8852 f_rslem_register(0, new_chan_nr);
8853 RSL.receive(tr_RSL_PAGING_CMD(t_MI_TMSI(tmsi)));
8854 f_rslem_unregister(0, new_chan_nr);
8855
8856 /* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
8857 * third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
8858 * the first MSC (bssap_idx := 0). */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008859 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 +02008860 f_sleep(1.0);
8861}
8862testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
8863 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
8864 f_sleep(1.0);
8865
8866 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
8867 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
8868 f_vty_transceive(BSCVTY, "mscpool roundrobin next 2");
8869
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008870 f_ctrs_msc_init();
8871
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008872 var MSC_ConnHdlr vc_conn1;
8873 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8874 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008875 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
8876 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008877 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
8878 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008879 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008880 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008881}
8882
8883/* For round-robin, skip an MSC that has 'no allow-attach' set. */
8884/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8885 * just as well using only RSL. */
8886testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
8887
8888 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8889 f_sleep(1.0);
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00008890 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
8891 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008892
8893 /* Control which MSC gets chosen next by the round-robin, otherwise
8894 * would be randomly affected by which other tests ran before this. */
8895 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8896
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008897 f_ctrs_msc_init();
8898
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008899 var MSC_ConnHdlr vc_conn1;
8900 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8901 pars1.mscpool.rsl_idx := 0;
8902 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8903 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8904 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008905 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008906
8907 var MSC_ConnHdlr vc_conn2;
8908 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8909 pars2.mscpool.rsl_idx := 1;
8910 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8911 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8912 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008913 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008914
8915 var MSC_ConnHdlr vc_conn3;
8916 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8917 pars3.mscpool.rsl_idx := 2;
8918 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
8919 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8920 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008921 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008922 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008923}
8924
8925/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
8926 * TMSI NRI. */
8927testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
8928
8929 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8930 f_sleep(1.0);
8931
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00008932 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
8933 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
8934
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008935 /* Control which MSC gets chosen next by the round-robin, otherwise
8936 * would be randomly affected by which other tests ran before this. */
8937 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8938
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008939 f_ctrs_msc_init();
8940
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008941 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
8942 var MSC_ConnHdlr vc_conn1;
8943 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8944 pars1.mscpool.rsl_idx := 0;
8945 /* An NRI of the second MSC's range (256-511) */
8946 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_TMSI_NRI_LV(260))));
8947 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8948 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008949 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008950
8951 var MSC_ConnHdlr vc_conn2;
8952 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
8953 pars2.mscpool.rsl_idx := 1;
8954 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8955 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8956 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008957 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008958
8959 var MSC_ConnHdlr vc_conn3;
8960 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 2);
8961 pars3.mscpool.rsl_idx := 2;
8962 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000003'H))));
8963 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8964 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008965 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008966 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008967}
8968
Philipp Maier783681c2020-07-16 16:47:06 +02008969/* Allow/Deny emergency calls globally via VTY */
8970private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
8971 f_vty_enter_cfg_msc(BSCVTY, 0);
8972 if (allow) {
8973 f_vty_transceive(BSCVTY, "allow-emergency allow");
8974 } else {
8975 f_vty_transceive(BSCVTY, "allow-emergency deny");
8976 }
8977 f_vty_transceive(BSCVTY, "exit");
8978 f_vty_transceive(BSCVTY, "exit");
8979}
8980
8981/* Allow/Deny emergency calls per BTS via VTY */
8982private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
8983 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
8984 if (allow) {
8985 f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
8986 } else {
8987 f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
8988 }
8989 f_vty_transceive(BSCVTY, "exit");
8990 f_vty_transceive(BSCVTY, "exit");
Neels Hofmeyrb6ed80c2020-10-12 22:52:39 +00008991 f_vty_transceive(BSCVTY, "exit");
Philipp Maier783681c2020-07-16 16:47:06 +02008992}
8993
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02008994/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
8995private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
8996 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
8997 if (allow) {
8998 f_vty_transceive(BSCVTY, "srvcc fast-return allow");
8999 } else {
9000 f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
9001 }
9002 f_vty_transceive(BSCVTY, "exit");
9003 f_vty_transceive(BSCVTY, "exit");
9004 f_vty_transceive(BSCVTY, "exit");
9005}
9006
Pau Espin Pedrol14475352021-07-22 15:48:16 +02009007/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
9008private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
9009 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9010 if (allow) {
9011 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
9012 } else {
9013 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
9014 }
9015 f_vty_transceive(BSCVTY, "exit");
9016 f_vty_transceive(BSCVTY, "exit");
9017 f_vty_transceive(BSCVTY, "exit");
9018}
9019
Philipp Maier783681c2020-07-16 16:47:06 +02009020/* Begin assignmet procedure and send an EMERGENCY SETUP (RR) */
9021private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
9022 var PDU_ML3_MS_NW emerg_setup;
9023 var octetstring emerg_setup_enc;
9024 var RSL_Message emerg_setup_data_ind;
9025
9026 f_establish_fully(omit, omit);
9027
9028 emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
9029 emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
9030 emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
9031
9032 RSL.send(emerg_setup_data_ind);
9033}
9034
9035/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
9036 * CALLS are permitted by the BSC config. */
9037private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
9038 var PDU_BSSAP emerg_setup_data_ind_bssap;
9039 var PDU_ML3_MS_NW emerg_setup;
9040 timer T := 3.0;
9041
9042 f_assignment_emerg_setup()
9043
9044 T.start;
9045 alt {
9046 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
9047 emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
9048 if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
9049 setverdict(fail, "no emergency setup");
9050 }
9051 }
9052 [] BSSAP.receive {
9053 setverdict(fail, "unexpected BSSAP message!");
9054 }
9055 [] T.timeout {
9056 setverdict(fail, "timout waiting for EMERGENCY SETUP!");
9057 }
9058 }
9059
9060 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009061 f_perform_clear();
Philipp Maier783681c2020-07-16 16:47:06 +02009062}
9063
9064/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
9065 * forbidden by the BSC config. */
9066private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
9067 var PDU_BSSAP emerg_setup_data_ind_bssap;
9068 timer T := 3.0;
9069
9070 f_assignment_emerg_setup()
9071
9072 T.start;
9073 alt {
9074 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
9075 setverdict(pass);
9076 }
9077 [] RSL.receive {
9078 setverdict(fail, "unexpected RSL message!");
9079 }
9080 [] T.timeout {
9081 setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
9082 }
9083 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009084 BSSAP.receive(tr_BSSMAP_ClearRequest);
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01009085 f_perform_clear_no_rr_rel();
Philipp Maier783681c2020-07-16 16:47:06 +02009086}
9087
9088/* EMERGENCY CALL situation #1, allowed globally and by BTS */
9089testcase TC_assignment_emerg_setup_allow() runs on test_CT {
9090 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9091 var MSC_ConnHdlr vc_conn;
9092
9093 f_init(1, true);
9094 f_sleep(1.0);
9095
9096 f_vty_allow_emerg_msc(true);
9097 f_vty_allow_emerg_bts(true, 0);
9098 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9099 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009100 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009101}
9102
9103/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
9104testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
9105 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9106 var MSC_ConnHdlr vc_conn;
9107
9108 f_init(1, true);
9109 f_sleep(1.0);
9110
9111 f_vty_allow_emerg_msc(false);
9112 f_vty_allow_emerg_bts(true, 0);
9113 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9114 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009115 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009116}
9117
9118/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS */
9119testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
9120 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9121 var MSC_ConnHdlr vc_conn;
9122
9123 /* Note: This simulates a spec violation by the MS, correct MS
9124 * implementations would not try to establish an emergency call because
9125 * the system information tells in advance that emergency calls are
9126 * not forbidden */
9127
9128 f_init(1, true);
9129 f_sleep(1.0);
9130
9131 f_vty_allow_emerg_msc(true);
9132 f_vty_allow_emerg_bts(false, 0);
9133 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9134 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009135 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009136}
9137
Philipp Maier82812002020-08-13 18:48:27 +02009138/* Test what happens when an emergency call arrives while all TCH channels are
9139 * busy, the BSC is expected to terminate one call in favor of the incoming
9140 * emergency call */
9141testcase TC_emerg_premption() runs on test_CT {
9142 var ASP_RSL_Unitdata rsl_ud;
9143 var integer i;
9144 var integer chreq_total, chreq_nochan;
9145 var RSL_Message rx_rsl;
Philipp Maier82812002020-08-13 18:48:27 +02009146
9147 f_init(1);
9148 f_sleep(1.0);
9149
9150 f_vty_allow_emerg_msc(true);
9151 f_vty_allow_emerg_bts(true, 0);
9152
9153 /* Fill up all channels on the BTS */
9154 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
9155 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
9156 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 +02009157 f_chreq_act_ack('33'O, i);
Philipp Maier82812002020-08-13 18:48:27 +02009158 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009159 IPA_RSL[0][0].clear;
Philipp Maier82812002020-08-13 18:48:27 +02009160 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
9161 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
9162
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009163 /* Send EST IND for the first TCH, so we get to test the RR release cause */
9164 var RslChannelNr first_tch := valueof(t_RslChanNr_Bm(1));
9165 var octetstring l3 := '00010203040506'O;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009166 f_ipa_tx(ts_RSL_EST_IND(first_tch, valueof(ts_RslLinkID_DCCH(0)), l3));
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009167
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009168 /* Accept BSSAP conn, so we get to test the Clear Request cause */
9169 var BSSAP_N_CONNECT_ind rx_c_ind;
9170 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
9171 var integer sccp_conn_id := rx_c_ind.connectionId;
9172 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
9173
Philipp Maier82812002020-08-13 18:48:27 +02009174 /* Send Channel request for emegergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009175 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier82812002020-08-13 18:48:27 +02009176
9177 /* Expect the BSC to release one (the first) TCH/F on the BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009178 f_expect_chan_rel(first_tch, expect_rr_chan_rel := true, expect_rll_rel_req := false,
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009179 expect_rr_cause := GSM48_RR_CAUSE_PREMPTIVE_REL);
Philipp Maier82812002020-08-13 18:48:27 +02009180
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009181 /* Also expect a BSSMAP Clear Request with PREEMPTION */
9182 var BSSAP_N_DATA_ind rx_clear_req;
9183 const myBSSMAP_Cause preemption := GSM0808_CAUSE_PREEMPTION;
9184 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_clear_req;
9185 log("XXX ", rx_clear_req);
9186 if (rx_clear_req.userData.pdu.bssmap.clearRequest.cause.causeValue != int2bit(enum2int(preemption), 7)) {
9187 setverdict(fail, "BSSMAP Clear Request: expected cause PREEMPTION");
9188 }
9189
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009190 /* Expect the BSC to send activate/assign the channel for the emergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009191 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009192 if (first_tch != rx_rsl.ies[0].body.chan_nr) {
9193 setverdict(fail, "different TCH lchan activated than expected");
9194 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009195 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(first_tch, 33));
9196 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Philipp Maier104f4c02020-09-11 18:12:18 +02009197
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009198 /* complete the BSSMAP Clear to satisfy the conn leak check */
9199 BSSAP.send(ts_BSSAP_DATA_req(sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(preemption))));
9200 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearComplete)) {
9201 BSSAP.send(ts_BSSAP_DISC_req(sccp_conn_id, 0));
9202 }
9203
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009204 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009205}
9206
9207/* Hopping parameters per a timeslot */
Vadim Yanitskiybc6654a2020-09-13 01:27:40 +07009208private type record length(0..64) of GsmArfcn ArfcnList;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009209private type record FHParamsTs {
9210 boolean enabled,
9211 uint6_t hsn,
9212 uint6_t maio,
9213 ArfcnList ma
9214};
9215
9216/* Hopping parameters per a transceiver */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009217private type record FHParamsTrx {
Philipp Maier798d8952021-10-19 14:43:19 +02009218 GsmBandArfcn arfcn,
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009219 FHParamsTs ts[8]
9220};
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009221
9222/* Randomly generate the hopping parameters for the given timeslot numbers */
9223private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
9224runs on test_CT return FHParamsTrx {
9225 var FHParamsTrx fhp;
9226
Philipp Maier798d8952021-10-19 14:43:19 +02009227 /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
9228 * fall in the GSM900 band. */
9229 fhp.arfcn.arfcn := f_rnd_int(3);
9230 fhp.arfcn.pcs := false;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009231
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009232 for (var integer tn := 0; tn < 8; tn := tn + 1) {
9233 if (not match(tn, tr_tn)) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009234 fhp.ts[tn].enabled := false;
9235 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009236 continue;
9237 }
9238
9239 /* Random HSN / MAIO values: 0..63 */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009240 fhp.ts[tn].hsn := f_rnd_int(64);
9241 fhp.ts[tn].maio := f_rnd_int(64);
9242 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009243
9244 /* Random Mobile Allocation (hopping channels) */
9245 var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
9246 var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
9247 for (var integer i := 1; i <= ma_len; i := i + 1) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009248 fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009249 }
9250
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009251 fhp.ts[tn].enabled := true;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009252 }
9253
9254 log("f_TC_fh_params_gen(): ", fhp);
9255 return fhp;
9256}
9257
9258/* Make sure that the given Channel Description IE matches the hopping configuration */
9259private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
9260{
9261 var template (present) ChannelDescription tr_cd;
9262 var template (present) MaioHsn tr_maio_hsn;
9263 var uint3_t tn := cd.chan_nr.tn;
9264
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009265 if (fhp.ts[tn].enabled) {
9266 tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009267 tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
9268 } else {
Philipp Maier798d8952021-10-19 14:43:19 +02009269 tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009270 }
9271
9272 if (not match(cd, tr_cd)) {
9273 setverdict(fail, "Channel Description IE does not match: ",
9274 cd, " vs expected ", tr_cd);
9275 }
9276}
9277
9278/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
9279private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
9280 in MobileAllocationLV ma)
9281{
9282 var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
9283
9284 if (not match(ma, tr_ma)) {
9285 setverdict(fail, "Mobile Allocation IE does not match (tn := ",
9286 tn, "): ", ma, " vs expected: ", tr_ma);
9287 } else {
9288 setverdict(pass);
9289 }
9290}
9291
9292private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
9293 in MobileAllocationLV ma)
9294return template MobileAllocationLV {
9295 /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009296 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009297 return { len := 0, ma := ''B };
9298 }
9299
9300 var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
9301 var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
9302 var bitstring ma_mask := ''B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009303
9304 /* Compose the full bit-mask (all channels, up to 1024 entries) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009305 for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
9306 for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
9307 if (full_mask[fhp.ts[i].ma[j]] == '1'B)
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009308 { continue; }
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009309 full_mask[fhp.ts[i].ma[j]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009310 }
9311 }
9312
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009313 /* Take ARFCN of the TRX itself into account */
Philipp Maier798d8952021-10-19 14:43:19 +02009314 full_mask[fhp.arfcn.arfcn] := '1'B;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009315
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009316 /* Compose a bit-mask for the given timeslot number */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009317 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9318 slot_mask[fhp.ts[tn].ma[i]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009319 }
9320
9321 /* Finally, compose the Mobile Allocation bit-mask */
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009322 for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009323 if (full_mask[i] != '1'B)
9324 { continue; }
9325
9326 /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
9327 if (slot_mask[i] == '1'B) {
9328 ma_mask := ma_mask & '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009329 } else {
9330 ma_mask := ma_mask & '0'B;
9331 }
9332 }
9333
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009334 /* ARFCN 0 (if present) goes to the last position of the bit-mask */
9335 if (full_mask[0] == '1'B) {
9336 /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
9337 if (slot_mask[0] == '1'B) {
9338 ma_mask := ma_mask & '1'B;
9339 } else {
9340 ma_mask := ma_mask & '0'B;
9341 }
9342 }
9343
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009344 /* Ensure that ma_mask is octet-aligned */
Vadim Yanitskiy2aa02522020-09-06 14:05:23 +07009345 var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009346 ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
9347
9348 return { len := ma_mask_len, ma := ma_mask };
9349}
9350
Philipp Maier798d8952021-10-19 14:43:19 +02009351/* Configure the appropriate band for a given arfcn, exc */
9352private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
9353{
9354 var charstring band;
9355 var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
9356
9357 select (arfcn_) {
9358 case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
9359 case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
9360 case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
9361 case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
9362 case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
9363 case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
9364 case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
9365 case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
9366 case else { return; }
9367 }
9368
9369 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9370 f_vty_transceive(BSCVTY, "band " & band);
9371 f_vty_transceive(BSCVTY, "end");
9372}
9373
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009374/* Configure the hopping parameters in accordance with the given record */
9375private function f_TC_fh_params_set(in FHParamsTrx fhp,
9376 uint8_t bts_nr := 0,
9377 uint8_t trx_nr := 0)
9378runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009379
9380 f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
9381
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009382 /* Enter the configuration node for the given BTS/TRX numbers */
9383 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9384
Philipp Maier798d8952021-10-19 14:43:19 +02009385 f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009386
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009387 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009388 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9389
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009390 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009391 f_vty_transceive(BSCVTY, "hopping enabled 0");
9392 f_vty_transceive(BSCVTY, "exit"); /* go back */
9393 continue;
9394 }
9395
9396 /* Configure HSN / MAIO values */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009397 f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
9398 f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009399
9400 /* Configure the Mobile Allocation (hopping channels) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009401 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9402 f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009403 }
9404
9405 f_vty_transceive(BSCVTY, "hopping enabled 1");
9406 f_vty_transceive(BSCVTY, "exit"); /* go back */
9407 }
9408
9409 f_vty_transceive(BSCVTY, "end");
9410}
9411
9412/* Disable frequency hopping on all timeslots */
9413private function f_TC_fh_params_unset(in FHParamsTrx fhp,
9414 uint8_t bts_nr := 0,
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009415 uint8_t trx_nr := 0,
Philipp Maier798d8952021-10-19 14:43:19 +02009416 GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009417runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009418
9419 f_TC_set_band_by_arfcn(bts_nr, arfcn);
9420
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009421 /* Enter the configuration node for the given BTS/TRX numbers */
9422 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9423
Philipp Maier798d8952021-10-19 14:43:19 +02009424 f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009425
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009426 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009427 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9428
9429 /* Delete all ARFCNs from the Mobile Allocation (if any) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009430 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9431 f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009432 }
9433
9434 f_vty_transceive(BSCVTY, "hopping enabled 0");
9435 f_vty_transceive(BSCVTY, "exit"); /* go back */
9436 }
9437
9438 f_vty_transceive(BSCVTY, "end");
9439 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9440}
9441
9442/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
9443 * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
9444testcase TC_fh_params_chan_activ() runs on test_CT {
9445 var FHParamsTrx fhp := f_TC_fh_params_gen();
9446 var RSL_Message rsl_msg;
9447 var RSL_IE_Body ie;
9448
9449 f_init_vty();
9450
9451 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9452 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9453
9454 f_init(1);
9455
9456 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9457 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009458 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9459 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009460
9461 /* Make sure that Channel Identification IE is present */
9462 if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
9463 setverdict(fail, "RSL Channel Identification IE is absent");
9464 continue;
9465 }
9466
9467 /* Make sure that hopping parameters (HSN/MAIO) match */
9468 f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
9469
9470 /* "Mobile Allocation shall be included but empty" - let's check this */
9471 if (ie.chan_ident.ma.v.len != 0) {
9472 setverdict(fail, "Mobile Allocation IE is not empty: ",
9473 ie.chan_ident.ma, ", despite it shall be");
9474 continue;
9475 }
9476 }
9477
9478 /* Disable frequency hopping */
9479 f_TC_fh_params_unset(fhp);
9480
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009481 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009482}
9483
9484/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
9485testcase TC_fh_params_imm_ass() runs on test_CT {
9486 var FHParamsTrx fhp := f_TC_fh_params_gen();
9487 var RSL_Message rsl_msg;
9488 var RSL_IE_Body ie;
9489
9490 f_init_vty();
9491
9492 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9493 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9494
9495 f_init(1);
9496
9497 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9498 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009499 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9500 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009501
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009502 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9503 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009504
9505 /* Make sure that Full Immediate Assign Info IE is present */
9506 if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
9507 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
9508 continue;
9509 }
9510
9511 /* Decode the actual Immediate Assignment message */
9512 var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
9513 if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
9514 setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
9515 continue;
9516 }
9517
9518 /* Make sure that hopping parameters (HSN/MAIO) match */
9519 f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
9520
9521 /* Make sure that the Mobile Allocation IE matches */
9522 f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
9523 rr_msg.payload.imm_ass.mobile_allocation);
9524 }
9525
9526 /* Disable frequency hopping */
9527 f_TC_fh_params_unset(fhp);
Philipp Maier82812002020-08-13 18:48:27 +02009528
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009529 f_shutdown_helper();
Philipp Maier82812002020-08-13 18:48:27 +02009530}
9531
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009532/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
9533testcase TC_fh_params_assignment_cmd() runs on test_CT {
9534 var FHParamsTrx fhp := f_TC_fh_params_gen();
9535 var RSL_Message rsl_msg;
9536 var RSL_IE_Body ie;
9537
9538 f_init_vty();
9539
9540 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9541 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9542
9543 f_init(1);
9544
9545 /* HACK: work around "Couldn't find Expect for CRCX" */
9546 vc_MGCP.stop;
9547
9548 var template PDU_BSSAP ass_cmd := f_gen_ass_req();
9549 ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
9550
9551 /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
9552 * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
9553 for (var integer i := 0; i < 3; i := i + 1) {
9554 /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
9555 var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, f_rnd_octstring(16));
9556
9557 /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
9558 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009559 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009560
9561 /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009562 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9563 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009564
9565 /* Make sure that L3 Information IE is present */
9566 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9567 setverdict(fail, "RSL L3 Information IE is absent");
9568 continue;
9569 }
9570
9571 /* Decode the L3 message and make sure it is (RR) Assignment Command */
9572 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9573 if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
9574 setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
9575 continue;
9576 }
9577
9578 /* Make sure that hopping parameters (HSN/MAIO) match */
9579 var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
9580 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9581
9582 /* Make sure that Cell Channel Description IE is present if FH is enabled */
9583 if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
Vadim Yanitskiy38d069d2020-09-02 17:18:57 +07009584 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009585 continue;
9586 }
9587
9588 /* Make sure that the Mobile Allocation IE matches (if present) */
9589 var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
9590 if (chan_desc.h and ma_present) {
9591 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9592 l3_msg.payload.ass_cmd.mobile_allocation.v);
9593 } else if (chan_desc.h and not ma_present) {
9594 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9595 continue;
9596 } else if (not chan_desc.h and ma_present) {
9597 setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
9598 continue;
9599 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009600
9601 f_perform_clear_test_ct(dt);
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009602 }
9603
9604 /* Give the IUT some time to release all channels */
9605 f_sleep(3.0);
9606
9607 /* Disable frequency hopping */
9608 f_TC_fh_params_unset(fhp);
9609
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009610 f_shutdown_helper();
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009611}
9612
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009613/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
9614private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
9615runs on test_CT {
9616 var RSL_Message rsl_msg;
9617 var RSL_IE_Body ie;
9618 var DchanTuple dt;
9619
9620 /* Establish a dedicated channel, so we can trigger handover */
9621 dt := f_est_dchan(f_rnd_ra_cs(), 23, f_rnd_octstring(16));
Vadim Yanitskiyc18ff472021-11-18 20:15:37 +03009622 f_sleep(0.5);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009623
9624 /* Trigger handover from BTS0 to BTS1 */
9625 f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
9626 f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
9627
9628 /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009629 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx := {1, 0});
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009630
9631 /* ACKnowledge channel activation and expect (RR) Handover Command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009632 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33), idx := {1, 0});
9633 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009634
9635 /* Make sure that L3 Information IE is present */
9636 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9637 setverdict(fail, "RSL L3 Information IE is absent");
9638 return;
9639 }
9640
9641 /* Decode the L3 message and make sure it is (RR) Handover Command */
9642 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9643 if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
9644 setverdict(fail, "Failed to match Handover Command: ", l3_msg);
9645 return;
9646 }
9647
9648 /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
9649 var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
9650 if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
9651 setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
9652 return;
9653 }
9654
9655 /* Make sure that hopping parameters (HSN/MAIO) match */
9656 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9657
9658 /* Make sure that Cell Channel Description IE is present */
9659 if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
9660 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
9661 return;
9662 }
9663
9664 /* Make sure that the Mobile Allocation (after time) IE is present and matches */
9665 var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
9666 if (ma_present) {
9667 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9668 l3_msg.payload.ho_cmd.mobile_allocation.v);
9669 } else {
9670 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9671 return;
9672 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009673
9674 f_perform_clear_test_ct(dt);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009675}
9676testcase TC_fh_params_handover_cmd() runs on test_CT {
9677 var FHParamsTrx fhp := f_TC_fh_params_gen();
9678
9679 f_init_vty();
9680
9681 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
9682 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
9683
9684 f_vty_transceive(BSCVTY, "timeslot 0");
9685 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
9686 f_vty_transceive(BSCVTY, "exit"); /* go back */
9687
9688 f_vty_transceive(BSCVTY, "timeslot 1");
9689 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
9690 f_vty_transceive(BSCVTY, "end"); /* we're done */
9691
9692 f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
9693 f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
9694
9695 f_init(2);
9696
9697 f_TC_fh_params_handover_cmd(fhp);
9698
9699 /* Disable frequency hopping on BTS1 */
9700 f_TC_fh_params_unset(fhp, 1);
9701
9702 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
9703 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
9704
9705 f_vty_transceive(BSCVTY, "timeslot 0");
9706 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
9707 f_vty_transceive(BSCVTY, "exit"); /* go back */
9708
9709 f_vty_transceive(BSCVTY, "timeslot 1");
9710 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
9711 f_vty_transceive(BSCVTY, "end"); /* we're done */
9712
9713 f_shutdown_helper();
9714}
9715
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009716/* Verify the hopping parameters in System Information Type 4 */
9717testcase TC_fh_params_si4_cbch() runs on test_CT {
9718 var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
9719 var ASP_RSL_Unitdata rx_rsl_ud;
9720 timer T := 5.0;
9721
9722 f_init_vty();
9723
9724 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
9725 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
9726
9727 f_vty_transceive(BSCVTY, "timeslot 0");
9728 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
9729 f_vty_transceive(BSCVTY, "exit"); /* go back */
9730
9731 f_vty_transceive(BSCVTY, "timeslot 1");
9732 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
9733 f_vty_transceive(BSCVTY, "end"); /* we're done */
9734
9735 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9736 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9737
9738 f_init(1);
9739
9740 T.start;
9741 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009742 [] 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 +07009743 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
9744 var SystemInformation si := dec_SystemInformation(ie.other.payload);
9745
9746 /* Make sure that what we decoded is System Information Type 4 */
9747 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
9748 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
9749 repeat;
9750 }
9751
9752 /* Make sure that CBCH Channel Description IE is present */
9753 if (not ispresent(si.payload.si4.cbch_chan_desc)) {
9754 setverdict(fail, "CBCH Channel Description IE is absent");
9755 break;
9756 }
9757
9758 /* Finally, check the hopping parameters (HSN, MAIO) */
9759 var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
9760 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9761
9762 /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
9763 * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
9764 if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
9765 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9766 break;
9767 } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
9768 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9769 si.payload.si4.cbch_mobile_alloc.v);
9770 }
9771 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009772 [] IPA_RSL[0][0].receive { repeat; }
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009773 [] T.timeout {
9774 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
9775 }
9776 }
9777
9778 /* Disable frequency hopping */
9779 f_TC_fh_params_unset(fhp);
9780
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +07009781 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009782 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
9783
9784 f_vty_transceive(BSCVTY, "timeslot 0");
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +07009785 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009786 f_vty_transceive(BSCVTY, "exit"); /* go back */
9787
9788 f_vty_transceive(BSCVTY, "timeslot 1");
9789 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
9790 f_vty_transceive(BSCVTY, "end"); /* we're done */
9791
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009792 f_shutdown_helper();
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009793}
9794
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009795template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
9796 := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
9797
9798private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
9799 template (present) BSSLAP_PDU expect_bsslap)
9800{
9801 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
9802 if (not match(bsslap, expect_bsslap)) {
9803 log("EXPECTING BSSLAP: ", expect_bsslap);
9804 log("GOT BSSLAP: ", bsslap);
9805 setverdict(fail, "BSSLAP is not as expected");
9806 mtc.stop;
9807 }
9808 setverdict(pass);
9809}
9810
9811/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
9812const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
9813
9814private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
9815 var PDU_BSSAP_LE rx_bsslap;
9816 BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
9817 f_match_bsslap(rx_bsslap, expect_rx_bsslap);
9818}
9819
9820/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9821 * Request on Lb interface. Either with or without the SMLC doing a BSSLAP TA Request. */
9822private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
9823 f_sleep(1.0);
9824
9825 f_establish_fully(omit, omit);
9826 f_bssap_le_register_imsi(g_pars.imsi, omit);
9827
9828 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9829 ts_CellId_CGI('262'H, '42'H, 23, 42))));
9830
9831 var PDU_BSSAP_LE plr;
9832 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9833
9834 if (not do_ta_request) {
9835 /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
9836 var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
9837 if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
9838 log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
9839 log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
9840 setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
9841 mtc.stop;
9842 }
9843 var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
9844 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
9845 if (not match(bsslap, expect_ta_layer3)) {
9846 log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
9847 log("GOT BSSLAP: ", bsslap);
9848 setverdict(fail, "BSSLAP is not as expected");
9849 mtc.stop;
9850 }
9851 /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
9852 * has no need to request the TA from the BSC and directly responds. */
9853 } else {
9854 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9855 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9856 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
9857 }
9858
9859 /* SMLC got the TA from the BSC, now responds with geo information data. */
9860 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
9861 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9862 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
9863
9864 /* The LCS was using an active A-interface conn. It should still remain active after this. */
9865 f_mo_l3_transceive();
9866
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009867 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009868
9869 f_sleep(2.0);
9870 setverdict(pass);
9871}
9872
9873/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9874 * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
9875private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
9876 f_lcs_loc_req_for_active_ms(false);
9877}
9878testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
9879 var MSC_ConnHdlr vc_conn;
9880 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9881
9882 f_init(1, true);
9883 f_sleep(1.0);
9884 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
9885 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009886 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009887}
9888
9889/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9890 * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
9891private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
9892 f_lcs_loc_req_for_active_ms(true);
9893}
9894testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
9895 var MSC_ConnHdlr vc_conn;
9896 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9897
9898 f_init(1, true);
9899 f_sleep(1.0);
9900 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
9901 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009902 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009903}
9904
9905/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
9906 * conn without an active lchan. */
9907private function f_clear_A_conn() runs on MSC_ConnHdlr
9908{
9909 var BssmapCause cause := 0;
9910 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
9911 BSSAP.receive(tr_BSSMAP_ClearComplete);
9912 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
9913
9914 timer no_more_bssap := 5.0;
9915 no_more_bssap.start;
9916 alt {
9917 [] no_more_bssap.timeout { break; }
9918 [] BSSAP.receive(tr_BSSAP_BSSMAP) {
9919 setverdict(fail, "Expected no more BSSAP after Clear Complete");
9920 mtc.stop;
9921 }
9922 }
9923 setverdict(pass);
9924}
9925
9926/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
9927 * for LCS, for cases where there is only an A conn without an active lchan. */
9928private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
9929{
9930 f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
9931
9932 /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
9933 * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
9934 * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
9935 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9936 ts_CellId_CGI('262'H, '42'H, 23, 42))));
9937 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
9938
9939 /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
9940 f_clear_A_conn();
9941 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
9942 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9943}
9944
9945/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9946 * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
9947 */
9948private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
9949 f_sleep(1.0);
9950
9951 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9952 f_bssap_le_register_imsi(g_pars.imsi, omit);
9953
9954 /* Register to receive the Paging Command */
9955 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
9956 g_chan_nr := new_chan_nr;
9957 f_rslem_register(0, g_chan_nr);
9958
9959 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
9960 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9961 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
9962 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
9963
9964 var PDU_BSSAP_LE plr;
9965 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9966
9967 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9968 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9969
9970 /* OsmoBSC needs to Page */
9971 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
9972 f_logp(BSCVTY, "got Paging Command");
9973
9974 /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
9975 * the MSC, and releases the lchan directly. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009976 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);
9977 f_expect_lchan_rel(RSL, RSL_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009978
9979 /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
9980
9981 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
9982
9983 /* SMLC got the TA from the BSC, now responds with geo information data. */
9984 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
9985 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9986
9987 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
9988
9989 /* The lchan is gone, the A-interface conn was created for the LCS only.
9990 * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
9991 f_verify_active_A_conn_and_clear();
9992
9993 f_sleep(2.0);
9994 setverdict(pass);
9995}
9996testcase TC_lcs_loc_req_for_idle_ms() runs on test_CT {
9997 var MSC_ConnHdlr vc_conn;
9998 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9999
10000 f_init(1, true);
10001 f_sleep(1.0);
10002
10003 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10004 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10005
10006 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
10007 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010008 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010009}
10010
10011/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
10012 */
10013private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
10014 f_sleep(1.0);
10015
10016 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10017 f_bssap_le_register_imsi(g_pars.imsi, omit);
10018
10019 /* provoke an abort by omitting both IMSI and IMEI */
10020 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10021 valueof(ts_BSSMAP_Perform_Location_Request(omit,
10022 ts_CellId_CGI('262'H, '42'H, 23, 42)))));
10023 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10024
10025 /* BSC tells MSC about failure */
10026 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10027 locationEstimate := omit, positioningData := omit,
10028 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
10029
10030 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10031 f_verify_active_A_conn_and_clear();
10032
10033 f_sleep(2.0);
10034 setverdict(pass);
10035}
10036testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
10037 var MSC_ConnHdlr vc_conn;
10038 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10039
10040 f_init(1, true);
10041 f_sleep(1.0);
10042
10043 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10044 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10045
10046 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
10047 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010048 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010049}
10050
10051/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10052 * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
10053private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
10054 f_sleep(1.0);
10055
10056 f_establish_fully(omit, omit);
10057 f_bssap_le_register_imsi(g_pars.imsi, omit);
10058
10059 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10060 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10061
10062 var PDU_BSSAP_LE plr;
10063 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10064
10065 if (do_ta) {
10066 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10067 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10068 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10069 }
10070
10071 /* SMLC fails to respond, BSC runs into timeout */
10072 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
10073 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10074
10075 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10076 locationEstimate := omit, positioningData := omit,
10077 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
10078
10079 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10080 f_verify_active_A_conn_and_clear();
10081
10082 f_sleep(2.0);
10083 setverdict(pass);
10084}
10085
10086/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10087 * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
10088private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
10089 f_lcs_loc_req_for_active_ms_le_timeout(false);
10090}
10091
10092testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
10093 var MSC_ConnHdlr vc_conn;
10094 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10095
10096 f_init(1, true);
10097 f_sleep(1.0);
10098 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
10099 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010100 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010101}
10102
10103/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10104 * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
10105private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
10106 f_lcs_loc_req_for_active_ms_le_timeout(true);
10107}
10108
10109testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
10110 var MSC_ConnHdlr vc_conn;
10111 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10112
10113 f_init(1, true);
10114 f_sleep(1.0);
10115 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
10116 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010117 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010118}
10119
10120/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
10121private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
10122 f_sleep(1.0);
10123
10124 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10125 f_bssap_le_register_imsi(g_pars.imsi, omit);
10126
10127 /* Register to receive the Paging Command */
10128 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10129 g_chan_nr := new_chan_nr;
10130 f_rslem_register(0, g_chan_nr);
10131
10132 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10133 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10134 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10135 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10136
10137 var PDU_BSSAP_LE plr;
10138 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10139
10140 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10141 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10142
10143 /* OsmoBSC needs to Page */
10144 var PDU_BSSAP_LE rx_bsslap;
10145 alt {
10146 [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
10147 f_logp(BSCVTY, "got Paging Command");
10148 repeat;
10149 }
10150 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10151 /* MS does not respond to Paging, TA Req runs into timeout. */
10152 f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
10153 }
10154 }
10155
10156 /* SMLC responds with failure */
10157 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10158 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10159
10160 /* BSC tells MSC about failure */
10161 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10162 locationEstimate := omit, positioningData := omit,
10163 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
10164
10165 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10166 f_verify_active_A_conn_and_clear();
10167
10168 f_sleep(2.0);
10169 setverdict(pass);
10170}
10171testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
10172 var MSC_ConnHdlr vc_conn;
10173 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10174
10175 f_init(1, true);
10176 f_sleep(1.0);
10177
10178 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10179 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10180
10181 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
10182 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010183 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010184}
10185
10186/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
10187 * over. */
10188private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10189 f_sleep(1.0);
10190
10191 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10192 f_bssap_le_register_imsi(g_pars.imsi, omit);
10193
10194 /* Register to receive the Paging Command */
10195 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10196 g_chan_nr := new_chan_nr;
10197 f_rslem_register(0, g_chan_nr);
10198
10199 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10200 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10201 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10202 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10203
10204 var PDU_BSSAP_LE plr;
10205 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10206
10207 /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
10208 * and establish Layer 3. It should use the existing A-interface conn. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010209 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 +020010210 do_clear := false, expect_bssmap_l3 := true);
10211
10212 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10213 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10214
10215 /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
10216 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10217
10218 /* SMLC got the TA from the BSC, now responds with geo information data. */
10219 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10220 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10221 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10222
10223 /* The lchan should still exist, it was from a CM Service Request. */
10224 f_mo_l3_transceive();
10225
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010226 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010227
10228 f_sleep(2.0);
10229 setverdict(pass);
10230}
10231testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
10232 var MSC_ConnHdlr vc_conn;
10233 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10234
10235 f_init(1, true);
10236 f_sleep(1.0);
10237
10238 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10239 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10240
10241 vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
10242 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010243 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010244}
10245
10246/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
10247 * the new lchan after handover. */
10248private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10249 f_sleep(1.0);
10250
10251 f_establish_fully(omit, omit);
10252 f_bssap_le_register_imsi(g_pars.imsi, omit);
10253
10254 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10255 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10256
10257 var PDU_BSSAP_LE plr;
10258 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10259
10260 /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
10261 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
10262
10263 var HandoverState hs := {
10264 rr_ho_cmpl_seen := false,
10265 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +020010266 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010267 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010268 };
10269 /* issue hand-over command on VTY */
10270 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
10271 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
10272 f_rslem_suspend(RSL1_PROC);
10273
10274 /* From the MGW perspective, a handover is is characterized by
10275 * performing one MDCX operation with the MGW. So we expect to see
10276 * one more MDCX during handover. */
10277 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
10278
10279 alt {
10280 [] as_handover(hs);
10281 }
10282
10283 var PDU_BSSAP_LE rx_bsslap;
10284
10285 interleave {
10286 /* Expect the BSC to inform the MSC about the handover */
10287 [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
10288
10289 /* Expect the BSC to inform the SMLC about the handover */
10290 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10291 f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
10292 }
10293 }
10294
10295 /* SMLC now responds with geo information data. */
10296 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10297 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10298 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10299
10300 /* lchan still active */
10301 f_mo_l3_transceive(RSL1);
10302
10303 /* MSC decides it is done now. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010304 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010305
10306 f_sleep(2.0);
10307 setverdict(pass);
10308}
10309testcase TC_ho_during_lcs_loc_req() runs on test_CT {
10310 var MSC_ConnHdlr vc_conn;
10311 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10312
10313 f_init(2, true);
10314 f_sleep(1.0);
10315 vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
10316 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010317 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010318}
10319
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010320private function f_tc_emerg_call_and_lcs_loc_req(charstring id) runs on MSC_ConnHdlr
10321{
10322 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
10323 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
10324 * another lchan. */
10325 g_pars.ra := 'b7'O;
10326 f_assignment_emerg_setup();
10327
10328 var PDU_BSSAP emerg_setup_data_ind_bssap;
10329 timer T := 3.0;
10330 T.start;
10331 alt {
10332 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
10333 var PDU_ML3_MS_NW verify_emerg_setup;
10334 verify_emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
10335 if (not isbound(verify_emerg_setup.msgs.cc.emergencySetup)) {
10336 setverdict(fail, "no emergency setup");
10337 }
10338 }
10339 [] BSSAP.receive {
10340 setverdict(fail, "unexpected BSSAP message!");
10341 }
10342 [] T.timeout {
10343 setverdict(fail, "timeout waiting for EMERGENCY SETUP!");
10344 }
10345 }
10346
10347 /* Here would usually be a CC Call Proceeding from the MSC, but what does the BSC care about DTAP. */
10348
10349 /* Do a Location Request in-between the CC call setup */
10350 f_bssap_le_register_imsi(g_pars.imsi, omit);
10351 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10352 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10353 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10354 /* SMLC got the TA from the BSC, now responds with geo information data. */
10355 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10356 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10357 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10358
10359 /* Go on with voice call assignment */
10360 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
10361 var PDU_BSSAP ass_cmd := f_gen_ass_req();
10362
10363 /* Below speechOrDataIndicator and codecList are copied from an emergency call captured during tests.
10364 * They seem a bit weird (AMR-WB, and the order differ between speechId_DataIndicator and the codecList), but
10365 * seems a good idea to see how osmo-bsc reacts to this. */
10366 ass_cmd.pdu.bssmap.assignmentRequest.channelType := {
10367 elementIdentifier := '0B'O, /* overwritten */
10368 lengthIndicator := 0, /* overwritten */
10369 speechOrDataIndicator := '0001'B, /* speech */
10370 spare1_4 := '0000'B,
10371 channelRateAndType := ChRate_TCHForH_Fpref,
10372 speechId_DataIndicator := 'c2918105'O
10373 };
10374 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({
10375 ts_CodecHR, ts_CodecAMR_WB, ts_CodecEFR, ts_CodecFR}));
10376
10377 f_rslem_dchan_queue_enable();
10378
10379 var ExpectCriteria mgcpcrit := {
10380 connid := omit,
10381 endpoint := omit,
10382 transid := omit
10383 };
10384 f_create_mgcp_expect(mgcpcrit);
10385
10386 BSSAP.send(ass_cmd);
10387
10388 var AssignmentState st := valueof(ts_AssignmentStateInit);
10389 st.voice_call := true;
10390 st.is_assignment := false;
10391 alt {
10392 [] as_modify(st);
10393 [] as_Media();
10394 [st.modify_done] BSSAP.receive(exp_compl) {
10395 setverdict(pass);
10396 }
10397 }
10398
10399 /* Voice call carries on ... */
10400 f_sleep(2.0);
10401
10402 setverdict(pass);
10403 f_perform_clear();
10404}
10405
10406testcase TC_emerg_call_and_lcs_loc_req() runs on test_CT {
10407 var MSC_ConnHdlr vc_conn;
10408 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10409
10410 f_init(1, true);
10411 f_sleep(1.0);
10412 f_vty_allow_emerg_msc(true);
10413 f_vty_allow_emerg_bts(true, 0);
10414 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req), pars);
10415 vc_conn.done;
10416 f_shutdown_helper();
10417}
10418
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010419private altstep no_bssmap_clear_req() runs on MSC_ConnHdlr {
10420 [] BSSAP.receive(tr_BSSMAP_ClearRequest) {
10421 setverdict(fail, "unexpected BSSMAP Clear Request");
10422 mtc.stop;
10423 }
10424}
10425
10426private type enumerated RslRel {
10427 RSLREL_REL_IND,
10428 RSLREL_CONN_FAIL
10429};
10430
10431private function f_emerg_call_and_lcs_loc_req_early_lchan_release(RslRel rsl_rel) runs on MSC_ConnHdlr
10432{
10433 g_pars.ra := f_rnd_ra_emerg();
10434 f_assignment_emerg_setup();
10435
10436 var PDU_BSSAP emerg_setup_data_ind_bssap;
10437 timer T := 3.0;
10438 T.start;
10439 alt {
10440 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
10441 var PDU_ML3_MS_NW verify_emerg_setup;
10442 verify_emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
10443 if (not ischosen(verify_emerg_setup.msgs.cc.emergencySetup)) {
10444 setverdict(fail, "no emergency setup");
10445 }
10446 }
10447 [] BSSAP.receive {
10448 setverdict(fail, "unexpected BSSAP message!");
10449 }
10450 [] T.timeout {
10451 setverdict(fail, "timeout waiting for EMERGENCY SETUP!");
10452 }
10453 }
10454
10455 /* Start a Location Request to locate the emergency */
10456 f_bssap_le_register_imsi(g_pars.imsi, omit);
10457 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10458 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10459 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10460
10461 /* 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
10462 * do a Clear Command when the Location Response arrives. */
10463 activate(no_bssmap_clear_req());
10464
10465 /* the lchan gets interrupted while the Location Request has no response */
10466 select (rsl_rel) {
10467 case (RSLREL_REL_IND) {
10468 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
10469 f_expect_lchan_rel(RSL, RSL_PROC);
10470 }
10471 case (RSLREL_CONN_FAIL) {
10472 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
10473 }
10474 case else {
10475 setverdict(fail, "Unknown RslRel type");
10476 mtc.stop;
10477 }
10478 }
10479
10480 /* Still expect the Location Response to find its way to the MSC. */
10481 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10482 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10483 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10484
10485 setverdict(pass);
10486
10487 select (rsl_rel) {
10488 case (RSLREL_REL_IND) {
10489 f_perform_clear_no_lchan();
10490 }
10491 case (RSLREL_CONN_FAIL) {
10492 f_perform_clear();
10493 }
10494 }
10495}
10496
10497private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind(charstring id) runs on MSC_ConnHdlr
10498{
10499 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_REL_IND);
10500}
10501
10502testcase TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() runs on test_CT {
10503 var MSC_ConnHdlr vc_conn;
10504 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10505
10506 f_init(1, true);
10507 f_sleep(1.0);
10508 f_vty_allow_emerg_msc(true);
10509 f_vty_allow_emerg_bts(true, 0);
10510 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind), pars);
10511 vc_conn.done;
10512 f_shutdown_helper();
10513}
10514
10515private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail(charstring id) runs on MSC_ConnHdlr
10516{
10517 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_CONN_FAIL);
10518}
10519
10520testcase TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() runs on test_CT {
10521 var MSC_ConnHdlr vc_conn;
10522 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10523
10524 f_init(1, true);
10525 f_sleep(1.0);
10526 f_vty_allow_emerg_msc(true);
10527 f_vty_allow_emerg_bts(true, 0);
10528 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail), pars);
10529 vc_conn.done;
10530 f_shutdown_helper();
10531}
10532
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010533/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
10534private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
10535 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10536
10537 /* Also disable attach for the single connected MSC */
10538 f_vty_msc_allow_attach(BSCVTY, { false });
10539
10540 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) ));
10541 f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
10542
10543 /* No MSC is found, expecting a proper release on RSL */
10544 interleave {
10545 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
10546 f_logp(BSCVTY, "Got RSL RR Release");
10547 }
10548 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10549 f_logp(BSCVTY, "Got RSL Deact SACCH");
10550 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010551 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010552 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
10553 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010554 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010555 }
10556 }
10557 setverdict(pass);
10558}
10559testcase TC_no_msc() runs on test_CT {
10560
10561 f_init(1, true);
10562 f_sleep(1.0);
10563 var MSC_ConnHdlr vc_conn;
10564 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10565
10566 f_ctrs_bsc_init(counternames_bsc_mscpool);
10567
10568 vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
10569 vc_conn.done;
10570
10571 f_ctrs_bsc_add("mscpool:subscr:no_msc");
10572 f_ctrs_bsc_verify();
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010573 f_shutdown_helper();
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010574}
10575
Harald Welte0ea2d5e2018-04-07 21:40:29 +020010576/* Dyn PDCH todo:
10577 * activate OSMO as TCH/F
10578 * activate OSMO as TCH/H
10579 * does the BSC-located PCU socket get the updated INFO?
10580 * what if no PCU is connected at the time?
10581 * is the info correct on delayed PCU (re)connect?
10582 */
Harald Welte94e0c342018-04-07 11:33:23 +020010583
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010584private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +020010585 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020010586 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010587
10588 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
10589 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10590 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
10591 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
10592 g_pars.ass_codec_list.codecElements[0];
10593 if (isvalue(g_pars.expect_mr_s0_s7)) {
10594 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
10595 g_pars.expect_mr_s0_s7;
10596 }
10597 }
10598 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
10599 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
10600 log("expecting ASS COMPL like this: ", exp_compl);
10601
10602 f_establish_fully(ass_cmd, exp_compl);
10603
Neels Hofmeyr8746b0d2021-06-01 17:25:39 +020010604 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 +000010605
10606 var RSL_Message rsl;
10607
10608 timer T := 5.0;
10609 T.start;
10610 alt {
10611 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
10612 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
10613 log("Rx L3 from net: ", l3);
10614 if (ischosen(l3.msgs.rrm.channelModeModify)) {
10615 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10616 mtc.stop;
10617 }
10618 }
10619 [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
10620 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10621 mtc.stop;
10622 }
10623 [] T.timeout {
10624 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
10625 setverdict(pass);
10626 }
10627 }
10628 T.stop;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010629
10630 f_perform_clear();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010631}
10632
10633/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
10634 * osmo-bsc. */
10635testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
10636 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10637 var MSC_ConnHdlr vc_conn;
10638
10639 f_init(1, true);
10640 f_sleep(1.0);
10641
10642 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10643 vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
10644 vc_conn.done;
10645 f_shutdown_helper();
10646}
10647
10648/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
10649 */
10650testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
10651 f_init_vty();
10652
10653 f_init(1, false);
10654 f_sleep(1.0);
10655
10656 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
10657
10658 var ASP_RSL_Unitdata rx_rsl_ud;
10659 timer T := 5.0;
10660
10661 T.start;
10662 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010663 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010664 if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
10665 T.stop;
10666 setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
10667 mtc.stop;
10668 }
10669 repeat;
10670 }
10671 [] T.timeout {
10672 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
10673 setverdict(pass);
10674 }
10675 }
10676}
10677
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010678private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
10679 /* First fully set up a speech lchan */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010680 f_assignment_codec(id, do_perform_clear := false);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010681
10682 /* Trigger re-assignment to another lchan */
10683 var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
10684
10685 /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
10686 * one MDCX on MGCP. */
10687 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
10688
10689 /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
10690 * as the old lchan used. */
10691 g_media.bts.ipa_crcx_seen := false;
10692 g_media.bts.ipa_mdcx_seen := false;
10693
10694 /* Send different BTS side RTP port number for the new lchan */
10695 g_media.bts.bts.port_nr := 4223;
10696
10697 f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
10698
10699 /* Trigger re-assignment. */
10700 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
10701
10702 timer T := 5.0;
10703 T.start;
10704 alt {
10705 [] as_assignment(assignment_st);
10706 [] as_Media();
10707 [] T.timeout {
10708 break;
10709 }
10710 }
10711
10712 if (not assignment_st.assignment_done) {
10713 setverdict(fail, "Assignment did not complete");
10714 mtc.stop;
10715 }
10716
10717 f_check_mgcp_expectations()
10718 setverdict(pass);
10719
10720 f_sleep(2.0);
10721 log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
10722
10723 /* Instruct BSC to clear channel */
10724 var BssmapCause cause := 0;
10725 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10726 interleave {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010727 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
10728 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010729 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010730 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010731 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010732 }
10733 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
10734 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10735 }
10736 }
Neels Hofmeyr40a45d12021-09-23 22:57:12 +020010737 f_expect_dlcx_conns();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010738
10739 f_sleep(0.5);
10740}
10741
10742testcase TC_reassignment_fr() runs on test_CT {
10743 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10744 var MSC_ConnHdlr vc_conn;
10745
10746 f_init(1, true);
10747 f_sleep(1.0);
10748
Neels Hofmeyrac432fa2021-11-02 16:45:56 +010010749 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010750
10751 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10752 vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
10753 vc_conn.done;
10754
10755 /* from f_establish_fully() */
10756 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
10757 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
10758 /* from re-assignment */
10759 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
10760 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
10761 f_ctrs_bsc_and_bts_verify();
10762 f_shutdown_helper();
10763}
10764
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010765const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
10766const charstring REEST_CLEAR := "REEST_CLEAR";
10767const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
10768
10769/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
10770 * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
10771 * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
10772 * the MSC as the CM Re-Establishment is handled.
10773 *
10774 * MS bts0 bts1 bsc msc test-component
10775 * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
10776 * | | _1 wait a bit, to settle down
10777 * |<-x x--| | _1 "lose connection"
10778 * | | REEST_LOST_CONNECTION
10779 * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
10780 * | | REEST_CLEAR
10781 * | |<-0---| _1 Clear Command on first A-conn
10782 * | |--0-->| _1 Clear Complete
10783 * | |<----------------->| | _1 Release first channel
10784 * | | REEST_CLEAR_DONE
10785 * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
10786 * |<-----------------|<-------|<-1---| _2 Clear Command, Release
10787 *
10788 */
10789private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
10790 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
10791 var PDU_BSSAP ass_cmd := f_gen_ass_req();
10792
10793 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
10794 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10795
10796 f_establish_fully(ass_cmd, exp_compl);
10797
10798 /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
10799 * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
10800 * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
10801 f_sleep(2.0);
10802 COORD.send(REEST_LOST_CONNECTION);
10803
10804 alt {
10805 [] COORD.receive(REEST_CLEAR);
10806 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10807 setverdict(fail, "Unexpected channel release");
10808 mtc.stop;
10809 }
10810 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
10811 setverdict(fail, "Unexpected channel release");
10812 mtc.stop;
10813 }
10814 }
10815 f_perform_clear()
Neels Hofmeyr969abd02021-09-23 22:24:08 +020010816 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010817 COORD.send(REEST_CLEAR_DONE);
10818}
10819
10820private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
10821 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
10822
10823 /* The MS lost the connection on the first channel, now establishes another one */
10824 COORD.receive(REEST_LOST_CONNECTION);
10825
10826 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
10827 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
10828 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
10829
10830 f_create_bssmap_exp(l3_enc);
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010831 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 +020010832 BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
10833
10834 /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
10835 COORD.send(REEST_CLEAR);
10836 COORD.receive(REEST_CLEAR_DONE);
10837
10838 f_sleep(2.0);
10839
10840 /* Answer the CM Re-Establishment with an Assignment Command. */
10841 var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
10842 var PDU_BSSAP ass_cmd := f_gen_ass_req();
10843 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
10844 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10845
10846 var AssignmentState st := valueof(ts_AssignmentStateInit);
10847 st.voice_call := true;
10848 st.is_assignment := true;
10849
10850 var ExpectCriteria mgcpcrit := {
10851 connid := omit,
10852 endpoint := omit,
10853 transid := omit
10854 };
10855 f_create_mgcp_expect(mgcpcrit);
10856
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010857 f_rslem_dchan_queue_enable(RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010858
10859 BSSAP.send(ass_cmd);
10860
10861 var PDU_BSSAP bssap;
10862
10863 alt {
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010864 [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
10865 [] as_Media_ipacc(RSL1, RSL2);
10866 [] as_Media_mgw();
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010867 [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
10868 break;
10869 }
10870 }
10871
10872 f_sleep(3.0);
10873
10874 f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010875 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010876}
10877
10878testcase TC_cm_reestablishment() runs on test_CT {
10879 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
10880 var MSC_ConnHdlr vc_conn1;
10881
10882 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
10883 var MSC_ConnHdlr vc_conn2;
10884 pars2.imsi := pars1.imsi;
10885 pars2.media_nr := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010886 pars2.expect_tsc := c_BtsParams[1].tsc;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010887
10888 f_init(2, true, guard_timeout := 40.0);
10889 f_sleep(1.0);
10890
10891 vc_conn1 := f_start_handler_create(pars1);
10892 vc_conn2 := f_start_handler_create(pars2);
10893 connect(vc_conn1:COORD, vc_conn2:COORD);
10894 f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
10895 f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
10896 vc_conn1.done;
10897 vc_conn2.done;
10898
10899 f_shutdown_helper();
10900}
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010901
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010902function f_exp_ipa_rx_nonfatal(template (present) RSL_Message t_rx,
10903 boolean ignore_other_rx := true,
10904 BtsTrxIdx idx := {0, 0},
10905 float Tval := 2.0)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010906runs on test_CT return template (omit) RSL_Message {
10907 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010908 timer T := Tval;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010909
10910 T.start;
10911 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010912 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010913 T.stop;
10914 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010915 [ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
10916 [not ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010917 log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
10918 T.stop;
10919 return omit;
10920 }
10921 [] T.timeout {
10922 return omit;
10923 }
10924 }
10925 return rx_rsl_ud.rsl;
10926}
10927
10928private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
10929 f_vty_enter_cfg_bts(pt, bts_nr);
10930 f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
10931 f_vty_transceive(pt, "exit");
10932 f_vty_transceive(pt, "exit");
10933 f_vty_transceive(pt, "exit");
10934}
10935
10936private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +030010937 template (present) RslChannelNr chan_nr := ?,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010938 template (present) uint12_t arfcn := ?,
10939 template (present) uint3_t tsc := ?)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010940{
10941 var RSL_IE_Body full_imm_ass_info;
10942 if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
10943 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
10944 mtc.stop;
10945 }
10946
10947 var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
10948 var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
10949 fn := fn,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010950 ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010951 page_mode := ?);
10952 if (not match(rr_imm_ass, expect_imm_ass)) {
10953 log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
10954 setverdict(fail, "Failed to match Immediate Assignment");
10955 mtc.stop;
10956 }
10957}
10958
10959testcase TC_imm_ass_post_chan_ack() runs on test_CT {
10960 var RSL_Message chan_act;
10961 var RSL_Message imm_ass;
10962
10963 f_init(1, false);
10964 f_sleep(1.0);
10965
10966 /* (should be the default anyway, just to make things clear) */
10967 f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
10968
10969 /* RA containing reason=LU */
10970 var GsmFrameNumber fn := 2342;
10971 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010972 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010973
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010974 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010975
10976 /* First send the Chan Act ACK */
10977 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010978 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010979 var RSL_IE_Body chan_ident_ie;
10980 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
10981 setverdict(fail, "RSL Channel Identification IE is absent");
10982 mtc.stop;
10983 }
10984
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010985 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010986
10987 /* Then expect the Immediate Assignment, after we ACKed the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010988 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010989
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010990 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
10991 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010992
10993 /* Check that the lchan is working */
10994 var octetstring l3 := '00010203040506'O;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010995 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010996
10997 var BSSAP_N_CONNECT_ind rx_c_ind;
10998 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010999 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011000 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11001
11002 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011003 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011004 f_shutdown_helper();
11005}
11006
11007testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
11008 var RSL_Message chan_act;
11009 var RSL_Message imm_ass;
11010
11011 f_init(1, false);
11012 f_sleep(1.0);
11013
11014 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11015
11016 /* RA containing reason=LU */
11017 var GsmFrameNumber fn := 2342;
11018 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011019 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011020
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011021 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011022 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011023 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011024 var RSL_IE_Body chan_ident_ie;
11025 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11026 setverdict(fail, "RSL Channel Identification IE is absent");
11027 mtc.stop;
11028 }
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011029
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011030 /* (set bts 0 cfg back to default) */
11031 f_vty_set_imm_ass(BSCVTY);
11032
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011033 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011034 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011035 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11036 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011037
11038 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011039 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011040
11041 /* Check that the lchan is working */
11042 var octetstring l3 := '00010203040506'O;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011043 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011044
11045 var BSSAP_N_CONNECT_ind rx_c_ind;
11046 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011047 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011048 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11049
11050 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011051 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011052 f_shutdown_helper();
11053}
11054
Neels Hofmeyr23158742021-09-07 19:08:07 +020011055testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
11056 var RSL_Message chan_act;
11057 var RSL_Message imm_ass;
11058
11059 f_init(1, false);
11060 f_sleep(1.0);
11061
11062 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11063
11064 /* RA containing reason=LU */
11065 var GsmFrameNumber fn := 2342;
11066 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011067 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011068
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011069 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011070 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011071 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr23158742021-09-07 19:08:07 +020011072 var RSL_IE_Body chan_ident_ie;
11073 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11074 setverdict(fail, "RSL Channel Identification IE is absent");
11075 mtc.stop;
11076 }
11077
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011078 /* (set bts 0 cfg back to default) */
11079 f_vty_set_imm_ass(BSCVTY);
11080
Neels Hofmeyr23158742021-09-07 19:08:07 +020011081 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011082 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011083 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11084 chan_ident_ie.chan_ident.ch_desc.v.tsc);
11085
11086 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011087 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011088
11089 /* Check that the lchan is working */
11090 var octetstring l3 := '00010203040506'O;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011091 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011092
11093 var BSSAP_N_CONNECT_ind rx_c_ind;
11094 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011095 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr23158742021-09-07 19:08:07 +020011096 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11097
11098 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011099 f_perform_clear_test_ct(dt);
Neels Hofmeyr23158742021-09-07 19:08:07 +020011100 f_shutdown_helper();
11101}
11102
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011103testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
11104 /* change Timeslot 6 before f_init() starts RSL */
11105 f_init_vty();
11106 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11107 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11108
11109 f_init(1, false);
11110 f_sleep(1.0);
11111
11112 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11113 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011114 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11115 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011116
11117 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11118 f_ts_set_chcomb(0, 0, 6, "PDCH");
11119
11120 /* block all static timeslots so that the dyn TS will be used */
11121 f_disable_all_tch_f();
11122 f_disable_all_tch_h();
11123 f_disable_all_sdcch();
11124
11125 var RSL_Message chan_act;
11126 var RSL_Message imm_ass;
11127
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011128 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11129
11130 /* RA containing reason=LU */
11131 var GsmFrameNumber fn := 2342;
11132 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011133 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011134
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011135 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011136 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
11137 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011138
11139 /* Now activation as SDCCH8 */
11140 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011141 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011142
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011143 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011144 var RSL_IE_Body chan_ident_ie;
11145 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11146 setverdict(fail, "RSL Channel Identification IE is absent");
11147 mtc.stop;
11148 }
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011149
11150 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011151 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011152 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11153 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011154
11155 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011156 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011157
11158 /* Check that the lchan is working */
11159 var octetstring l3 := '00010203040506'O;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011160 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011161
11162 var BSSAP_N_CONNECT_ind rx_c_ind;
11163 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011164 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011165 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11166
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011167 /* (set bts 0 cfg back to default) */
11168 f_vty_set_imm_ass(BSCVTY);
11169
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011170 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011171 f_perform_clear_test_ct(dt);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011172 f_shutdown_helper();
11173}
11174
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011175testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
11176 /* change Timeslot 6 before f_init() starts RSL */
11177 f_init_vty();
11178 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11179 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11180
11181 f_init(1, false);
11182 f_sleep(1.0);
11183
11184 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11185 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011186 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11187 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011188
11189 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11190 f_ts_set_chcomb(0, 0, 6, "PDCH");
11191
11192 /* block all static timeslots so that the dyn TS will be used */
11193 f_disable_all_tch_f();
11194 f_disable_all_tch_h();
11195 f_disable_all_sdcch();
11196
11197 var RSL_Message chan_act;
11198 var RSL_Message imm_ass;
11199
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011200 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11201
11202 /* RA containing reason=LU */
11203 var GsmFrameNumber fn := 2342;
11204 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011205 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011206
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011207 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011208 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011209
11210 /* And already the Immediate Assignment even before the PDCH Deact ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011211 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011212
11213 /* continue the Osmo style PDCH Deact (usual chan rel) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011214 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011215
11216 /* Now activation as SDCCH8 */
11217 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011218 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011219
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011220 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011221 var RSL_IE_Body chan_ident_ie;
11222 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11223 setverdict(fail, "RSL Channel Identification IE is absent");
11224 mtc.stop;
11225 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011226 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011227
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011228 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11229 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011230
11231 /* Check that the lchan is working */
11232 var octetstring l3 := '00010203040506'O;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011233 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011234
11235 var BSSAP_N_CONNECT_ind rx_c_ind;
11236 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011237 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011238 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11239
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011240 /* (set bts 0 cfg back to default) */
11241 f_vty_set_imm_ass(BSCVTY);
11242
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011243 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011244 f_perform_clear_test_ct(dt);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011245 f_shutdown_helper();
11246}
11247
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011248/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
11249testcase TC_ctrl_trx_rf_locked() runs on test_CT {
11250 var MSC_ConnHdlr vc_conn;
11251
11252 f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
11253 f_sleep(1.0);
11254
11255 /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
11256 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11257 "0,0,operational,unlocked,on,rsl-up;" &
11258 "1,0,operational,unlocked,on,rsl-up;" &
11259 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011260 "2,1,operational,unlocked,on,rsl-down;" &
11261 "2,2,operational,unlocked,on,rsl-down;" &
11262 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011263 "3,0,inoperational,locked,on,rsl-down;");
11264
11265 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock BTS 1 TRX 0");
11266 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11267 /* give it a moment to settle the FSM status */
11268 f_sleep(1.0);
11269
11270 /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
11271 * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
11272 * of "off"? But that's for a future patch if at all. */
11273 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11274 "0,0,operational,unlocked,on,rsl-up;" &
11275 "1,0,operational,locked,on,rsl-up;" &
11276 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011277 "2,1,operational,unlocked,on,rsl-down;" &
11278 "2,2,operational,unlocked,on,rsl-down;" &
11279 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011280 "3,0,inoperational,locked,on,rsl-down;");
11281
11282 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
11283 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11284 f_sleep(1.0);
11285 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11286 "0,0,operational,unlocked,on,rsl-up;" &
11287 "1,0,operational,locked,on,rsl-up;" &
11288 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011289 "2,1,operational,unlocked,on,rsl-down;" &
11290 "2,2,operational,unlocked,on,rsl-down;" &
11291 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011292 "3,0,inoperational,locked,on,rsl-down;");
11293
11294 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
11295 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
11296 f_sleep(1.0);
11297 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11298 "0,0,operational,unlocked,on,rsl-up;" &
11299 "1,0,operational,unlocked,on,rsl-up;" &
11300 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011301 "2,1,operational,unlocked,on,rsl-down;" &
11302 "2,2,operational,unlocked,on,rsl-down;" &
11303 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011304 "3,0,inoperational,locked,on,rsl-down;");
11305
11306 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
11307 f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
11308 f_sleep(1.0);
11309 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11310 "0,0,operational,unlocked,on,rsl-up;" &
11311 "1,0,operational,unlocked,on,rsl-up;" &
11312 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011313 "2,1,operational,unlocked,on,rsl-down;" &
11314 "2,2,operational,unlocked,on,rsl-down;" &
11315 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011316 "3,0,inoperational,locked,on,rsl-down;");
11317
11318 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
11319 f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
11320 f_sleep(1.0);
11321 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11322 "0,0,operational,unlocked,on,rsl-up;" &
11323 "1,0,operational,unlocked,on,rsl-up;" &
11324 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011325 "2,1,operational,unlocked,on,rsl-down;" &
11326 "2,2,operational,unlocked,on,rsl-down;" &
11327 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011328 "3,0,inoperational,locked,on,rsl-down;");
11329
11330 f_shutdown_helper();
11331}
11332
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011333const CounterNameVals counternames_cm_serv_rej := {
11334 { "cm_serv_rej", 0 },
11335 { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
11336 { "cm_serv_rej:illegal_ms", 0 },
11337 { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
11338 { "cm_serv_rej:imei_not_accepted", 0 },
11339 { "cm_serv_rej:illegal_me", 0 },
11340 { "cm_serv_rej:plmn_not_allowed", 0 },
11341 { "cm_serv_rej:loc_not_allowed", 0 },
11342 { "cm_serv_rej:roaming_not_allowed", 0 },
11343 { "cm_serv_rej:network_failure", 0 },
11344 { "cm_serv_rej:synch_failure", 0 },
11345 { "cm_serv_rej:congestion", 0 },
11346 { "cm_serv_rej:srv_opt_not_supported", 0 },
11347 { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
11348 { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
11349 { "cm_serv_rej:call_can_not_be_identified", 0 },
11350 { "cm_serv_rej:incorrect_message", 0 },
11351 { "cm_serv_rej:invalid_mandantory_inf", 0 },
11352 { "cm_serv_rej:msg_type_not_implemented", 0 },
11353 { "cm_serv_rej:msg_type_not_compatible", 0 },
11354 { "cm_serv_rej:inf_eleme_not_implemented", 0 },
11355 { "cm_serv_rej:condtional_ie_error", 0 },
11356 { "cm_serv_rej:msg_not_compatible", 0 },
11357 { "cm_serv_rej:protocol_error", 0 },
11358 { "cm_serv_rej:retry_in_new_cell", 0 }
11359};
11360
11361private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
11362{
11363 f_create_chan_and_exp();
Vadim Yanitskiya7fc5a62021-12-04 20:10:08 +030011364 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011365 BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011366 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_CM_SERV_REJ));
11367 f_perform_clear();
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011368 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011369}
11370testcase TC_cm_serv_rej() runs on test_CT {
11371 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11372 var MSC_ConnHdlr vc_conn;
11373
11374 f_init(1, true);
11375 f_sleep(1.0);
11376
11377 f_ctrs_bts_init(1, counternames_cm_serv_rej);
11378
11379 vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
11380 vc_conn.done;
11381
11382 f_ctrs_bts_add(0, "cm_serv_rej", 1);
11383 f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
11384 f_ctrs_bts_verify();
11385
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011386 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011387 f_shutdown_helper();
11388}
11389
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011390/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
11391 * Activ Ack (SYS#5627). */
11392private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
11393 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Vadim Yanitskiyf0310e32021-10-26 00:30:59 +030011394
11395 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11396 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011397
11398 var BSSMAP_FIELD_CodecType codecType;
11399 codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
11400
11401 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
11402
11403 /* First establish a signalling lchan */
11404 f_create_chan_and_exp();
11405 f_rslem_dchan_queue_enable();
11406
11407 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011408
11409 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
Vadim Yanitskiy6be4cf42022-06-04 21:25:47 +060011410 activate(as_Media_mgw(fail_on_dlcx := false));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011411
11412 var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
11413 f_rslem_register(0, chan_nr);
11414
11415 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
11416 BSSAP.send(ass_cmd);
11417
11418
11419 /* Wait for the Channel Activ for the TCH channel */
11420 var ASP_RSL_Unitdata rx_rsl_ud;
11421 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
11422
11423 /* make the original SDCCH disappear */
11424 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
11425
11426 /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
11427 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
11428
11429 interleave {
11430 [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
11431 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
11432 }
11433
11434 BSSAP.send(ts_BSSMAP_ClearCommand(0));
11435 BSSAP.receive(tr_BSSMAP_ClearComplete);
11436 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11437
11438 var MgcpCommand mgcp;
Vadim Yanitskiy6be4cf42022-06-04 21:25:47 +060011439 var MGCP_RecvFrom mrf;
11440 var template MgcpMessage msg_dlcx := { command := tr_DLCX };
11441 alt {
11442 [g_pars.aoip] MGCP.receive(tr_DLCX) -> value mgcp {
11443 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
11444 }
11445 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
11446 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
11447 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
11448 }));
11449 }
11450 }
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011451
11452 f_sleep(0.5);
11453}
11454testcase TC_lost_sdcch_during_assignment() runs on test_CT {
11455 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11456 var MSC_ConnHdlr vc_conn;
11457
11458 f_init(1, true);
11459 f_sleep(1.0);
11460
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011461 vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
11462 vc_conn.done;
11463
11464 f_shutdown_helper();
11465}
11466
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011467const CounterNameVals counternames_bsc_bts_all_available_allocated := {
11468 { "all_allocated:sdcch", 0 },
11469 { "all_allocated:static_sdcch", 0 },
11470 { "all_allocated:tch", 0 },
11471 { "all_allocated:static_tch", 0 }
11472}
11473
11474private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
11475{
11476 /* Make sure counters settle first */
11477 f_sleep(1.0);
11478
11479 /* Take a baseline of counters */
11480 f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
11481
11482 /* Elapse some time so that we see changes in counters, hopefully where expected */
11483 f_sleep(2.0);
11484
11485 /* Get new counters */
11486 var charstring_list all_changed := {};
11487 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
11488 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
11489
11490 /* Compare with expectations */
11491 var charstring_list all_expect_changed := {};
11492 for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
11493 all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
11494 }
11495 f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
11496}
11497
11498testcase TC_ratectr_all_available_allocated() runs on test_CT {
11499 var ASP_RSL_Unitdata rsl_ud;
11500 var integer i;
11501 var integer chreq_total, chreq_nochan;
11502
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011503 f_init(1, guard_timeout := 60.0);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011504 f_sleep(1.0);
11505
11506 /* Exhaust all dedicated SDCCH lchans.
11507 /* GSM 44.018 Table 9.1.8.2:
11508 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11509 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011510 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011511 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011512 chan_cleanup := chan_cleanup & { f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011513 }
11514
11515 /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
11516 * level.
11517 * All SDCCH are now occupied. */
11518 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11519
11520 /* Also fill up all remaining (TCH) channels */
11521 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011522 chan_cleanup := chan_cleanup & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011523 }
11524
11525 /* All TCH are now also occupied */
11526 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11527 "all_allocated:tch", "all_allocated:static_tch"});
11528
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011529 /* Clean up SDCCH lchans */
11530 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11531 f_perform_clear_test_ct(chan_cleanup[i]);
11532 }
11533
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011534 f_shutdown_helper();
11535}
11536
11537testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
11538 var ASP_RSL_Unitdata rsl_ud;
11539 var integer i;
11540 var integer chreq_total, chreq_nochan;
11541
11542 f_init_vty();
11543 f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
11544 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11545 /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
11546
11547 f_init(1, guard_timeout := 60.0);
11548 f_sleep(1.0);
11549
11550 /* The dyn TS wants to activate PDCH mode, ACK that. */
11551 var RslChannelNr chan_nr;
11552 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011553 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11554 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011555
11556 /* Exhaust all dedicated SDCCH lchans.
11557 /* GSM 44.018 Table 9.1.8.2:
11558 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11559 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011560 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011561 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011562 chan_cleanup := chan_cleanup & { f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011563 }
11564
11565 /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
11566 * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
11567 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
11568
11569 /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
11570 * Will release them later, so remember all the DchanTuples. */
11571 var DchanTuples dyn_sddch := {};
11572 dyn_sddch := dyn_sddch & { f_est_dchan_dyn('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
11573
11574 /* Also occupy the seven other SDCCH of the dyn TS */
11575 for (i := 0; i < 7; i := i+1) {
11576 dyn_sddch := dyn_sddch & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
11577 }
11578
11579 /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
11580 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11581
11582 /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
11583 for (i := 0; i < 5; i := i+1) {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011584 chan_cleanup := chan_cleanup & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011585 }
11586
11587 /* All TCH lchans are now also occupied, both static and dynamic */
11588 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11589 "all_allocated:tch", "all_allocated:static_tch"});
11590
11591 /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
11592 * incrementing. */
11593 var BssmapCause cause := 0;
11594 var DchanTuple dt := dyn_sddch[0];
11595 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011596 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011597
11598 /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
11599 * count as occupied, so those still both increment. */
11600 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
11601 "all_allocated:tch", "all_allocated:static_tch"});
11602
11603 /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
11604 for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
11605 dt := dyn_sddch[i];
11606 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011607 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011608 }
11609
11610 /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
11611 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011612 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11613 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011614
11615 /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
11616 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
11617
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011618 /* Clean up SDCCH lchans */
11619 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11620 f_perform_clear_test_ct(chan_cleanup[i]);
11621 }
11622
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011623 /* clean up config */
11624 f_ts_reset_chcomb(0);
11625
11626 f_shutdown_helper();
11627}
11628
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011629private function f_TC_chan_alloc_algo(DchanTuple dt, BtsTrxIdx idx)
11630runs on test_CT {
11631 /* MSC sends an Assignment Request */
11632 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11633 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11634 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11635 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
11636
11637 /* Expect the BSC to allocate a TCH channel on the given BTS/TRX */
11638 var RSL_Message rsl_chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
11639 /* Send CHAN ACT NACK, so that the requested TCH channel becomes BORKEN */
11640 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(rsl_chan_act.ies[0].body.chan_nr, RSL_ERR_EQUIPMENT_FAIL), idx);
11641 /* Expect to receive an Assignment Failure */
11642 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail));
11643}
11644
11645testcase TC_chan_alloc_algo_ascending() runs on test_CT {
11646 /* We need to access BTS2, which has 4 TRXs */
11647 f_init(nr_bts := 3);
11648
11649 /* HACK: work around "Couldn't find Expect for CRCX" */
11650 vc_MGCP.stop;
11651
11652 f_vty_enter_cfg_bts(BSCVTY, 2);
11653 f_vty_transceive(BSCVTY, "channel allocator ascending");
11654 f_vty_transceive(BSCVTY, "end");
11655
11656 /* Expect the BSC to allocate 4 x TCH/F channels on BTS2/TRX0 */
11657 for (var integer i := 0; i < 4; i := i + 1) {
11658 var DchanTuple dt := f_est_dchan('23'O, 23, '00000000'O, {2, 0});
11659 f_TC_chan_alloc_algo(dt, {2, 0});
11660 f_perform_clear_test_ct(dt);
11661 }
11662
11663 /* At this point all 4 x TCH/F channels are BORKEN, but they will be
11664 * resurrected upon the A-bis/OML link re-establishment. */
11665 f_shutdown_helper();
11666}
11667
11668testcase TC_chan_alloc_algo_descending() runs on test_CT {
11669 /* We need to access BTS2, which has 4 TRXs */
11670 f_init(nr_bts := 3);
11671
11672 /* HACK: work around "Couldn't find Expect for CRCX" */
11673 vc_MGCP.stop;
11674
11675 f_vty_enter_cfg_bts(BSCVTY, 2);
11676 f_vty_transceive(BSCVTY, "channel allocator descending");
11677 f_vty_transceive(BSCVTY, "end");
11678
11679 /* Expect the BSC to allocate 5 x TCH/F channels on BTS2/TRX3 */
11680 for (var integer i := 0; i < 5; i := i + 1) {
11681 var DchanTuple dt := f_est_dchan('23'O, 23, '00000000'O, {2, 0});
11682 f_TC_chan_alloc_algo(dt, {2, 3});
11683 f_perform_clear_test_ct(dt);
11684 }
11685
11686 /* At this point all 5 x TCH/F channels are BORKEN, but they will be
11687 * resurrected upon the A-bis/OML link re-establishment. */
11688 f_shutdown_helper();
11689}
11690
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011691testcase TC_chan_alloc_algo_ass_dynamic() runs on test_CT {
11692 const BtsTrxIdx TRX0 := {2, 0};
11693 const BtsTrxIdx TRX3 := {2, 3};
11694
11695 /* We need to access BTS2, which has 4 TRXs */
11696 f_init(nr_bts := 3);
11697
11698 /* HACK: work around "Couldn't find Expect for CRCX" */
11699 vc_MGCP.stop;
11700
11701 f_vty_enter_cfg_bts(BSCVTY, 2);
11702 f_vty_transceive(BSCVTY, "channel allocator mode assignment dynamic");
11703 f_vty_transceive(BSCVTY, "channel allocator dynamic-param ul-rxlev thresh 50 avg-num 2");
11704 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 0");
11705 f_vty_transceive(BSCVTY, "end");
11706
11707 var DchanTuple dt;
11708
11709 f_logp(BSCVTY, "Case a) Unknown Uplink RxLev, fall-back to ascending");
11710 dt := f_est_dchan('23'O, 23, '00000000'O, TRX0);
11711 f_TC_chan_alloc_algo(dt, TRX0);
11712 f_perform_clear_test_ct(dt);
11713
11714 f_logp(BSCVTY, "Case b) Not enough RxLev samples, use ascending");
11715 dt := f_est_dchan('23'O, 23, '00000000'O, TRX0);
11716 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11717 ts_RSL_IE_UplinkMeas(30, 0),
11718 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011719 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011720 f_TC_chan_alloc_algo(dt, TRX0);
11721 f_perform_clear_test_ct(dt);
11722
11723 f_logp(BSCVTY, "Case c) Uplink RxLev below the threshold, use ascending");
11724 dt := f_est_dchan('23'O, 23, '00000000'O, TRX0);
11725 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11726 ts_RSL_IE_UplinkMeas(45, 0),
11727 ts_RSL_IE_BS_Power(0)), TRX0);
11728 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
11729 ts_RSL_IE_UplinkMeas(48, 0),
11730 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011731 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011732 f_TC_chan_alloc_algo(dt, TRX0);
11733 f_perform_clear_test_ct(dt);
11734
11735 f_logp(BSCVTY, "Case d) Uplink RxLev above the threshold, use descending");
11736 dt := f_est_dchan('23'O, 23, '00000000'O, TRX0);
11737 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11738 ts_RSL_IE_UplinkMeas(50, 0),
11739 ts_RSL_IE_BS_Power(0)), TRX0);
11740 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
11741 ts_RSL_IE_UplinkMeas(58, 0),
11742 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011743 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011744 f_TC_chan_alloc_algo(dt, TRX3);
11745 f_perform_clear_test_ct(dt);
11746
11747 f_vty_enter_cfg_bts(BSCVTY, 2);
11748 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 90");
11749 f_vty_transceive(BSCVTY, "end");
11750
11751 f_logp(BSCVTY, "Case e) Uplink RxLev above the threshold, but C0 load is not");
11752 dt := f_est_dchan('23'O, 23, '00000000'O, TRX0);
11753 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11754 ts_RSL_IE_UplinkMeas(50, 0),
11755 ts_RSL_IE_BS_Power(0)), TRX0);
11756 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
11757 ts_RSL_IE_UplinkMeas(58, 0),
11758 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011759 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011760 f_TC_chan_alloc_algo(dt, TRX0);
11761 f_perform_clear_test_ct(dt);
11762
11763 f_vty_enter_cfg_bts(BSCVTY, 2);
11764 f_vty_transceive(BSCVTY, "channel allocator ascending");
11765 f_vty_transceive(BSCVTY, "end");
11766
11767 /* At this point some TCH/F channels are BORKEN, but they will be
11768 * resurrected upon the A-bis/OML link re-establishment. */
11769 f_shutdown_helper();
11770}
11771
Harald Welte28d943e2017-11-25 15:00:50 +010011772control {
Harald Welte898113b2018-01-31 18:32:21 +010011773 /* CTRL interface testing */
Harald Welte4003d112017-12-09 22:35:39 +010011774 execute( TC_ctrl_msc_connection_status() );
Stefan Sperlingb041b3d2018-01-03 17:14:55 +010011775 execute( TC_ctrl_msc0_connection_status() );
Neels Hofmeyrf65ce872021-09-23 18:40:10 +020011776 /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
11777 * these in the AoIP test suite. */
11778 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
11779 execute( TC_stat_num_msc_connected_1() );
11780 execute( TC_stat_num_msc_connected_2() );
11781 execute( TC_stat_num_msc_connected_3() );
11782 }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020011783 execute( TC_stat_num_bts_connected_1() );
11784 execute( TC_stat_num_bts_connected_2() );
11785 execute( TC_stat_num_bts_connected_3() );
Harald Welte96c94412017-12-09 03:12:45 +010011786 execute( TC_ctrl() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020011787 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +020011788 execute( TC_ctrl_location() );
11789 }
Harald Welte898113b2018-01-31 18:32:21 +010011790
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020011791 execute( TC_si_default() );
Neels Hofmeyr66aeba42020-07-06 02:21:21 +020011792 execute( TC_si2quater_2_earfcns() );
11793 execute( TC_si2quater_3_earfcns() );
11794 execute( TC_si2quater_4_earfcns() );
11795 execute( TC_si2quater_5_earfcns() );
11796 execute( TC_si2quater_6_earfcns() );
Neels Hofmeyrad132f22020-07-08 02:20:16 +020011797 execute( TC_si2quater_12_earfcns() );
11798 execute( TC_si2quater_23_earfcns() );
11799 execute( TC_si2quater_32_earfcns() );
11800 execute( TC_si2quater_33_earfcns() );
11801 execute( TC_si2quater_42_earfcns() );
11802 execute( TC_si2quater_48_earfcns() );
11803 execute( TC_si2quater_49_earfcns() );
Pau Espin Pedrol85a84432020-07-20 18:45:03 +020011804 execute( TC_si_acc_rotate() );
Alexander Couzens4ad3a352020-09-10 22:29:12 +020011805 execute( TC_si_acc_ramp_rotate() );
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020011806
Harald Welte898113b2018-01-31 18:32:21 +010011807 /* RSL DCHAN Channel ACtivation / Deactivation */
Harald Welteae026692017-12-09 01:03:01 +010011808 execute( TC_chan_act_noreply() );
Harald Welte4003d112017-12-09 22:35:39 +010011809 execute( TC_chan_act_counter() );
Harald Welteae026692017-12-09 01:03:01 +010011810 execute( TC_chan_act_ack_noest() );
Philipp Maier9c60a622020-07-09 15:08:46 +020011811 execute( TC_chan_act_ack_noest_emerg() );
Philipp Maier606f07d2020-08-12 17:21:58 +020011812 execute( TC_chan_rqd_emerg_deny() );
Harald Welteae026692017-12-09 01:03:01 +010011813 execute( TC_chan_act_ack_est_ind_noreply() );
11814 execute( TC_chan_act_ack_est_ind_refused() );
Harald Welte618ef642017-12-14 14:58:20 +010011815 execute( TC_chan_act_nack() );
Harald Welte799c97b2017-12-14 17:50:30 +010011816 execute( TC_chan_exhaustion() );
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +070011817 execute( TC_chan_deact_silence() );
Harald Welte4003d112017-12-09 22:35:39 +010011818 execute( TC_chan_rel_rll_rel_ind() );
11819 execute( TC_chan_rel_conn_fail() );
11820 execute( TC_chan_rel_hard_clear() );
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +020011821 execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
11822 execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
Harald Welte99787102019-02-04 10:41:36 +010011823 execute( TC_chan_rel_hard_clear_csfb() );
Harald Welted8c36cd2017-12-09 23:05:31 +010011824 execute( TC_chan_rel_hard_rlsd() );
Harald Welte550daf92018-06-11 19:22:13 +020011825 execute( TC_chan_rel_hard_rlsd_ms_dead() );
Harald Welte85804d42017-12-10 14:11:58 +010011826 execute( TC_chan_rel_a_reset() );
Pau Espin Pedrolc675b612020-01-09 19:55:40 +010011827 execute( TC_chan_rel_sccp_tiar_timeout() );
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +020011828 execute( TC_chan_rel_rr_cause() );
Harald Welte6f521d82017-12-11 19:52:02 +010011829
Harald Weltecfe2c962017-12-15 12:09:32 +010011830 execute( TC_outbound_connect() );
Harald Welte898113b2018-01-31 18:32:21 +010011831
11832 /* Assignment related */
Harald Welte16a4adf2017-12-14 18:54:01 +010011833 execute( TC_assignment_cic_only() );
Harald Welte235ebf12017-12-15 14:18:16 +010011834 execute( TC_assignment_csd() );
11835 execute( TC_assignment_ctm() );
11836 execute( TC_assignment_sign() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020011837 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
11838 execute( TC_assignment_aoip_tla_v6() );
11839 }
Harald Welte235ebf12017-12-15 14:18:16 +010011840 execute( TC_assignment_fr_a5_0() );
11841 execute( TC_assignment_fr_a5_1() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020011842 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte8f67d1d2018-05-25 20:38:42 +020011843 execute( TC_assignment_fr_a5_1_codec_missing() );
11844 }
Harald Welte235ebf12017-12-15 14:18:16 +010011845 execute( TC_assignment_fr_a5_3() );
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +020011846 execute( TC_assignment_fr_a5_4() );
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +020011847 execute( TC_assignment_fr_a5_4_fail() );
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +020011848 execute( TC_assignment_fr_a5_not_sup() );
Harald Welte3c86ea02018-05-10 22:28:05 +020011849 execute( TC_ciph_mode_a5_0() );
11850 execute( TC_ciph_mode_a5_1() );
Oliver Smith50b98122021-07-09 15:00:28 +020011851 execute( TC_ciph_mode_a5_2_0() );
Oliver Smith1dff88d2021-07-09 08:45:51 +020011852 execute( TC_ciph_mode_a5_2_1() );
Harald Welte3c86ea02018-05-10 22:28:05 +020011853 execute( TC_ciph_mode_a5_3() );
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +020011854 execute( TC_ciph_mode_a5_4() );
Harald Welte16a4adf2017-12-14 18:54:01 +010011855
Harald Welte60aa5762018-03-21 19:33:13 +010011856 execute( TC_assignment_codec_fr() );
Neels Hofmeyr559d5d02021-04-16 16:50:49 +020011857 execute( TC_assignment_codec_fr_by_mode_modify() );
Harald Welte60aa5762018-03-21 19:33:13 +010011858 execute( TC_assignment_codec_hr() );
11859 execute( TC_assignment_codec_efr() );
11860 execute( TC_assignment_codec_amr_f() );
11861 execute( TC_assignment_codec_amr_h() );
Philipp Maier8a581d22019-03-26 18:32:48 +010011862
Neels Hofmeyrf246a922020-05-13 02:27:10 +020011863 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier8a581d22019-03-26 18:32:48 +010011864 execute( TC_assignment_codec_amr_f_S1() );
11865 execute( TC_assignment_codec_amr_h_S1() );
11866 execute( TC_assignment_codec_amr_f_S124() );
11867 execute( TC_assignment_codec_amr_h_S124() );
11868 execute( TC_assignment_codec_amr_f_S0() );
11869 execute( TC_assignment_codec_amr_f_S02() );
11870 execute( TC_assignment_codec_amr_f_S024() );
11871 execute( TC_assignment_codec_amr_f_S0247() );
11872 execute( TC_assignment_codec_amr_h_S0() );
11873 execute( TC_assignment_codec_amr_h_S02() );
11874 execute( TC_assignment_codec_amr_h_S024() );
11875 execute( TC_assignment_codec_amr_h_S0247() );
11876 execute( TC_assignment_codec_amr_f_S01234567() );
11877 execute( TC_assignment_codec_amr_f_S0234567() );
11878 execute( TC_assignment_codec_amr_f_zero() );
11879 execute( TC_assignment_codec_amr_f_unsupp() );
11880 execute( TC_assignment_codec_amr_h_S7() );
Neels Hofmeyr21863562020-11-26 00:34:33 +000011881 execute( TC_assignment_codec_amr_f_start_mode_auto() );
11882 execute( TC_assignment_codec_amr_h_start_mode_auto() );
Neels Hofmeyr3eb94562020-11-26 02:40:26 +000011883 execute( TC_assignment_codec_amr_f_start_mode_4() );
11884 execute( TC_assignment_codec_amr_h_start_mode_4() );
Neels Hofmeyr454d7922020-11-26 02:24:57 +000011885 execute( TC_assignment_codec_amr_startmode_cruft() );
Philipp Maier8a581d22019-03-26 18:32:48 +010011886 }
Harald Welte60aa5762018-03-21 19:33:13 +010011887
Philipp Maierac09bfc2019-01-08 13:41:39 +010011888 execute( TC_assignment_codec_fr_exhausted_req_hr() );
11889 execute( TC_assignment_codec_fr_exhausted_req_fr() );
11890 execute( TC_assignment_codec_fr_exhausted_req_fr_hr() );
11891 execute( TC_assignment_codec_fr_exhausted_req_hr_fr() );
11892 execute( TC_assignment_codec_hr_exhausted_req_fr() );
11893 execute( TC_assignment_codec_hr_exhausted_req_hr() );
11894 execute( TC_assignment_codec_hr_exhausted_req_hr_fr() );
11895 execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
11896 execute( TC_assignment_codec_req_hr_fr() );
11897 execute( TC_assignment_codec_req_fr_hr() );
Pau Espin Pedrol14475352021-07-22 15:48:16 +020011898 execute( TC_assignment_sdcch_exhausted_req_signalling() );
11899 execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
11900 execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
Philipp Maierac09bfc2019-01-08 13:41:39 +010011901
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +020011902 execute( TC_assignment_osmux() );
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020011903 execute( TC_assignment_osmux_cn() );
11904 execute( TC_assignment_osmux_bts() );
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +020011905
Harald Welte898113b2018-01-31 18:32:21 +010011906 /* RLL Establish Indication on inactive DCHAN / SAPI */
Harald Welte5cd20ed2017-12-13 21:03:20 +010011907 execute( TC_rll_est_ind_inact_lchan() );
11908 execute( TC_rll_est_ind_inval_sapi1() );
11909 execute( TC_rll_est_ind_inval_sapi3() );
11910 execute( TC_rll_est_ind_inval_sacch() );
11911
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +070011912 /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
11913 execute( TC_tch_dlci_link_id_sapi() );
11914
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070011915 /* SAPI N Reject triggered by RLL establishment failures */
11916 execute( TC_rll_rel_ind_sapi_n_reject() );
11917 execute( TC_rll_err_ind_sapi_n_reject() );
11918 execute( TC_rll_timeout_sapi_n_reject() );
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +070011919 execute( TC_rll_sapi_n_reject_dlci_cc() );
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070011920
Harald Welte898113b2018-01-31 18:32:21 +010011921 /* Paging related tests */
Harald Welte6f521d82017-12-11 19:52:02 +010011922 execute( TC_paging_imsi_nochan() );
11923 execute( TC_paging_tmsi_nochan() );
11924 execute( TC_paging_tmsi_any() );
11925 execute( TC_paging_tmsi_sdcch() );
11926 execute( TC_paging_tmsi_tch_f() );
11927 execute( TC_paging_tmsi_tch_hf() );
11928 execute( TC_paging_imsi_nochan_cgi() );
11929 execute( TC_paging_imsi_nochan_lac_ci() );
11930 execute( TC_paging_imsi_nochan_ci() );
11931 execute( TC_paging_imsi_nochan_lai() );
11932 execute( TC_paging_imsi_nochan_lac() );
11933 execute( TC_paging_imsi_nochan_all() );
Harald Welte751d3eb2018-01-31 15:51:06 +010011934 execute( TC_paging_imsi_nochan_plmn_lac_rnc() );
11935 execute( TC_paging_imsi_nochan_rnc() );
11936 execute( TC_paging_imsi_nochan_lac_rnc() );
11937 execute( TC_paging_imsi_nochan_lacs() );
11938 execute( TC_paging_imsi_nochan_lacs_empty() );
Stefan Sperling049a86e2018-03-20 15:51:00 +010011939 execute( TC_paging_imsi_nochan_cgi_unknown_cid() );
Harald Welte10985002017-12-12 09:29:15 +010011940 execute( TC_paging_imsi_a_reset() );
Harald Weltee65d40e2017-12-13 00:09:06 +010011941 execute( TC_paging_imsi_load() );
Philipp Maier779a7922018-02-16 11:00:37 +010011942 execute( TC_paging_counter() );
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +010011943 execute( TC_paging_resp_unsol() );
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +020011944 execute( TC_paging_500req() );
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +020011945 execute( TC_paging_450req_no_paging_load_ind() );
Harald Welte4e9b9cc2017-12-14 18:31:02 +010011946
11947 execute( TC_rsl_drop_counter() );
Stefan Sperling830dc9d2018-02-12 21:08:28 +010011948 execute( TC_rsl_unknown_unit_id() );
11949
11950 execute( TC_oml_unknown_unit_id() );
Harald Welte898113b2018-01-31 18:32:21 +010011951
11952 execute( TC_classmark() );
Harald Welteeddf0e92020-06-21 19:42:15 +020011953 execute( TC_common_id() );
Harald Welte898113b2018-01-31 18:32:21 +010011954 execute( TC_unsol_ass_fail() );
Harald Welteea99a002018-01-31 20:46:43 +010011955 execute( TC_unsol_ass_compl() );
Harald Weltefbf9b5e2018-01-31 20:41:23 +010011956 execute( TC_unsol_ho_fail() );
Harald Weltee3bd6582018-01-31 22:51:25 +010011957 execute( TC_err_82_short_msg() );
Harald Weltee9e02e42018-01-31 23:36:25 +010011958 execute( TC_err_84_unknown_msg() );
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010011959
Harald Welte261af4b2018-02-12 21:20:39 +010011960 execute( TC_ho_int() );
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +020011961 execute( TC_ho_int_a5_0() );
11962 execute( TC_ho_int_a5_1() );
11963 execute( TC_ho_int_a5_3() );
11964 execute( TC_ho_int_a5_4() );
Neels Hofmeyr5f144212020-11-03 15:41:58 +000011965 execute( TC_ho_int_radio_link_failure() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010011966
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010011967 /* TC_ho_out_of_this_bsc is run last, see comment below */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +020011968 execute( TC_ho_out_fail_no_msc_response() );
11969 execute( TC_ho_out_fail_rr_ho_failure() );
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +020011970 execute( TC_ho_out_fail_no_result_after_ho_cmd() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010011971
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010011972 execute( TC_ho_into_this_bsc() );
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +020011973 execute( TC_ho_into_this_bsc_a5_0() );
11974 execute( TC_ho_into_this_bsc_a5_1() );
11975 execute( TC_ho_into_this_bsc_a5_3() );
11976 execute( TC_ho_into_this_bsc_a5_4() );
Neels Hofmeyr93182e02022-02-17 21:59:07 +010011977 execute( TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() );
11978 execute( TC_ho_into_this_bsc_a5_1_3() );
Neels Hofmeyr907b23b2022-02-17 21:58:47 +010011979 execute( TC_ho_into_this_bsc_a5_mismatch() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020011980 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
11981 execute( TC_ho_into_this_bsc_tla_v6() );
11982 }
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +020011983 execute( TC_srvcc_eutran_to_geran() );
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +030011984 execute( TC_srvcc_eutran_to_geran_a5_3() );
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +010011985 execute( TC_srvcc_eutran_to_geran_src_sai() );
Pau Espin Pedrol35801c32021-04-19 13:03:20 +020011986 execute( TC_srvcc_eutran_to_geran_ho_out() );
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +020011987 execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
11988 execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010011989 execute( TC_ho_in_fail_msc_clears() );
11990 execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
11991 execute( TC_ho_in_fail_no_detect() );
11992 execute( TC_ho_in_fail_no_detect2() );
Neels Hofmeyra23f3b12022-03-02 19:57:12 +010011993 execute( TC_ho_into_this_bsc_sccp_cr_without_bssap() );
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010011994
Neels Hofmeyr91401012019-07-11 00:42:35 +020011995 execute( TC_ho_neighbor_config_1() );
11996 execute( TC_ho_neighbor_config_2() );
11997 execute( TC_ho_neighbor_config_3() );
11998 execute( TC_ho_neighbor_config_4() );
11999 execute( TC_ho_neighbor_config_5() );
12000 execute( TC_ho_neighbor_config_6() );
12001 execute( TC_ho_neighbor_config_7() );
12002
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012003 execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() );
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010012004 execute( TC_bssmap_clear_does_not_cause_bssmap_reset() );
Neels Hofmeyrfd445c32018-03-09 15:39:31 +010012005 execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() );
Harald Welte94e0c342018-04-07 11:33:23 +020012006
12007 execute( TC_dyn_pdch_ipa_act_deact() );
12008 execute( TC_dyn_pdch_ipa_act_nack() );
12009 execute( TC_dyn_pdch_osmo_act_deact() );
12010 execute( TC_dyn_pdch_osmo_act_nack() );
Pau Espin Pedrol37a4c152021-11-16 19:02:23 +010012011 execute( TC_dyn_ts_sdcch8_act_deact() );
12012 execute( TC_dyn_ts_sdcch8_all_subslots_used() );
12013 execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
12014 execute( TC_dyn_ts_sdcch8_act_nack() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012015
Stefan Sperling0796a822018-10-05 13:01:39 +020012016 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +020012017 execute( TC_chopped_ipa_payload() );
Stefan Sperling0796a822018-10-05 13:01:39 +020012018
Pau Espin Pedrol8f773632019-11-05 11:46:53 +010012019 /* Power control related */
12020 execute( TC_assignment_verify_ms_power_params_ie() );
Vadim Yanitskiy4b233042021-06-30 00:58:43 +020012021 execute( TC_c0_power_red_mode() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012022
12023 /* MSC pooling */
12024 /* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
12025 * RESET->RESET-ACK is unconditionally negotiated for all configured MSCs, they always all appear as connected
12026 * to osmo-bsc. The MSC pooling tests however require disconnecting selected MSCs, and hence don't work out as
12027 * intended on SCCPlite. So for now, run these only for SCCP/M3UA. */
12028 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12029 execute( TC_mscpool_L3Compl_on_1_msc() );
12030 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
12031 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
12032 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
12033 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
12034 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
12035 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
12036 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
12037 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
12038 execute( TC_mscpool_paging_and_response_imsi() );
12039 execute( TC_mscpool_paging_and_response_tmsi() );
12040 execute( TC_mscpool_no_allow_attach_round_robin() );
12041 execute( TC_mscpool_no_allow_attach_valid_nri() );
12042 }
12043
Harald Welte99f3ca02018-06-14 13:40:29 +020012044 execute( TC_early_conn_fail() );
12045 execute( TC_late_conn_fail() );
Oliver Smithaf03bef2021-08-24 15:34:51 +020012046 execute( TC_stats_conn_fail() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012047
Philipp Maier783681c2020-07-16 16:47:06 +020012048 /* Emergency call handling (deny / allow) */
12049 execute( TC_assignment_emerg_setup_allow() );
12050 execute( TC_assignment_emerg_setup_deny_msc() );
12051 execute( TC_assignment_emerg_setup_deny_bts() );
Philipp Maier82812002020-08-13 18:48:27 +020012052 execute( TC_emerg_premption() );
12053
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +070012054 /* Frequency hopping parameters handling */
12055 execute( TC_fh_params_chan_activ() );
12056 execute( TC_fh_params_imm_ass() );
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070012057 execute( TC_fh_params_assignment_cmd() );
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070012058 execute( TC_fh_params_handover_cmd() );
Vadim Yanitskiyca974032020-09-01 07:20:39 +070012059 execute( TC_fh_params_si4_cbch() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012060
12061 if (mp_enable_lcs_tests) {
12062 execute( TC_lcs_loc_req_for_active_ms() );
12063 execute( TC_lcs_loc_req_for_active_ms_ta_req() );
12064 execute( TC_lcs_loc_req_for_idle_ms() );
12065 execute( TC_lcs_loc_req_no_subscriber() );
12066 execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
12067 execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
12068 execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
12069 execute( TC_cm_service_during_lcs_loc_req() );
12070 execute( TC_ho_during_lcs_loc_req() );
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020012071 execute( TC_emerg_call_and_lcs_loc_req() );
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020012072 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() );
12073 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012074 }
Neels Hofmeyrbf037052020-10-28 22:52:02 +000012075
12076 execute( TC_no_msc() );
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000012077
12078 execute( TC_refuse_chan_act_to_vamos() );
12079 execute( TC_refuse_mode_modif_to_vamos() );
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000012080
12081 execute( TC_reassignment_fr() );
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020012082
12083 execute( TC_cm_reestablishment() );
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020012084
12085 execute( TC_imm_ass_post_chan_ack() );
12086 execute( TC_imm_ass_pre_chan_ack() );
Neels Hofmeyr23158742021-09-07 19:08:07 +020012087 execute( TC_imm_ass_pre_ts_ack() );
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020012088 execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020012089 execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020012090
12091 execute( TC_ctrl_trx_rf_locked() );
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012092
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012093 execute( TC_ratectr_all_available_allocated() );
12094 execute( TC_ratectr_all_available_allocated_dyn() );
12095
Neels Hofmeyrb7581872021-11-07 14:02:49 +010012096 execute( TC_cm_serv_rej() );
12097
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012098 execute( TC_lost_sdcch_during_assignment() );
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012099
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012100 /* Channel allocator */
12101 execute( TC_chan_alloc_algo_ascending() );
12102 execute( TC_chan_alloc_algo_descending() );
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012103 execute( TC_chan_alloc_algo_ass_dynamic() );
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012104
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012105 /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
12106 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
12107 execute( TC_ho_out_of_this_bsc() );
Harald Welte28d943e2017-11-25 15:00:50 +010012108}
12109
12110}