blob: a1503101fed8e05b3e8b8e56a6db8106c3420317 [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
Vadim Yanitskiy59494702022-09-14 15:29:04 +0700114private const RSL_IE_Body c_mr_conf_5_90 :=
Pau Espin Pedrolf7634dc2022-09-02 17:56:00 +0200115 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: */
Vadim Yanitskiy4d852082022-09-14 14:07:20 +07001276 if (Misc_Helpers.f_osmo_repo_is("nightly")) {
1277 f_vty_enter_cfg_bts(BSCVTY, bts_idx);
1278 if (g_osmux_enabled_bts) {
1279 f_vty_transceive(BSCVTY, "osmux on");
1280 } else {
1281 f_vty_transceive(BSCVTY, "osmux off");
1282 }
1283 f_vty_transceive(BSCVTY, "end");
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001284 }
Harald Welte28d943e2017-11-25 15:00:50 +01001285}
1286
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001287function f_init_bts_and_check_sysinfo(integer bts_idx := 0,
1288 integer trx_num := NUM_TRX_CFG,
1289 boolean handler_mode := false,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001290 template SystemInformationConfig expect_si)
1291runs on test_CT {
1292 var default sysinfo := activate(as_catch_RSL_sysinfo(bts_idx));
1293
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001294 f_init_bts(bts_idx, trx_num, handler_mode);
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001295
1296 /* Give some time to (hopefully/most likely) collect all system informations from RSL startup.
1297 * We could stop as soon as all expected SI are received, but then we might miss SI that we don't expect and
1298 * that might be sent afterwards. So rather give a generous timeout and be quite sure to catch all SI.
1299 */
1300 f_sleep(5.0);
1301 log("RSL ", bts_idx, " SYSTEM INFORMATION: ", g_system_information[bts_idx]);
1302
1303 deactivate(sysinfo);
1304
1305 if (match(g_system_information[bts_idx], expect_si)) {
1306 setverdict(pass);
1307 } else {
1308 log("RSL ", bts_idx, ": EXPECTED SI: ", expect_si);
1309 log("RSL ", bts_idx, ": GOT SI: ", g_system_information[bts_idx]);
1310 setverdict(fail, "received SI does not match expectations");
1311 return;
1312 }
1313}
1314
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001315/* expect to receive a RSL message matching a specified template on a given BTS / TRX */
1316function f_exp_ipa_rx(template (present) RSL_Message t_rx,
1317 BtsTrxIdx idx := {0, 0},
1318 float Tval := 2.0)
Harald Welteae026692017-12-09 01:03:01 +01001319runs on test_CT return RSL_Message {
1320 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001321 timer T := Tval;
Harald Welteae026692017-12-09 01:03:01 +01001322
1323 T.start;
1324 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001325 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Harald Welteae026692017-12-09 01:03:01 +01001326 T.stop;
1327 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001328 [] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
Harald Welteb2917702017-12-10 15:48:52 +01001329 [] T.timeout {
1330 setverdict(fail, "Timeout expecting ", t_rx);
Daniel Willmannafce8662018-07-06 23:11:32 +02001331 mtc.stop;
Harald Welteb2917702017-12-10 15:48:52 +01001332 }
Harald Welteae026692017-12-09 01:03:01 +01001333 }
1334 return rx_rsl_ud.rsl;
1335}
1336
Harald Welte21b46bd2017-12-17 19:46:32 +01001337/* helper function to transmit RSL on a given BTS/stream */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001338function f_ipa_tx(template (value) RSL_Message t_tx,
1339 BtsTrxIdx idx := {0, 0},
1340 IpaStreamId sid := IPAC_PROTO_RSL_TRX0)
Harald Welteae026692017-12-09 01:03:01 +01001341runs on test_CT {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001342 IPA_RSL[idx.bts][idx.trx].send(ts_ASP_RSL_UD(t_tx, sid));
Harald Welteae026692017-12-09 01:03:01 +01001343}
1344
1345
Harald Welte4003d112017-12-09 22:35:39 +01001346/* verify we get a CHAN_ACT after CHAN RQD */
Harald Welteae026692017-12-09 01:03:01 +01001347testcase TC_chan_act_noreply() runs on test_CT {
1348 var BSSAP_N_UNITDATA_ind ud_ind;
Harald Welte930d0a72018-03-22 22:08:40 +01001349 var RSL_Message rsl_unused;
Harald Welte28d943e2017-11-25 15:00:50 +01001350
Harald Welte89d42e82017-12-17 16:42:41 +01001351 f_init(1);
Harald Welte28d943e2017-11-25 15:00:50 +01001352
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001353 f_ipa_tx(ts_RSL_CHAN_RQD('23'O, 23));
1354 rsl_unused := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001355 f_shutdown_helper();
Harald Welte28d943e2017-11-25 15:00:50 +01001356}
1357
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001358const CounterNameVals counternames_bts_chreq := {
1359 { "chreq:total", 0 },
1360 { "chreq:attempted_emerg", 0 },
1361 { "chreq:attempted_call", 0 },
1362 { "chreq:attempted_location_upd", 0 },
1363 { "chreq:attempted_pag", 0 },
1364 { "chreq:attempted_pdch", 0 },
1365 { "chreq:attempted_other", 0 },
1366 { "chreq:attempted_unknown", 0 },
1367 { "chreq:successful", 0 },
1368 { "chreq:successful_emerg", 0 },
1369 { "chreq:successful_call", 0 },
1370 { "chreq:successful_location_upd", 0 },
1371 { "chreq:successful_pag", 0 },
1372 { "chreq:successful_pdch", 0 },
1373 { "chreq:successful_other", 0 },
1374 { "chreq:successful_unknown", 0 },
1375 { "chreq:no_channel", 0 },
1376 { "chreq:max_delay_exceeded", 0 }
1377};
1378
1379/* verify the "chreq:*" counters */
1380private function f_chan_act_counter(OCT1 ra, charstring chreq_ctr_suffix) runs on test_CT
1381{
1382 var GsmFrameNumber fn := 23;
1383
1384 f_logp(BSCVTY, "f_chan_act_counter(" & chreq_ctr_suffix & ")");
1385
1386 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001387 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn));
1388 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001389 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1390
1391 f_ctrs_bts_add(0, "chreq:total");
1392 f_ctrs_bts_add(0, "chreq:attempted_" & chreq_ctr_suffix);
1393 f_ctrs_bts_verify();
1394
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001395 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
1396 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001397
1398 f_ctrs_bts_add(0, "chreq:successful");
1399 f_ctrs_bts_add(0, "chreq:successful_" & chreq_ctr_suffix);
1400 f_ctrs_bts_verify();
1401
1402 /* test is done, release RSL Conn Fail Ind to clean up */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001403 f_ipa_tx(ts_RSL_CONN_FAIL_IND(chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1404 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
1405 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001406 f_sleep(1.0);
1407}
1408
Harald Welte4003d112017-12-09 22:35:39 +01001409testcase TC_chan_act_counter() runs on test_CT {
1410 var BSSAP_N_UNITDATA_ind ud_ind;
1411 var integer chreq_total;
Harald Welte930d0a72018-03-22 22:08:40 +01001412 var RSL_Message rsl_unused;
Harald Welte4003d112017-12-09 22:35:39 +01001413
Harald Welte89d42e82017-12-17 16:42:41 +01001414 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001415
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001416 f_vty_allow_emerg_bts(true, 0);
1417
1418 f_ctrs_bts_init(1, counternames_bts_chreq);
1419
1420 /* emergency call: RA & 0xe0 == 0xa0 --> CHREQ_T_EMERG_CALL */
1421 f_chan_act_counter('a3'O, "emerg");
1422
1423 /* voice TCH/H: RA & 0xf0 == 0x40 --> CHREQ_T_VOICE_CALL_TCH_H */
1424 f_chan_act_counter('43'O, "call");
1425
1426 /* LU: RA & 0xf0 == 0x00 --> CHREQ_T_LOCATION_UPD */
1427 f_chan_act_counter('03'O, "location_upd");
1428
1429 /* Paging: RA & 0xf0 == 0x20 --> CHREQ_T_PAG_R_TCH_F */
1430 f_chan_act_counter('23'O, "pag");
1431 /* Paging: RA & 0xf0 == 0x30 --> CHREQ_T_PAG_R_TCH_FH */
1432 f_chan_act_counter('33'O, "pag");
1433
1434 /* LU: RA & 0xfc == 0x78 --> CHREQ_T_PDCH_TWO_PHASE */
1435 /* no PCU, so PDCH not allowed. Skip this test for now. */
1436 /* f_chan_act_counter('7b'O, "pdch"); */
1437
1438 /* LU: RA & 0xf0 == 0x10 --> CHREQ_T_SDCCH */
1439 f_chan_act_counter('13'O, "other");
Harald Welte4003d112017-12-09 22:35:39 +01001440
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001441 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001442}
1443
Harald Welteae026692017-12-09 01:03:01 +01001444/* CHAN RQD -> CHAN ACT -> CHAN ACT ACK -> RF CHAN REL */
Philipp Maier9c60a622020-07-09 15:08:46 +02001445private function f_TC_chan_act_ack_noest(OCT1 ra := '23'O) runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +01001446 var RSL_Message rx_rsl;
1447
Harald Welteae026692017-12-09 01:03:01 +01001448 /* Send CHAN RQD and wait for allocation; acknowledge it */
Philipp Maier9c60a622020-07-09 15:08:46 +02001449 var RslChannelNr chan_nr := f_chreq_act_ack(ra);
Harald Welteae026692017-12-09 01:03:01 +01001450
1451 /* expect BSC to disable the channel again if there's no RLL EST IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001452 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := T3101_MAX);
Harald Welteae026692017-12-09 01:03:01 +01001453
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001454 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001455}
1456
Philipp Maier9c60a622020-07-09 15:08:46 +02001457/* Normal variant */
1458testcase TC_chan_act_ack_noest() runs on test_CT {
Philipp Maieraf58db22020-08-12 17:24:40 +02001459 f_init(1);
Philipp Maier9c60a622020-07-09 15:08:46 +02001460 f_TC_chan_act_ack_noest();
1461}
1462
1463/* Emergency call variant */
1464testcase TC_chan_act_ack_noest_emerg() runs on test_CT {
1465 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
Philipp Maieraf58db22020-08-12 17:24:40 +02001466 f_init(1);
1467 f_vty_allow_emerg_bts(true, 0);
Philipp Maier9c60a622020-07-09 15:08:46 +02001468 f_TC_chan_act_ack_noest(ra := 'A5'O);
1469}
1470
Philipp Maier606f07d2020-08-12 17:21:58 +02001471/* Emergency call variant, but emergency calls are not allowed */
1472testcase TC_chan_rqd_emerg_deny() runs on test_CT {
1473 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
1474
1475 var RSL_Message rx_rsl;
1476 var GsmRrMessage rr;
1477
1478 f_init(1);
1479 f_vty_allow_emerg_bts(false, 0);
1480
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001481 IPA_RSL[0][0].clear;
1482 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier606f07d2020-08-12 17:21:58 +02001483
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001484 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Philipp Maier606f07d2020-08-12 17:21:58 +02001485 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
1486 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1487 setverdict(pass);
1488 } else {
1489 setverdict(fail, "immediate assignment not rejected");
1490 }
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01001491
1492 f_shutdown_helper();
Philipp Maier606f07d2020-08-12 17:21:58 +02001493}
1494
Harald Welteae026692017-12-09 01:03:01 +01001495/* Test behavior if MSC never answers to CR */
1496testcase TC_chan_act_ack_est_ind_noreply() runs on test_CT {
Harald Weltef77aef62018-01-28 15:35:42 +01001497 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
1498 var IpaStreamId sid := IPAC_PROTO_RSL_TRX0;
Harald Welteae026692017-12-09 01:03:01 +01001499 var RSL_Message rx_rsl;
Harald Weltef77aef62018-01-28 15:35:42 +01001500 var ASP_RSL_Unitdata rx_rsl_ud;
Harald Welteae026692017-12-09 01:03:01 +01001501
Harald Welte89d42e82017-12-17 16:42:41 +01001502 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001503
1504 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001505 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001506
1507 var octetstring l3 := '00010203040506'O
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001508 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
Harald Welteae026692017-12-09 01:03:01 +01001509
1510 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3)));
1511
1512 /* expect BSC to disable the channel again if there's no response from MSC */
Harald Weltef77aef62018-01-28 15:35:42 +01001513 /* MS waits 20s (T3210) at LU; 10s (T3230) at CM SERV REQ and 5s (T3220) AT detach */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001514 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001515 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001516}
1517
1518/* Test behavior if MSC answers with CREF to CR */
1519testcase TC_chan_act_ack_est_ind_refused() runs on test_CT {
1520 var BSSAP_N_CONNECT_ind rx_c_ind;
1521 var RSL_Message rx_rsl;
1522
Harald Welte89d42e82017-12-17 16:42:41 +01001523 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001524
1525 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001526 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001527
1528 var octetstring l3 := '00010203040506'O
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001529 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
Harald Welteae026692017-12-09 01:03:01 +01001530
1531 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1532 BSSAP.send(ts_BSSAP_DISC_req(rx_c_ind.connectionId, 0));
1533
1534 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001535 f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001536 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001537}
1538
Harald Welte618ef642017-12-14 14:58:20 +01001539/* CHAN RQD -> CHAN ACT -> CHAN ACT NACK -> RF CHAN REL */
1540testcase TC_chan_act_nack() runs on test_CT {
1541 var RSL_Message rx_rsl;
1542 var integer chact_nack;
1543
Harald Welte89d42e82017-12-17 16:42:41 +01001544 f_init(1);
Harald Welte618ef642017-12-14 14:58:20 +01001545
1546 chact_nack := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack");
1547
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001548 f_ipa_tx(ts_RSL_CHAN_RQD('33'O, 33));
1549 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Harald Welte618ef642017-12-14 14:58:20 +01001550 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1551
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001552 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte618ef642017-12-14 14:58:20 +01001553
1554 /* wait for some time to hope the NACK arrives before the CTRL GET below */
1555 f_sleep(0.5);
1556
1557 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack", chact_nack+1);
1558
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001559 f_shutdown_helper();
Harald Welte618ef642017-12-14 14:58:20 +01001560}
1561
Harald Welte799c97b2017-12-14 17:50:30 +01001562/* Test for channel exhaustion due to RACH overload */
1563testcase TC_chan_exhaustion() runs on test_CT {
1564 var ASP_RSL_Unitdata rsl_ud;
1565 var integer i;
1566 var integer chreq_total, chreq_nochan;
1567
Harald Welte89d42e82017-12-17 16:42:41 +01001568 f_init(1);
Harald Welte799c97b2017-12-14 17:50:30 +01001569
1570 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
1571 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
1572
Neels Hofmeyr85fa37f2021-10-06 13:50:38 +02001573 /* GSM 44.018 Table 9.1.8.2:
Pau Espin Pedrolfe200d72018-12-10 12:41:04 +01001574 * RA = '33'O -> Establishment cause = 0011xxxx (MS dual rate capable and asks for "TCH/H or TCH/F").
1575 * With current setup, expect 4xSDCCH + 4xTCH/F + 1xTCH/H to succeed */
Philipp Maiercb6cc482018-03-26 13:08:00 +02001576 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 +01001577 var RslChannelNr chan_nr := f_chreq_act_ack('33'O, i);
Harald Welte799c97b2017-12-14 17:50:30 +01001578 }
1579
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001580 IPA_RSL[0][0].clear;
Harald Welte799c97b2017-12-14 17:50:30 +01001581
Harald Weltedd8cbf32018-01-28 12:07:52 +01001582 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001583 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
Harald Welte799c97b2017-12-14 17:50:30 +01001584
1585 /* now expect additional channel activations to fail */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001586 f_ipa_tx(ts_RSL_CHAN_RQD('42'O, 42));
Harald Welte799c97b2017-12-14 17:50:30 +01001587
1588 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001589 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV))) {
Harald Welte799c97b2017-12-14 17:50:30 +01001590 setverdict(fail, "Received CHAN ACT ACK without resources?!?");
1591 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001592 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) -> value rsl_ud {
Harald Welte799c97b2017-12-14 17:50:30 +01001593 var GsmRrMessage rr;
1594 /* match on IMM ASS REJ */
1595 rr := dec_GsmRrMessage(rsl_ud.rsl.ies[1].body.full_imm_ass_info.payload);
1596 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1597 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001598 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS+1);
Harald Welte799c97b2017-12-14 17:50:30 +01001599 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel",
1600 chreq_nochan+1);
1601 setverdict(pass);
1602 } else {
1603 repeat;
1604 }
1605 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001606 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte799c97b2017-12-14 17:50:30 +01001607 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001608 f_shutdown_helper();
Harald Welte799c97b2017-12-14 17:50:30 +01001609}
1610
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001611/* Test channel deactivation due to silence from MS */
1612testcase TC_chan_deact_silence() runs on test_CT {
1613 var RslChannelNr chan_nr;
1614
1615 f_init(1);
1616
1617 /* Request for a dedicated channel */
1618 chan_nr := f_chreq_act_ack('23'O);
1619
1620 /* Wait some time until the channel is released */
1621 f_sleep(2.0);
1622
1623 /* Expect CHANnel RELease */
1624 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001625 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001626 log("Received CHANnel RELease");
1627 setverdict(pass);
1628 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001629 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001630 /* See OS#3709, OsmoBSC should not send Immediate
1631 * Assignment Reject since a dedicated channel was
1632 * already allocated, and Immediate Assignment was
1633 * already sent. */
1634 setverdict(fail, "Unexpected Immediate Assignment!");
1635 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001636 [] IPA_RSL[0][0].receive {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001637 setverdict(fail, "Unexpected RSL message!");
1638 }
1639 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001640 f_shutdown_helper();
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001641}
1642
Harald Weltecfe2c962017-12-15 12:09:32 +01001643/***********************************************************************
1644 * Assignment Testing
1645 ***********************************************************************/
1646
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02001647/* Verify that the BSC refuses any BSSAP connection from the MSC (They are all BSC->MSC direction,
1648 * except for the inter-BSC handover, MT side) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001649testcase TC_outbound_connect(integer bssap_idx := 0) runs on test_CT {
Harald Welte89d42e82017-12-17 16:42:41 +01001650 f_init(1);
Harald Weltecfe2c962017-12-15 12:09:32 +01001651
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001652 BSSAP.send(ts_BSSAP_CONNECT_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
1653 2342, ts_BSSMAP_AssignmentReq));
Harald Weltecfe2c962017-12-15 12:09:32 +01001654 BSSAP.receive(tr_BSSAP_DISC_ind(2342, ?, ?));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001655 f_shutdown_helper();
Harald Weltecfe2c962017-12-15 12:09:32 +01001656}
1657
Harald Welte16a4adf2017-12-14 18:54:01 +01001658/* Test behavior if MSC answers with CREF to CR */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001659testcase TC_assignment_cic_only(integer bssap_idx := 0) runs on test_CT {
Harald Welte16a4adf2017-12-14 18:54:01 +01001660 var BSSAP_N_CONNECT_ind rx_c_ind;
1661 var RSL_Message rx_rsl;
1662 var DchanTuple dt;
1663
Harald Welte89d42e82017-12-17 16:42:41 +01001664 f_init(1);
Harald Welte16a4adf2017-12-14 18:54:01 +01001665
1666 dt := f_est_dchan('23'O, 23, '00000000'O);
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001667 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte17b27da2018-05-25 20:33:53 +02001668 /* send assignment without AoIP IEs */
1669 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(ts_BSSMAP_IE_CIC(0, 1))));
1670 } else {
1671 /* Send assignmetn without CIC in IPA case */
1672 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
1673 valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
1674 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(omit, tla)));
1675 }
Harald Welte16a4adf2017-12-14 18:54:01 +01001676 alt {
1677 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1678 setverdict(fail, "AoIP BSC cannot accept ASSIGNMENT without AoIP Transport IE");
1679 }
Harald Welte235ebf12017-12-15 14:18:16 +01001680 /* TODO: Actually expect GSM0808_CAUSE_REQ_A_IF_TYPE_NOT_SUPP */
Harald Welte16a4adf2017-12-14 18:54:01 +01001681 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1682 setverdict(pass);
1683 }
1684 [] BSSAP.receive { repeat; }
1685 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001686 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001687 f_shutdown_helper();
Harald Welte16a4adf2017-12-14 18:54:01 +01001688}
1689
Harald Welteed848512018-05-24 22:27:58 +02001690/* generate an assignment request for either AoIP or SCCPlite */
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001691function 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 +02001692 var PDU_BSSAP ass_cmd;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001693 var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001694 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welteed848512018-05-24 22:27:58 +02001695 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001696 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001697 if (osmux_enabled) {
1698 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla, osmux_cid));
1699 } else {
1700 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla));
1701 }
Harald Welteed848512018-05-24 22:27:58 +02001702 } else {
1703 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrol096d73d2019-06-06 12:49:17 +02001704 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(cic, omit));
Harald Welteed848512018-05-24 22:27:58 +02001705 }
1706 return ass_cmd;
1707}
1708
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02001709function f_gen_handover_req(integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4",
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001710 template (value) BSSMAP_IE_CellIdentifier cell_id_source := ts_CellID_LAC_CI(1, 1),
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001711 template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit,
1712 template (omit) TestHdlrEncrParams enc := omit) return PDU_BSSAP {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001713 var PDU_BSSAP ho_req;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001714
1715 var BSSMAP_IE_EncryptionInformation encryptionInformation :=
1716 valueof(ts_BSSMAP_IE_EncrInfo('0000000000000000'O,'01'O));
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03001717 var template (omit) BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := omit;
1718 var template (omit) BSSMAP_IE_KC128 kc128 := omit;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001719 if (ispresent(enc)) {
1720 var TestHdlrEncrParams v_enc := valueof(enc);
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01001721 encryptionInformation := valueof(ts_BSSMAP_IE_EncrInfo(v_enc.enc_key, v_enc.enc_alg_permitted));
1722 if (ispresent(v_enc.enc_alg_chosen)) {
1723 chosenEncryptionAlgorithm := valueof(
1724 ts_BSSMAP_IE_ChosenEncryptionAlgorithm(int2oct(enum2int(
1725 f_cipher_mode_bssmap_to_rsl(v_enc.enc_alg_chosen)), 1)));
1726 }
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001727 if (ispresent(v_enc.enc_kc128)) {
1728 kc128 := ts_BSSMAP_IE_Kc128(v_enc.enc_kc128);
1729 }
1730 }
1731
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001732 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001733 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001734 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001735 ho_req := valueof(ts_BSSMAP_HandoverRequest(omit, tla,
1736 cell_id_source := cell_id_source,
1737 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001738 encryptionInformation := encryptionInformation,
1739 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
Neels Hofmeyr9fe13202022-03-04 00:05:43 +01001740 kC128 := kc128,
1741 /* on AoIP, allow "all" codecs (until we add more concise
1742 * tests) */
1743 codecList := ts_BSSMAP_IE_CodecList(
1744 {ts_CodecAMR_F, ts_CodecAMR_H,
1745 ts_CodecEFR, ts_CodecFR, ts_CodecHR})));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001746 } else {
1747 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01001748 ho_req := valueof(ts_BSSMAP_HandoverRequest(cic, omit,
1749 cell_id_source := cell_id_source,
1750 oldToNewBSSIEs := oldToNewBSSIEs,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001751 encryptionInformation := encryptionInformation,
1752 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
1753 kC128 := kc128));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001754 }
1755 return ho_req;
1756}
1757
Harald Welteed848512018-05-24 22:27:58 +02001758/* generate an assignment complete template for either AoIP or SCCPlite */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001759function f_gen_exp_compl(integer bssap_idx := 0)
1760runs on MSC_ConnHdlr return template PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001761 var template PDU_BSSAP exp_compl;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001762 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001763 var template BSSMAP_IE_Osmo_OsmuxCID exp_osmux_cid := omit;
1764 if (g_pars.use_osmux_cn) {
1765 var template (present) INT1 exp_cid := ?;
1766 if (isbound(g_media.mgcp_conn[0].local_osmux_cid) and isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1767 exp_cid := (g_media.mgcp_conn[0].local_osmux_cid, g_media.mgcp_conn[1].local_osmux_cid);
1768 } else if (isbound(g_media.mgcp_conn[0].local_osmux_cid)) {
1769 exp_cid := g_media.mgcp_conn[0].local_osmux_cid;
1770 } else if (isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
1771 exp_cid := g_media.mgcp_conn[1].local_osmux_cid;
1772 }
1773 exp_osmux_cid := tr_OsmuxCID(exp_cid);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001774 }
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001775 exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, exp_osmux_cid);
Harald Welteed848512018-05-24 22:27:58 +02001776 } else {
1777 /* CIC is optional "*" as the MSC allocated it */
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02001778 exp_compl := tr_BSSMAP_AssignmentComplete(*, omit, omit);
Harald Welteed848512018-05-24 22:27:58 +02001779 }
1780 return exp_compl;
1781}
1782
Harald Welte235ebf12017-12-15 14:18:16 +01001783/* Run everything required up to sending a caller-specified assignment command and expect response */
1784function f_assignment_exp(PDU_BSSAP ass_cmd, template PDU_BSSAP exp, charstring fail_text)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001785runs on test_CT return DchanTuple {
Harald Welte235ebf12017-12-15 14:18:16 +01001786 var BSSAP_N_CONNECT_ind rx_c_ind;
1787 var RSL_Message rx_rsl;
1788 var DchanTuple dt;
1789
Harald Welte89d42e82017-12-17 16:42:41 +01001790 f_init(1);
Harald Welte235ebf12017-12-15 14:18:16 +01001791
1792 dt := f_est_dchan('23'O, 23, '00000000'O);
1793 /* send assignment without AoIP IEs */
1794 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
1795 alt {
1796 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1797 if (ischosen(exp.pdu.bssmap.assignmentComplete)) {
1798 setverdict(pass);
1799 } else {
1800 setverdict(fail, fail_text);
1801 }
1802 }
1803 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1804 if (ischosen(exp.pdu.bssmap.assignmentFailure)) {
1805 setverdict(pass);
1806 } else {
1807 setverdict(fail, fail_text);
1808 }
1809 }
1810 [] BSSAP.receive { repeat; }
1811 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001812 return dt;
Harald Welte235ebf12017-12-15 14:18:16 +01001813}
1814testcase TC_assignment_csd() runs on test_CT {
1815 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001816 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001817 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
1818 //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 +01001819 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for CSD");
1820 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001821 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001822}
1823
1824testcase TC_assignment_ctm() runs on test_CT {
1825 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001826 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001827 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
1828 //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 +01001829 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
1830 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001831 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001832}
1833
Harald Welte4003d112017-12-09 22:35:39 +01001834type record DchanTuple {
1835 integer sccp_conn_id,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001836 RslChannelNr rsl_chan_nr,
1837 BtsTrxIdx idx
Harald Weltea5d2ab22017-12-09 14:21:42 +01001838}
1839
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +02001840type record of DchanTuple DchanTuples;
1841
Harald Welted6939652017-12-13 21:02:46 +01001842/* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001843private function f_chreq_act_ack(OCT1 ra := '23'O,
1844 GsmFrameNumber fn := 23,
1845 BtsTrxIdx idx := {0, 0})
Harald Welted6939652017-12-13 21:02:46 +01001846runs on test_CT return RslChannelNr {
1847 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001848 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
1849 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Harald Welted6939652017-12-13 21:02:46 +01001850 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001851 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10), idx);
1852 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Harald Welted6939652017-12-13 21:02:46 +01001853 return chan_nr;
1854}
1855
Harald Welte4003d112017-12-09 22:35:39 +01001856/* helper function to establish a dedicated channel via BTS and MSC */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001857function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1858 BtsTrxIdx idx := {0, 0})
Harald Welte4003d112017-12-09 22:35:39 +01001859runs on test_CT return DchanTuple {
1860 var BSSAP_N_CONNECT_ind rx_c_ind;
Harald Welte4003d112017-12-09 22:35:39 +01001861 var DchanTuple dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001862
Harald Welte4003d112017-12-09 22:35:39 +01001863 /* Send CHAN RQD and wait for allocation; acknowledge it */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001864 dt.rsl_chan_nr := f_chreq_act_ack(ra, fn, idx);
Harald Welte4003d112017-12-09 22:35:39 +01001865
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001866 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 +01001867
1868 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1869 dt.sccp_conn_id := rx_c_ind.connectionId;
1870 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1871
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001872 dt.idx := idx;
Harald Welte4003d112017-12-09 22:35:39 +01001873 return dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001874}
1875
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001876/* 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 +06001877function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3,
1878 BtsTrxIdx idx := {0, 0})
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001879runs on test_CT return DchanTuple {
1880 var BSSAP_N_CONNECT_ind rx_c_ind;
1881 var DchanTuple dt;
1882
1883 /* Send CHAN RQD */
1884 var RSL_Message rx_rsl;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001885 f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001886
1887 /* The dyn TS first deactivates PDCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001888 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 +02001889 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001890 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001891
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001892 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001893 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1894
1895 /* Now activates the signalling channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001896 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10), idx);
1897 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001898
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001899 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 +02001900
1901 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1902 dt.sccp_conn_id := rx_c_ind.connectionId;
1903 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1904
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001905 dt.idx := idx;
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001906 return dt;
1907}
1908
Harald Welte641fcbe2018-06-14 10:58:35 +02001909/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001910private function f_exp_chan_rel_and_clear(DchanTuple dt)
1911runs on test_CT {
Harald Welte641fcbe2018-06-14 10:58:35 +02001912 var RSL_Message rx_rsl;
1913 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001914 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 +02001915 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001916 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), dt.idx);
Harald Welte641fcbe2018-06-14 10:58:35 +02001917
1918 /* expect Clear Complete from BSC */
1919 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
1920
1921 /* MSC disconnects as instructed. */
1922 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
1923}
1924
Harald Welte4003d112017-12-09 22:35:39 +01001925/* Test behavior of channel release after unilateral RLL REL IND (DISC from MS) */
1926testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001927 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01001928 var DchanTuple dt;
Harald Welte96c94412017-12-09 03:12:45 +01001929
Harald Welte89d42e82017-12-17 16:42:41 +01001930 f_init(1);
Harald Welte96c94412017-12-09 03:12:45 +01001931
Harald Welte4003d112017-12-09 22:35:39 +01001932 dt := f_est_dchan('23'O, 23, '00010203040506'O);
1933
1934 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001935 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Harald Welte4003d112017-12-09 22:35:39 +01001936
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001937 /* expect Clear Request on MSC side */
1938 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
1939
1940 /* Instruct BSC to clear channel */
1941 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
1942 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
1943
Harald Welte4003d112017-12-09 22:35:39 +01001944 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001945 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001946
1947 /* wait for SCCP emulation to do its job */
1948 f_sleep(1.0);
Harald Welte4003d112017-12-09 22:35:39 +01001949
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001950 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001951}
1952
1953/* Test behavior of channel release after CONN FAIL IND from BTS */
1954testcase TC_chan_rel_conn_fail() runs on test_CT {
1955 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01001956 var DchanTuple dt;
1957
Harald Welte89d42e82017-12-17 16:42:41 +01001958 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001959
1960 dt := f_est_dchan('23'O, 23, '00010203040506'O);
1961
1962 /* simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001963 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte4003d112017-12-09 22:35:39 +01001964 /* TODO: different cause values? */
1965
Harald Welte4003d112017-12-09 22:35:39 +01001966 /* expect Clear Request from BSC */
1967 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
1968
1969 /* Instruct BSC to clear channel */
1970 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
1971 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
1972
Harald Welte6ff76ea2018-01-28 13:08:01 +01001973 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001974 f_exp_chan_rel_and_clear(dt);
Harald Welte4003d112017-12-09 22:35:39 +01001975
1976 /* wait for SCCP emulation to do its job */
1977 f_sleep(1.0);
1978
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001979 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001980}
1981
Harald Welte99f3ca02018-06-14 13:40:29 +02001982/* Test behavior of early CONN FAIL IND from BTS (before EST IND!) */
1983/* See also https://www.osmocom.org/issues/3182 */
1984testcase TC_early_conn_fail() runs on test_CT {
1985 var RSL_Message rx_rsl;
1986 var DchanTuple dt;
1987
1988 f_init(1);
1989
1990 /* BTS->BSC: Send CHAN RQD and wait for allocation; acknowledge it */
Harald Weltec46ea3c2020-10-10 18:46:12 +02001991 dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_ra_cs(), 23);
Harald Welte99f3ca02018-06-14 13:40:29 +02001992
1993 /* BTS->BSC: simulate CONN FAIL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001994 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02001995
1996 /* BTS->BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06001997 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02001998
1999 /* BTS<-BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002000 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002001
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002002 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002003}
2004
2005/* Test behavior of late CONN FAIL IND from BTS (ater REL IND!) */
2006/* See also https://www.osmocom.org/issues/3182 */
2007testcase TC_late_conn_fail() runs on test_CT {
2008 var RSL_Message rx_rsl;
2009 var DchanTuple dt;
2010
2011 f_init(1);
2012
2013 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2014
2015 /* BSC<-MSC: Instruct BSC to clear connection */
2016 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(0)));
2017
2018 /* BTS->BSC: expect BSC to deactivate SACCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002019 rx_rsl := f_exp_ipa_rx(tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002020
2021 /* BTS->BSC: simulate a late CONN FAIL IND from BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002022 f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte99f3ca02018-06-14 13:40:29 +02002023
2024 /* BTS<-BSC: Expect RF channel release from BSC on Abis */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002025 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
Harald Welte99f3ca02018-06-14 13:40:29 +02002026 /* BTS->BSC: respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002027 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
Harald Welte99f3ca02018-06-14 13:40:29 +02002028
2029 /* BSC->MSC: expect Clear Complete from BSC */
2030 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
2031
2032 /* BSC<-MSC: MSC disconnects as requested. */
2033 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2034
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002035 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02002036}
2037
Oliver Smithaf03bef2021-08-24 15:34:51 +02002038private function f_TC_stats_conn_fail(charstring id) runs on MSC_ConnHdlr {
2039 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
2040 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2041
2042 f_statsd_reset();
2043
2044 /* Establish SDCCH */
2045 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
2046 f_establish_fully(ass_cmd, exp_fail);
2047
2048 /* Expect stats to be 0 */
2049 var StatsDExpects expect := {
2050 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
2051 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
2052 };
2053 f_statsd_expect(expect);
2054
2055 /* Simulate CONN FAIL IND on SDCCH */
2056 RSL.send(ts_ASP_RSL_UD(
2057 ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
2058 IPAC_PROTO_RSL_TRX0));
2059
Neels Hofmeyr58be48a2021-09-07 18:39:21 +02002060 f_sleep(1.0);
2061
Oliver Smithaf03bef2021-08-24 15:34:51 +02002062 /* Expect stats to be 1 */
2063 expect := {
2064 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
2065 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
2066 };
2067 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002068 BSSAP.receive(tr_BSSMAP_ClearRequest);
2069 f_perform_clear();
Oliver Smithaf03bef2021-08-24 15:34:51 +02002070}
2071testcase TC_stats_conn_fail() runs on test_CT {
2072 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2073 var MSC_ConnHdlr vc_conn;
2074
2075 f_init(1, true);
2076 f_sleep(1.0);
2077
2078 vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
2079 vc_conn.done;
2080
2081 f_shutdown_helper();
2082}
2083
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002084function f_expect_chan_rel(RslChannelNr rsl_chan_nr,
2085 BtsTrxIdx idx := {0, 0},
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002086 boolean expect_deact_sacch := true,
2087 boolean expect_rr_chan_rel := true,
2088 boolean expect_rll_rel_req := true,
Harald Welte99787102019-02-04 10:41:36 +01002089 boolean handle_rll_rel := true,
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002090 template CellSelIndValue expect_cells := omit,
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002091 template (present) RR_Cause expect_rr_cause := ?
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002092 ) runs on test_CT {
Harald Welte91d54a52018-01-28 15:35:07 +01002093
2094 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002095 var boolean got_deact_sacch := false;
2096 var boolean got_rr_chan_rel := false;
2097 var boolean got_rll_rel_req := false;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002098 var ASP_RSL_Unitdata ud;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002099 var RSL_IE_Body l3_ie;
2100 var PDU_ML3_NW_MS l3;
2101 var RR_Cause got_cause;
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002102 log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
2103 " expect_rll_rel_req=", expect_rll_rel_req);
Harald Welte91d54a52018-01-28 15:35:07 +01002104 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002105 [] 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 +01002106 got_deact_sacch := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002107 repeat;
2108 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002109 [] 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 +01002110 got_rr_chan_rel := true;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002111
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002112 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2113 setverdict(fail, "cannot find L3");
2114 mtc.stop;
2115 }
2116 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2117
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002118 if (not istemplatekind(expect_cells, "omit")) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002119 var CellSelIndValue cells := dec_CellSelIndValue(
2120 l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
2121
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002122 log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
2123 if (match(cells, expect_cells)) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002124 setverdict(pass);
2125 } else {
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002126 log("EXPECTED CELLS: ", expect_cells);
2127 setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002128 }
2129 }
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002130
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002131 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2132 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2133 if (match(got_cause, expect_rr_cause)) {
2134 setverdict(pass);
2135 } else {
2136 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2137 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002138 }
Harald Welte99787102019-02-04 10:41:36 +01002139 repeat;
2140 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002141 [] 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 +01002142 got_rll_rel_req := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002143 /* FIXME: Why are we getting this for LinkID SACCH? */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002144 if (handle_rll_rel) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002145 f_ipa_tx(ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002146 }
Harald Welte91d54a52018-01-28 15:35:07 +01002147 repeat;
2148 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002149 [] 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 +01002150 /* respond with CHAN REL ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002151 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
Harald Welte91d54a52018-01-28 15:35:07 +01002152 }
2153 /* ignore any user data */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002154 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002155 repeat;
2156 }
2157 }
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002158
2159 log("f_expect_chan_rel() summary: got_deact_sacch=", got_deact_sacch, " got_rr_chan_rel=", got_rr_chan_rel,
2160 " got_rll_rel_req=", got_rll_rel_req);
2161
2162 if (expect_deact_sacch != got_deact_sacch) {
2163 setverdict(fail, "f_expect_chan_rel(): expect_deact_sacch=", expect_deact_sacch, " got_deact_sacch=", got_deact_sacch);
2164 }
2165 if (expect_rr_chan_rel != got_rr_chan_rel) {
2166 setverdict(fail, "f_expect_chan_rel(): expect_rr_chan_rel=", expect_rr_chan_rel, " got_rr_chan_rel=", got_rr_chan_rel);
2167 }
2168 if (expect_rll_rel_req != got_rll_rel_req) {
2169 setverdict(fail, "f_expect_chan_rel(): expect_rll_rel_req=", expect_rll_rel_req, " got_rll_rel_req=", got_rll_rel_req);
2170 }
Harald Welte91d54a52018-01-28 15:35:07 +01002171}
2172
Harald Welte4003d112017-12-09 22:35:39 +01002173/* Test behavior of channel release after hard Clear Command from MSC */
2174testcase TC_chan_rel_hard_clear() runs on test_CT {
2175 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002176 var DchanTuple dt;
Harald Welte4003d112017-12-09 22:35:39 +01002177
Harald Welte89d42e82017-12-17 16:42:41 +01002178 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002179
2180 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2181
2182 /* Instruct BSC to clear channel */
2183 var BssmapCause cause := 0;
2184 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2185
2186 /* expect Clear Complete from BSC on A */
2187 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2188 /* release the SCCP connection */
2189 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2190 }
2191
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002192 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002193 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002194}
2195
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002196function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
2197 var BSSAP_N_DATA_ind rx_di;
2198 var DchanTuple dt;
2199
2200 f_init(1);
2201
2202 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2203 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2204 /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
2205 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
2206
2207 /* Instruct BSC to clear channel */
2208 var BssmapCause cause := 0;
2209 if (tx_csfb_ind) {
2210 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2211 } else {
2212 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2213 }
2214
2215 /* expect Clear Complete from BSC on A */
2216 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2217 /* release the SCCP connection */
2218 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2219 }
2220
2221 /* 1 neighbor is added by default in osmo-bts.cfg and
2222 SystemInformationConfig_default, use that: */
2223 var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
2224
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002225 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 +02002226 f_shutdown_helper();
2227}
2228
2229/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
2230 from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
2231 PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2232 EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
2233 Indicator or not shouldn't matter at all. */
2234testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
2235 f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
2236}
2237
2238/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
2239 MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
2240 Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2241 EUTRAN neighbor list sent later on by BSC in RR Channel. */
2242testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
2243 f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
2244}
2245
2246/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
2247 MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
2248 Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
2249 CSFB Indicator should not be used anymore, and hence, there should be no
2250 EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
2251 Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
Harald Welte99787102019-02-04 10:41:36 +01002252testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
2253 var BSSAP_N_DATA_ind rx_di;
2254 var DchanTuple dt;
2255
2256 f_init(1);
2257
2258 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2259
2260 /* Instruct BSC to clear channel */
2261 var BssmapCause cause := 0;
2262 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2263
2264 /* expect Clear Complete from BSC on A */
2265 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2266 /* release the SCCP connection */
2267 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2268 }
2269
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002270 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002271 f_shutdown_helper();
Harald Welte99787102019-02-04 10:41:36 +01002272}
2273
Harald Welted8c36cd2017-12-09 23:05:31 +01002274/* Test behavior of channel release after hard RLSD from MSC */
2275testcase TC_chan_rel_hard_rlsd() runs on test_CT {
Harald Welted8c36cd2017-12-09 23:05:31 +01002276 var DchanTuple dt;
Harald Welted8c36cd2017-12-09 23:05:31 +01002277
Harald Welte89d42e82017-12-17 16:42:41 +01002278 f_init(1);
Harald Welted8c36cd2017-12-09 23:05:31 +01002279
2280 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2281
2282 /* release the SCCP connection */
2283 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2284
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002285 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002286 f_shutdown_helper();
Harald Welted8c36cd2017-12-09 23:05:31 +01002287}
2288
Harald Welte550daf92018-06-11 19:22:13 +02002289/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
2290testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
2291 var DchanTuple dt;
2292
2293 f_init(1);
2294
2295 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2296
2297 /* release the SCCP connection */
2298 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2299
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002300 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002301 f_shutdown_helper();
Harald Welte550daf92018-06-11 19:22:13 +02002302}
2303
Harald Welte85804d42017-12-10 14:11:58 +01002304/* Test behavior of channel release after BSSMAP RESET from MSC */
2305testcase TC_chan_rel_a_reset() runs on test_CT {
Harald Welte85804d42017-12-10 14:11:58 +01002306 var DchanTuple dt;
Harald Welte85804d42017-12-10 14:11:58 +01002307
Harald Welte89d42e82017-12-17 16:42:41 +01002308 f_init(1);
Harald Welte85804d42017-12-10 14:11:58 +01002309
2310 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2311
2312 /* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002313 IPA_RSL[0][0].clear;
Harald Welte85804d42017-12-10 14:11:58 +01002314
2315 /* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002316 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 +01002317 interleave {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02002318 [] 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 +01002319 [] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
2320 }
2321
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002322 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002323 f_shutdown_helper();
Harald Welte85804d42017-12-10 14:11:58 +01002324}
2325
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002326/* Verify T(iar) triggers and releases the channel */
2327testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
2328 var DchanTuple dt;
2329
2330 /* Set T(iar) in BSC low enough that it will trigger before other side
2331 has time to keep alive with a T(ias). Keep recommended ratio of
2332 T(iar) >= T(ias)*2 */
2333 g_bsc_sccp_timer_ias := 2;
2334 g_bsc_sccp_timer_iar := 5;
2335
2336 f_init(1);
2337
2338 dt := f_est_dchan('23'O, 23, '00010203040506'O);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002339 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002340 f_shutdown_helper();
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002341}
2342
Vadim Yanitskiybc7c35a2022-03-16 19:50:06 +03002343private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause,
2344 template (present) RR_Cause expect_rr_cause)
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002345runs on test_CT
2346{
2347 var DchanTuple dt;
2348
2349 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2350 var BssmapCause cause := 0;
2351 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
2352 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2353 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2354 }
2355
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002356 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_rr_cause := expect_rr_cause);
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002357}
2358
2359/* Test that Clear Command cause codes affect the RR Channel Release cause code */
2360testcase TC_chan_rel_rr_cause() runs on test_CT {
2361 f_init(1);
2362
2363 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
2364 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
2365 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
2366 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
2367 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
2368 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
Vadim Yanitskiye18aebb2021-01-03 13:10:43 +01002369
2370 f_shutdown_helper();
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002371}
2372
Harald Welte5cd20ed2017-12-13 21:03:20 +01002373/* Test behavior if RSL EST IND for non-active channel */
2374testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
2375 timer T := 2.0;
2376
Harald Welte89d42e82017-12-17 16:42:41 +01002377 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002378
2379 var octetstring l3 := '00010203040506'O;
2380 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002381 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002382
2383 T.start;
2384 alt {
2385 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2386 setverdict(fail, "MSC received COMPL L3 for non-active lchan");
2387 }
2388 [] BSSAP.receive {}
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002389 [] IPA_RSL[0][0].receive {}
Harald Welte5cd20ed2017-12-13 21:03:20 +01002390 [] T.timeout {}
2391 }
2392
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002393 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002394}
2395
2396/* Test behavior if RSL EST IND for invalid SAPI */
2397testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
2398 var RslChannelNr chan_nr;
2399
Harald Welte89d42e82017-12-17 16:42:41 +01002400 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002401
2402 chan_nr := f_chreq_act_ack()
2403
2404 var octetstring l3 := '00010203040506'O;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002405 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002406
2407 timer T := 2.0;
2408 T.start;
2409 alt {
2410 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2411 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
2412 }
2413 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002414 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002415 [] T.timeout {}
2416 }
2417
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002418 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002419}
2420
2421/* Test behavior if RSL EST IND for invalid SAPI */
2422testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
2423 timer T := 2.0;
2424
Harald Welte89d42e82017-12-17 16:42:41 +01002425 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002426
2427 var RslChannelNr chan_nr := f_chreq_act_ack();
2428
2429 var octetstring l3 := '00010203040506'O;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002430 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002431
2432 T.start;
2433 alt {
2434 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2435 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
2436 }
2437 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002438 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002439 [] T.timeout {}
2440 }
2441
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002442 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002443}
2444
2445/* Test behavior if RSL EST IND for invalid SACCH */
2446testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
2447 timer T := 2.0;
2448
Harald Welte89d42e82017-12-17 16:42:41 +01002449 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002450
2451 var RslChannelNr chan_nr := f_chreq_act_ack();
2452
2453 var octetstring l3 := '00010203040506'O;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002454 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3));
Harald Welte5cd20ed2017-12-13 21:03:20 +01002455
2456 T.start;
2457 alt {
2458 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2459 setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
2460 }
2461 [] BSSAP.receive { repeat; }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002462 [] IPA_RSL[0][0].receive { repeat; }
Harald Welte5cd20ed2017-12-13 21:03:20 +01002463 [] T.timeout {}
2464 }
2465
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002466 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002467}
2468
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002469/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
2470private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
2471 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
2472 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2473
2474 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
2475 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
2476
2477 f_establish_fully(ass_cmd, exp_compl);
2478
2479 /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
2480 RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
2481 /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
2482 BSSAP.receive(PDU_BSSAP:{
2483 discriminator := '1'B,
2484 spare := '0000000'B,
2485 dlci := 'C3'O,
2486 lengthIndicator := ?,
2487 pdu := { dtap := '0904'O }
2488 });
2489
2490 /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
2491 for (var integer i := 0; i < 32; i := i + 1) {
2492 var octetstring l3 := '09'O & f_rnd_octstring(14);
2493 var template (value) RslLinkId link_id;
2494 var template (value) OCT1 dlci;
2495
2496 if (i mod 2 == 0) {
2497 /* SAPI0 on FACCH or SDCCH */
2498 link_id := ts_RslLinkID_DCCH(0);
2499 dlci := '80'O;
2500 } else {
2501 /* SAPI3 on SACCH */
2502 link_id := ts_RslLinkID_SACCH(3);
2503 dlci := 'C3'O;
2504 }
2505
2506 /* Send MO message: RSL -> BSSAP */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002507 f_mo_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002508 /* Send MT message: BSSAP -> RSL */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002509 f_mt_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002510 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002511 f_perform_clear();
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002512}
2513testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
2514 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2515 var MSC_ConnHdlr vc_conn;
2516
2517 f_init(1, true);
2518 f_sleep(1.0);
2519
2520 vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
2521 vc_conn.done;
2522
2523 f_shutdown_helper();
2524}
2525
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002526private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002527 template (present) myBSSMAP_Cause cause := ?,
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002528 template (present) BIT2 cc := ?,
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002529 float T_val := 2.0)
2530runs on test_CT {
2531 var BSSAP_N_DATA_ind rx_di;
2532 timer T;
2533
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03002534 var template (present) BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
2535 var template (present) PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002536
2537 T.start(T_val);
2538 alt {
2539 [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
2540 var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
2541 if (not match(rx_cause, tr_cause)) {
2542 setverdict(fail, "Rx unexpected Cause IE: ",
2543 rx_cause, " vs expected ", tr_cause);
2544 }
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002545
2546 /* Who ever on the earth decided to define this field as two separate bits?!? */
2547 var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
2548 & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
2549 if (not match(rx_cc, cc)) {
2550 setverdict(fail, "Rx unexpected Control Channel type: ",
2551 rx_cc, " vs expected ", cc);
2552 }
2553
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002554 setverdict(pass);
2555 }
2556 [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
2557 setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
2558 }
2559 [] T.timeout {
2560 setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
2561 }
2562 }
2563}
2564
2565/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
2566testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
2567 var octetstring rnd_data := f_rnd_octstring(16);
2568 var RSL_Message rx_rsl;
2569 var DchanTuple dt;
2570
2571 f_init(1);
2572
2573 /* MS establishes a SAPI=0 link on DCCH */
2574 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2575
2576 /* MSC sends some data on (not yet established) SAPI=3 link */
2577 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2578 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002579 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 +07002580
2581 /* MS sends unexpected RELease INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002582 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002583 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2584 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
2585
2586 /* Clean up the connection */
2587 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002588 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002589
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002590 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002591}
2592
2593/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
2594testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
2595 var octetstring rnd_data := f_rnd_octstring(16);
2596 var RSL_Message rx_rsl;
2597 var DchanTuple dt;
2598
2599 f_init(1);
2600
2601 /* MS establishes a SAPI=0 link on DCCH */
2602 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2603
2604 /* MSC sends some data on (not yet established) SAPI=3 link */
2605 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2606 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002607 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 +07002608
2609 /* BTS sends unexpected ERROR INDication on SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002610 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002611 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2612 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
2613
2614 /* Clean up the connection */
2615 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002616 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002617
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002618 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002619}
2620
2621/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
2622testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
2623 var octetstring rnd_data := f_rnd_octstring(16);
2624 var RSL_Message rx_rsl;
2625 var DchanTuple dt;
2626
2627 f_init(1);
2628
2629 /* MS establishes a SAPI=0 link on DCCH */
2630 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2631
2632 /* MSC sends some data on (not yet established) SAPI=3 link */
2633 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2634 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002635 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 +07002636
2637 /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
2638 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
2639
2640 /* Clean up the connection */
2641 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002642 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002643
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002644 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002645}
2646
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002647/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
2648testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
2649 var octetstring rnd_data := f_rnd_octstring(16);
2650 var RSL_Message rx_rsl;
2651 var DchanTuple dt;
2652
2653 f_init(1);
2654
2655 /* MS establishes a SAPI=0 link on DCCH */
2656 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2657
2658 /* MSC sends some data on (not yet established) SAPI=3 link */
2659 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2660 /* BSC attempts to establish a SAPI=3 link on DCCH */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002661 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 +07002662
2663 /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002664 f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Pau Espin Pedrol121f27f2022-01-12 12:02:10 +01002665 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, '10'B);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002666
2667 /* Clean up the connection */
2668 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002669 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002670
2671 f_shutdown_helper();
2672}
2673
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002674testcase TC_si_default() runs on test_CT {
2675 f_init(0);
2676 f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002677 f_shutdown_helper();
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002678}
Harald Welte4003d112017-12-09 22:35:39 +01002679
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002680/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
2681 * the entire value range. This function provides the same EARFCN numbers for the same earfcn_index */
2682private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uint16_t
2683{
2684 select (earfcn_index) {
2685 case (0) {
2686 /* E-ARFCN 111 is already added in the osmo-bsc.cfg */
2687 return 111;
2688 }
2689 case (1) {
2690 return 1;
2691 }
2692 case (2) {
2693 return 0;
2694 }
2695 case (3) {
2696 return 65535;
2697 }
2698 case else {
2699 return 23 * (earfcn_index - 3);
2700 }
2701 }
2702}
2703
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002704function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
2705 template CellSelIndValue expect_cells := omit) runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002706
2707 f_init(0);
2708
2709 /* E-ARFCN 111 is already added in the osmo-bsc.cfg, so only add more arfcns if total_earfcns > 1 */
2710 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002711 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2712 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002713 }
2714
2715 f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
2716
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002717 if (not istemplatekind(expect_cells, "omit")) {
2718 /* Also check that RR Channel Release contains these EARFCNs.
2719 * (copied code from TC_chan_rel_hard_clear_csfb) */
2720 var BSSAP_N_DATA_ind rx_di;
2721 var DchanTuple dt;
2722
2723 dt := f_est_dchan('23'O, 23, '00010203040506'O);
Pau Espin Pedrold0046312021-04-19 16:35:58 +02002724 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2725 * yet when generating the EUTRAN neigh list in RR CHannel Release) */
2726 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002727
2728 /* Instruct BSC to clear channel */
2729 var BssmapCause cause := 0;
2730 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2731
2732 /* expect Clear Complete from BSC on A */
2733 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2734 /* release the SCCP connection */
2735 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2736 }
2737
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002738 f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := expect_cells);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002739 }
2740
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002741 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002742 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 +02002743 }
2744}
2745
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002746private function f_tr_si2quater_earfcns(integer count) return template SI2quaterRestOctetsList
2747{
2748 var template SI2quaterRestOctetsList si2quater := {};
2749 var integer si2quater_count := (count + 2) / 3;
2750
2751 for (var integer i := 0; i < count; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002752 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002753 var integer index := i / 3;
2754 var integer earfcn_index := i mod 3;
2755 if (index >= lengthof(si2quater)) {
2756 si2quater[index] := tr_SI2quaterRestOctets_EUTRAN(index := index, count := si2quater_count - 1);
2757 }
2758 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);
2759 }
2760
2761 return si2quater;
2762}
2763
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002764private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
2765{
2766 var template CellSelIndValue_EUTRAN_Descrs cells := {};
2767
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002768 /* the lte neighbors must match the config & vty to pass this test */
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002769 for (var integer i := 0; i < count; i := i + 1) {
2770 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002771 cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002772 }
2773
2774 return tr_CellSelIndValue_EUTRAN(cells);
2775}
2776
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002777private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
2778{
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002779 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrol8ab62e42020-12-18 16:19:11 +01002780 sic.si2quater := f_tr_si2quater_earfcns(n);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002781 var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
2782 f_test_si2quater(n, sic, cells);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002783}
2784
2785testcase TC_si2quater_2_earfcns() runs on test_CT {
2786 f_tc_si2quater_n_earfcns(2);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002787 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002788}
2789
2790testcase TC_si2quater_3_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002791 f_tc_si2quater_n_earfcns(3);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002792 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002793}
2794
2795testcase TC_si2quater_4_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002796 f_tc_si2quater_n_earfcns(4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002797 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002798}
2799
2800testcase TC_si2quater_5_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002801 f_tc_si2quater_n_earfcns(5);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002802 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002803}
2804
2805testcase TC_si2quater_6_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002806 f_tc_si2quater_n_earfcns(6);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002807 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002808}
2809
2810testcase TC_si2quater_12_earfcns() runs on test_CT {
2811 f_tc_si2quater_n_earfcns(12);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002812 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002813}
2814
2815testcase TC_si2quater_23_earfcns() runs on test_CT {
2816 f_tc_si2quater_n_earfcns(23);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002817 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002818}
2819
2820testcase TC_si2quater_32_earfcns() runs on test_CT {
2821 f_tc_si2quater_n_earfcns(32);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002822 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002823}
2824
2825testcase TC_si2quater_33_earfcns() runs on test_CT {
2826 f_tc_si2quater_n_earfcns(33);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002827 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002828}
2829
2830testcase TC_si2quater_42_earfcns() runs on test_CT {
2831 f_tc_si2quater_n_earfcns(42);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002832 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002833}
2834
2835testcase TC_si2quater_48_earfcns() runs on test_CT {
2836 f_tc_si2quater_n_earfcns(48);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002837 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002838}
2839
2840/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
2841 * 48 EARFCNs. */
2842testcase TC_si2quater_49_earfcns() runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002843 var template SystemInformationConfig sic := SystemInformationConfig_default;
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002844 sic.si2quater := f_tr_si2quater_earfcns(48); /* 48, not 49! */
2845 f_init(0);
2846
2847 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002848 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2849 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002850 }
2851
2852 /* The 49th EARFCN no longer fits, expect VTY error */
2853 f_vty_enter_cfg_bts(BSCVTY, 0);
2854 var charstring vty_error;
2855 vty_error := f_vty_transceive_ret(BSCVTY,
2856 "si2quater neighbor-list add earfcn 70 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3")
2857 f_vty_transceive(BSCVTY, "end");
2858
2859 if (f_strstr(vty_error, "Unable to add ARFCN 70") >= 0) {
2860 log("Got expected VTY error: ", vty_error);
2861 setverdict(pass);
2862 } else {
2863 setverdict(fail, "Expected the 49th EUTRAN ARFCN to be rejected by vty config, got: ", vty_error);
2864 }
2865
2866 f_init_bts_and_check_sysinfo(0, expect_si := sic);
2867
2868 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002869 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 +02002870 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002871 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002872}
2873
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002874private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
2875{
2876 var uint8_t count := 0;
2877 for (var integer i := 5; i < 16; i := i + 1) {
2878 if (acc[i] == '0'B) { /* the list marks barred, we count allowed */
2879 count := count + 1;
2880 }
2881 }
2882 return count;
2883}
2884
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002885private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return SystemInformationType1
2886{
2887 var ASP_RSL_Unitdata rx_rsl_ud;
2888 var SystemInformationType1 last_si1;
2889
2890 timer T := 30.0;
2891 T.start;
2892 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002893 [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
2894 tr_RSL_BCCH_INFO,
2895 tr_RSL_NO_SACCH_FILL,
2896 tr_RSL_SACCH_FILL))) -> value rx_rsl_ud {
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002897 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
2898 if (g_system_information[rsl_idx].si1 == omit) {
2899 repeat;
2900 }
2901 last_si1 := g_system_information[rsl_idx].si1;
2902 g_system_information[rsl_idx].si1 := omit;
2903 T.stop;
2904 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06002905 [] IPA_RSL[rsl_idx][0].receive { repeat; }
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002906 [] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
2907 }
2908 return last_si1;
2909}
2910
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002911/* verify ACC rotate feature */
2912testcase TC_si_acc_rotate() runs on test_CT {
2913 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002914 var SystemInformationType1 last_si1;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002915 var AccessControlClass acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002916 var uint8_t count;
2917 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2918
2919 f_init(0, guard_timeout := 60.0);
2920
2921 f_bts_0_cfg(BSCVTY, {"rach access-control-class 5 barred",
2922 "access-control-class-rotate 3",
2923 "access-control-class-rotate-quantum 1"});
2924
2925 /* Init and get first sysinfo */
2926 f_init_bts_and_check_sysinfo(0, expect_si := ?);
2927
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002928 for (var integer i:= 0; i < 20; i := i + 1) {
2929 last_si1 := f_recv_next_si1(0);
2930 acc := last_si1.rach_control.acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002931 count := f_acc09_count_allowed(acc);
2932 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
2933
2934 if (count != 3) {
2935 log("RSL: EXPECTED SI ACC len=3");
2936 setverdict(fail, "received SI does not match expectations");
2937 break;
2938 }
2939
2940 for (var integer j := 0; j < 10; j := j + 1) {
2941 if (acc[16 - 1 - j] == '0'B) { /* the list marks barred, we count allowed */
2942 times_allowed[j] := times_allowed[j] + 1;
2943 }
2944 }
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002945 }
2946
2947 for (var integer j := 0; j < 10; j := j + 1) {
2948 log("ACC", j, " allowed ", times_allowed[j], " times" );
2949 if (j != 5 and times_allowed[j] < 3) {
2950 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " < 1 times");
2951 } else if (j == 5 and times_allowed[j] > 0) {
2952 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " > 0 times");
2953 }
2954 }
2955
2956 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
2957 "rach access-control-class 5 allowed"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002958 f_shutdown_helper();
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002959}
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002960
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002961/* verify ACC startup ramp+rotate feature */
2962testcase TC_si_acc_ramp_rotate() runs on test_CT {
2963 var template SystemInformationConfig sic := SystemInformationConfig_default;
2964 var SystemInformationType1 last_si1;
2965 var AccessControlClass acc;
2966 var ASP_RSL_Unitdata rx_rsl_ud;
2967 var uint8_t count;
2968 var uint8_t prev_count;
2969 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2970
2971 f_init(0, guard_timeout := 80.0);
2972
2973 f_bts_0_cfg(BSCVTY, {"rach access-control-class 4 barred",
2974 "access-control-class-rotate 0",
2975 "access-control-class-rotate-quantum 1",
2976 "access-control-class-ramping",
2977 "access-control-class-ramping-step-interval 5",
2978 "access-control-class-ramping-step-size 5"});
2979
2980 /* Init and get first sysinfo */
2981 f_init_bts_and_check_sysinfo(0, expect_si := ?);
2982 last_si1 := g_system_information[0].si1;
2983 acc := last_si1.rach_control.acc;
2984 count := f_acc09_count_allowed(acc);
2985 /* Adm subset size was set to 0 above, so wait until all ACC are barred */
2986 while (count > 0) {
2987 last_si1 := f_recv_next_si1(0);
2988 acc := last_si1.rach_control.acc;
2989 count := f_acc09_count_allowed(acc);
2990 log("RSL: wait len()=0: GOT SI1 ACC len=", count, ": ", acc);
2991 }
2992
2993 /* Increase adm subset size, we should see ramping start up */
2994 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10"});
2995 prev_count := 0;
2996 while (true) {
2997 last_si1 := f_recv_next_si1(0);
2998 acc := last_si1.rach_control.acc;
2999 count := f_acc09_count_allowed(acc);
3000 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
3001
3002 if (prev_count > count) {
3003 setverdict(fail, "ACC allowed count dropped while expecting grow: ", prev_count, " -> ", count);
3004 break;
3005 }
3006
3007 if (count == 9) {
3008 break; /* Maximum reached (10 - 1 perm barred), done here */
3009 }
3010
3011 prev_count := count;
3012 }
3013
3014 setverdict(pass);
3015
3016 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
3017 "rach access-control-class 4 allowed",
3018 "no access-control-class-ramping"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003019 f_shutdown_helper();
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02003020}
3021
Harald Welte4003d112017-12-09 22:35:39 +01003022testcase TC_ctrl_msc_connection_status() runs on test_CT {
3023 var charstring ctrl_resp;
3024
Harald Welte89d42e82017-12-17 16:42:41 +01003025 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003026
3027 /* See https://osmocom.org/issues/2729 */
3028 f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003029 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01003030}
3031
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003032testcase TC_ctrl_msc0_connection_status() runs on test_CT {
3033 var charstring ctrl_resp;
3034
3035 f_init(1);
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003036
3037 f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003038 f_shutdown_helper();
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01003039}
3040
Neels Hofmeyr0bc470d2021-08-21 13:37:13 +02003041/* Verify correct stats on the number of configured and connected MSCs */
3042private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
3043 g_pars := f_gen_test_hdlr_pars();
3044 var StatsDExpects expect := {
3045 { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
3046 { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
3047 };
3048 f_statsd_expect(expect);
3049}
3050
3051private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
3052{
3053 var MSC_ConnHdlr vc_conn;
3054
3055 f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
3056 f_sleep(1.0);
3057 vc_conn := f_start_handler(tc_fn);
3058 vc_conn.done;
3059
3060 /* Also verify stat exposed on CTRL interface */
3061 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
3062 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
3063
3064 f_shutdown_helper();
3065}
3066
3067/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
3068private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
3069 f_tc_stat_num_msc_connected_msc_connhdlr(1);
3070}
3071testcase TC_stat_num_msc_connected_1() runs on test_CT {
3072 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
3073}
3074
3075/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
3076private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
3077 f_tc_stat_num_msc_connected_msc_connhdlr(2);
3078}
3079testcase TC_stat_num_msc_connected_2() runs on test_CT {
3080 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
3081}
3082
3083/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
3084private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
3085 f_tc_stat_num_msc_connected_msc_connhdlr(3);
3086}
3087testcase TC_stat_num_msc_connected_3() runs on test_CT {
3088 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
3089}
3090
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003091/* Verify correct stats on the number of configured and connected MSCs */
3092private 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 +06003093 var integer num_trx_connected := 0;
3094 var integer num_trx_total := 0;
3095
3096 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3097 var integer trx_num := c_BtsParams[i].trx_num;
3098 num_trx_total := num_trx_total + trx_num;
3099 if (i < expect_num_bts_connected) {
3100 num_trx_connected := num_trx_connected + trx_num;
3101 }
3102 }
3103
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003104 var StatsDExpects expect := {
3105 { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
3106 { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3107 { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003108 { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := num_trx_connected, max := num_trx_connected },
3109 { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := num_trx_total, max := num_trx_total }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003110 };
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003111
3112 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003113 f_statsd_expect(expect);
3114}
3115
3116private 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 +06003117 var integer num_trx_connected := 0;
3118 var integer num_trx_total := 0;
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003119 var MSC_ConnHdlr vc_conn;
3120
3121 f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
3122 f_sleep(1.0);
3123 vc_conn := f_start_handler(tc_fn);
3124 vc_conn.done;
3125
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003126 for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
3127 var integer trx_num := c_BtsParams[i].trx_num;
3128 num_trx_total := num_trx_total + trx_num;
3129 if (i < nr_bts) {
3130 num_trx_connected := num_trx_connected + trx_num;
3131 }
3132 }
3133
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003134 /* Also verify stat exposed on CTRL interface */
3135 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
3136 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 +06003137 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(num_trx_connected));
3138 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 +02003139
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003140 /* Verify rf_states exposed on CTRL interface */
3141 var charstring expect_net_rf_states := "";
3142 for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003143 var charstring expect_bts_rf_states := "";
3144
3145 for (var integer j := 0; j < c_BtsParams[i].trx_num; j := j + 1) {
3146 expect_bts_rf_states := expect_bts_rf_states &
3147 int2str(i) & "," & int2str(j) & ",";
3148 if (i < NUM_BTS) {
3149 /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
3150 expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
3151 } else {
3152 /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
3153 expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
3154 }
3155 /* The RF policy is still global in osmo-bsc, i.e. always "on" */
3156 expect_bts_rf_states := expect_bts_rf_states & "on,";
3157 if (i < nr_bts) {
3158 /* For BTS where RSL is connected, the RSL state will be "up" */
3159 expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
3160 } else {
3161 expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
3162 }
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003163 }
3164
3165 f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
3166 expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
3167 }
3168 f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
3169
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003170 f_shutdown_helper();
3171}
3172
3173/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
3174private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
3175 f_tc_stat_num_bts_connected_msc_connhdlr(1);
3176}
3177testcase TC_stat_num_bts_connected_1() runs on test_CT {
3178 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
3179}
3180
3181/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
3182private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
3183 f_tc_stat_num_bts_connected_msc_connhdlr(2);
3184}
3185testcase TC_stat_num_bts_connected_2() runs on test_CT {
3186 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
3187}
3188
3189/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
3190private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
3191 f_tc_stat_num_bts_connected_msc_connhdlr(3);
3192}
3193testcase TC_stat_num_bts_connected_3() runs on test_CT {
3194 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
3195}
3196
Harald Welte4003d112017-12-09 22:35:39 +01003197testcase TC_ctrl() runs on test_CT {
3198 var charstring ctrl_resp;
3199
Harald Welte89d42e82017-12-17 16:42:41 +01003200 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003201
3202 /* all below values must match the osmo-bsc.cfg config file used */
3203
Harald Welte6a129692018-03-17 17:30:14 +01003204 f_ctrl_get_exp(IPA_CTRL, "mcc", "001");
3205 f_ctrl_get_exp(IPA_CTRL, "mnc", "01");
Oliver Smith75aa0202019-08-19 14:17:50 +02003206 f_ctrl_get_exp(IPA_CTRL, "number-of-bts", "4");
Harald Welte4003d112017-12-09 22:35:39 +01003207
3208 var integer bts_nr := 0;
3209 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "location-area-code", "1");
3210 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "cell-identity", "0");
3211 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "oml-connection-state", "connected");
3212 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "gprs-mode", "gprs");
3213 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "rf_state", "operational,unlocked,on");
3214 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "arfcn", "871");
3215 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "max-power-reduction", "20");
3216
3217 var integer uptime := str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime"));
3218 f_sleep(2.0);
3219 if (str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime")) < uptime+1) {
3220 setverdict(fail, "oml-uptime not incrementing as expected");
3221 }
3222 /* TODO: Disconnect RSL, imply that OML is disconnected and check for uptime zero? */
3223
3224 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
3225
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003226 f_shutdown_helper();
Harald Welte96c94412017-12-09 03:12:45 +01003227}
3228
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003229/* Verify that Upon receival of SET "location", BSC forwards a TRAP
3230 "location-state" over the SCCPlite IPA conn */
3231testcase TC_ctrl_location() runs on test_CT {
3232 var MSC_ConnHdlr vc_conn;
3233 var integer bts_nr := 0;
3234
3235 f_init(1, true);
3236 f_sleep(1.0);
3237
3238 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234567,fix3d,0.340000,0.560000,0.780000");
3239 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3240 "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
3241
3242 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "1");
3243 f_sleep(2.0);
3244
3245 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234888,fix3d,0.350000,0.570000,0.790000");
3246 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3247 "1234888,fix3d,0.350000,0.570000,0.790000,operational,locked,off,001,01");
3248
3249 /* should match the one from config */
3250 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
3251
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003252 f_shutdown_helper();
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003253}
3254
Harald Welte6f521d82017-12-11 19:52:02 +01003255
3256/***********************************************************************
3257 * Paging Testing
3258 ***********************************************************************/
3259
3260type record Cell_Identity {
3261 GsmMcc mcc,
3262 GsmMnc mnc,
3263 GsmLac lac,
3264 GsmCellId ci
3265};
Harald Welte24135bd2018-03-17 19:27:53 +01003266private const Cell_Identity cid := { '001'H, '01'H, 1, 0 };
Stefan Sperling049a86e2018-03-20 15:51:00 +01003267private const Cell_Identity unknown_cid := { '678'H, 'f90'H, 1, 0 };
Harald Welte6f521d82017-12-11 19:52:02 +01003268
Harald Welte5d1a2202017-12-13 19:51:29 +01003269type set of integer BtsIdList;
3270
3271private function f_bts_in_list(integer bts_id, BtsIdList bts_ids) return boolean {
3272 for (var integer j := 0; j < sizeof(bts_ids); j := j + 1) {
3273 if (bts_id == bts_ids[j]) {
3274 return true;
3275 }
3276 }
3277 return false;
3278}
Harald Welte6f521d82017-12-11 19:52:02 +01003279
3280/* core paging test helper function; used by most paging test cases */
3281private function f_pageing_helper(hexstring imsi,
3282 template BSSMAP_FIELD_CellIdentificationList cid_list,
Harald Welte5d1a2202017-12-13 19:51:29 +01003283 BtsIdList bts_ids := { 0 },
Harald Welte6f521d82017-12-11 19:52:02 +01003284 template RSL_ChanNeeded rsl_chneed := omit,
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003285 template (omit) OCT4 tmsi := omit) runs on test_CT
Harald Welte6f521d82017-12-11 19:52:02 +01003286{
3287 var template BSSMAP_IE_ChannelNeeded bssmap_chneed;
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003288 var template MobileIdentityV mi;
Harald Welte6f521d82017-12-11 19:52:02 +01003289 var RSL_Message rx_rsl;
3290 var integer paging_group := hex2int(imsi[lengthof(imsi)-1]);
Harald Welte5d1a2202017-12-13 19:51:29 +01003291 var integer i;
Harald Welte6f521d82017-12-11 19:52:02 +01003292
3293 f_init();
Harald Welte6f521d82017-12-11 19:52:02 +01003294
3295 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Harald Weltec3068592018-03-17 19:55:31 +01003296 for (i := 0; i < NUM_BTS; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003297 IPA_RSL[i][0].clear;
Harald Welte5d1a2202017-12-13 19:51:29 +01003298 }
Harald Welte6f521d82017-12-11 19:52:02 +01003299
3300 if (isvalue(rsl_chneed)) {
3301 /* The values of 08.08 3.2.2.36 and 08.58 9.3.40 are luckily identical */
3302 bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
3303 } else {
3304 bssmap_chneed := omit;
3305 }
3306
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003307 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
3308 ts_BSSMAP_Paging(imsi, cid_list, tmsi, bssmap_chneed)));
Harald Welte6f521d82017-12-11 19:52:02 +01003309
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003310 if (not istemplatekind(tmsi, "omit")) {
3311 mi := t_MI_TMSI(tmsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003312 } else {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003313 mi := tr_MI_IMSI(imsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003314 }
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003315
Harald Welte5d1a2202017-12-13 19:51:29 +01003316 for (i := 0; i < sizeof(bts_ids); i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003317 rx_rsl := f_exp_ipa_rx(tr_RSL_PAGING_CMD(mi), idx := {bts_ids[i], 0});
Harald Welte5d1a2202017-12-13 19:51:29 +01003318 /* check channel type, paging group */
3319 if (rx_rsl.ies[1].body.paging_group != paging_group) {
3320 setverdict(fail, "Paging for wrong paging group");
3321 }
3322 if (ispresent(rsl_chneed) and
3323 rx_rsl.ies[3].body.chan_needed.chan_needed != valueof(rsl_chneed)) {
3324 setverdict(fail, "RSL Channel Needed != BSSMAP Channel Needed");
3325 }
Harald Welte6f521d82017-12-11 19:52:02 +01003326 }
Harald Welte2fccd982018-01-31 15:48:19 +01003327 f_sleep(2.0);
Harald Welte5d1a2202017-12-13 19:51:29 +01003328 /* do a quick check on all not-included BTSs if they received paging */
3329 for (i := 0; i < NUM_BTS; i := i + 1) {
3330 timer T := 0.1;
3331 if (f_bts_in_list(i, bts_ids)) {
3332 continue;
3333 }
3334 T.start;
3335 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003336 [] IPA_RSL[i][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003337 setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
3338 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003339 [] IPA_RSL[i][0].receive { repeat; }
Harald Welte5d1a2202017-12-13 19:51:29 +01003340 [] T.timeout { }
3341 }
Harald Welte6f521d82017-12-11 19:52:02 +01003342 }
3343
3344 setverdict(pass);
3345}
3346
Harald Welte5d1a2202017-12-13 19:51:29 +01003347const BtsIdList c_BtsId_all := { 0, 1, 2 };
Harald Welte751d3eb2018-01-31 15:51:06 +01003348const BtsIdList c_BtsId_none := { };
Harald Welte5d1a2202017-12-13 19:51:29 +01003349const BtsIdList c_BtsId_LAC1 := { 0, 1 };
3350const BtsIdList c_BtsId_LAC2 := { 2 };
3351
Harald Welte6f521d82017-12-11 19:52:02 +01003352/* PAGING by IMSI + TMSI */
3353testcase TC_paging_imsi_nochan() runs on test_CT {
3354 var BSSMAP_FIELD_CellIdentificationList cid_list;
3355 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Philipp Maier8c04b0a2018-02-23 13:48:48 +01003356 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, omit);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003357 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003358}
3359
3360/* PAGING by IMSI + TMSI */
3361testcase TC_paging_tmsi_nochan() runs on test_CT {
3362 var BSSMAP_FIELD_CellIdentificationList cid_list;
3363 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003364 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, 'A1B2C301'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003365 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003366}
3367
3368/* Paging with different "channel needed' values */
3369testcase TC_paging_tmsi_any() runs on test_CT {
3370 var BSSMAP_FIELD_CellIdentificationList cid_list;
3371 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003372 f_pageing_helper('001010100000002'H, cid_list, c_BtsId_all, RSL_CHANNEED_ANY, 'A1B2C302'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003373 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003374}
3375testcase TC_paging_tmsi_sdcch() runs on test_CT {
3376 var BSSMAP_FIELD_CellIdentificationList cid_list;
3377 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003378 f_pageing_helper('001010100000003'H, cid_list, c_BtsId_all, RSL_CHANNEED_SDCCH, 'A1B2C303'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003379 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003380}
3381testcase TC_paging_tmsi_tch_f() runs on test_CT {
3382 var BSSMAP_FIELD_CellIdentificationList cid_list;
3383 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003384 f_pageing_helper('001010000000004'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_F, 'A1B2C304'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003385 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003386}
3387testcase TC_paging_tmsi_tch_hf() runs on test_CT {
3388 var BSSMAP_FIELD_CellIdentificationList cid_list;
3389 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003390 f_pageing_helper('001010000000005'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_ForH, 'A1B2C305'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003391 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003392}
3393
3394/* Paging by CGI */
3395testcase TC_paging_imsi_nochan_cgi() runs on test_CT {
3396 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3397 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(cid.mcc, cid.mnc, cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003398 f_pageing_helper('001010000000006'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003399 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003400}
3401
3402/* Paging by LAC+CI */
3403testcase TC_paging_imsi_nochan_lac_ci() runs on test_CT {
3404 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3405 cid_list := { cIl_LAC_CI := { ts_BSSMAP_CI_LAC_CI(cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003406 f_pageing_helper('001010000000007'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003407 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003408}
3409
3410/* Paging by CI */
3411testcase TC_paging_imsi_nochan_ci() runs on test_CT {
3412 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3413 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003414 f_pageing_helper('001010000000008'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003415 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003416}
3417
3418/* Paging by LAI */
3419testcase TC_paging_imsi_nochan_lai() runs on test_CT {
3420 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3421 cid_list := { cIl_LAI := { ts_BSSMAP_CI_LAI(cid.mcc, cid.mnc, cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003422 f_pageing_helper('001010000000009'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003423 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003424}
3425
3426/* Paging by LAC */
3427testcase TC_paging_imsi_nochan_lac() runs on test_CT {
3428 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3429 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003430 f_pageing_helper('001010000000010'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003431 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003432}
3433
3434/* Paging by "all in BSS" */
3435testcase TC_paging_imsi_nochan_all() runs on test_CT {
3436 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3437 cid_list := { cIl_allInBSS := ''O };
Harald Welte5d1a2202017-12-13 19:51:29 +01003438 f_pageing_helper('001010000000011'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003439 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003440}
3441
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003442/* Paging by PLMN+LAC+RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003443testcase TC_paging_imsi_nochan_plmn_lac_rnc() runs on test_CT {
3444 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3445 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 +01003446 f_pageing_helper('001010000000012'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003447 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003448}
Harald Welte6f521d82017-12-11 19:52:02 +01003449
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003450/* Paging by RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003451testcase TC_paging_imsi_nochan_rnc() runs on test_CT {
3452 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3453 cid_list := { cIl_RNC := { int2oct(13, 2) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003454 f_pageing_helper('001010000000013'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003455 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003456}
3457
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003458/* Paging by LAC+RNC; We do not implement; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003459testcase TC_paging_imsi_nochan_lac_rnc() runs on test_CT {
3460 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3461 cid_list := { cIl_LAC_RNC := { ts_BSSMAP_CI_LAC_RNC(cid.lac, 14) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003462 f_pageing_helper('001010000000014'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003463 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003464}
3465
Harald Welte6f521d82017-12-11 19:52:02 +01003466/* Paging on multiple cells (multiple entries in list): Verify all of them page */
Harald Welte751d3eb2018-01-31 15:51:06 +01003467testcase TC_paging_imsi_nochan_lacs() runs on test_CT {
3468 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3469 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(1), ts_BSSMAP_CI_LAC(2) } };
3470 f_pageing_helper('001010000000015'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003471 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003472}
3473
3474/* Paging on empty list: Verify none of them page */
3475testcase TC_paging_imsi_nochan_lacs_empty() runs on test_CT {
3476 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3477 cid_list := { cIl_LAC := { } };
3478 f_pageing_helper('001010000000016'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003479 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003480}
3481
Stefan Sperling049a86e2018-03-20 15:51:00 +01003482/* Paging by CGI with unknown MCC/MNC: Verify nothing is paged. */
3483testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
3484 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3485 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(unknown_cid.mcc, unknown_cid.mnc, unknown_cid.lac, unknown_cid.ci) } };
3486 f_pageing_helper('001010000000006'H, cid_list, c_BtsId_none);
3487 f_shutdown_helper();
3488}
3489
Harald Welte6f521d82017-12-11 19:52:02 +01003490/* Verify paging retransmission interval + count */
3491/* Verify paging stops after channel establishment */
Harald Welte6f521d82017-12-11 19:52:02 +01003492/* Test behavior under paging overload */
Harald Welteae026692017-12-09 01:03:01 +01003493
Harald Weltee65d40e2017-12-13 00:09:06 +01003494/* Verify PCH load */
3495testcase TC_paging_imsi_load() runs on test_CT {
3496 var BSSMAP_FIELD_CellIdentificationList cid_list;
3497 timer T := 4.0;
Harald Welte2caa1062018-03-17 18:19:05 +01003498 timer T_retrans := 1.0;
Harald Weltee65d40e2017-12-13 00:09:06 +01003499 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003500 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Weltee65d40e2017-12-13 00:09:06 +01003501
3502 /* tell BSC there is no paging space anymore */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003503 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte3b57ab52018-03-17 18:01:10 +01003504 f_sleep(0.2);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003505 IPA_RSL[0][0].clear;
Harald Weltee65d40e2017-12-13 00:09:06 +01003506
3507 /* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
3508 * there would be 8 retransmissions during 4 seconds */
3509 T.start;
Harald Welte2caa1062018-03-17 18:19:05 +01003510 T_retrans.start;
Harald Weltee65d40e2017-12-13 00:09:06 +01003511 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003512 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Weltee65d40e2017-12-13 00:09:06 +01003513 setverdict(fail, "Received PAGING after LOAD_IND(0)");
Daniel Willmannafce8662018-07-06 23:11:32 +02003514 mtc.stop;
Harald Weltee65d40e2017-12-13 00:09:06 +01003515 }
Harald Welte2caa1062018-03-17 18:19:05 +01003516 [] T_retrans.timeout {
3517 /* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003518 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
Harald Welte2caa1062018-03-17 18:19:05 +01003519 T_retrans.start;
3520 repeat;
3521 }
Harald Weltee65d40e2017-12-13 00:09:06 +01003522 [] T.timeout {
3523 setverdict(pass);
3524 }
3525 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003526
3527 f_shutdown_helper();
Harald Weltee65d40e2017-12-13 00:09:06 +01003528}
3529
Harald Welte235ebf12017-12-15 14:18:16 +01003530/* Verify Paging Counter */
Harald Welte1ff69992017-12-14 12:31:17 +01003531testcase TC_paging_counter() runs on test_CT {
3532 var BSSMAP_FIELD_CellIdentificationList cid_list;
3533 timer T := 4.0;
3534 var integer i;
3535 var integer paging_attempted_bsc;
3536 var integer paging_attempted_bts[NUM_BTS];
Oliver Smith8b343d32021-11-26 13:01:42 +01003537 var integer paging_expired_bsc;
Harald Welte1ff69992017-12-14 12:31:17 +01003538 var integer paging_expired_bts[NUM_BTS];
3539 cid_list := valueof(ts_BSSMAP_CIL_noCell);
3540
3541 f_init();
3542
3543 /* read counters before paging */
3544 paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
Oliver Smith8b343d32021-11-26 13:01:42 +01003545 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.8.0 */
3546 paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
3547 }
Harald Welte1ff69992017-12-14 12:31:17 +01003548 for (i := 0; i < NUM_BTS; i := i+1) {
3549 paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
3550 paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
3551 }
3552
3553 f_pageing_helper('001230000000001'H, cid_list, c_BtsId_all);
3554
3555 /* expect the attempted pages on BSC and each BTSs to have incremented by one */
3556 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", paging_attempted_bsc+1);
3557 for (i := 0; i < NUM_BTS; i := i+1) {
3558 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted",
3559 paging_attempted_bts[i]+1);
3560 }
3561
3562 /* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
3563 f_sleep(12.0);
Oliver Smith8b343d32021-11-26 13:01:42 +01003564 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.8.0 */
3565 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
3566 }
Harald Welte1ff69992017-12-14 12:31:17 +01003567 for (i := 0; i < NUM_BTS; i := i+1) {
3568 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
3569 paging_expired_bts[i]+1);
3570 }
Harald Welte1ff69992017-12-14 12:31:17 +01003571
Philipp Maier282ca4b2018-02-27 17:17:00 +01003572 f_shutdown_helper();
Harald Welte1ff69992017-12-14 12:31:17 +01003573}
3574
3575
Harald Welte10985002017-12-12 09:29:15 +01003576/* Verify paging stops after A-RESET */
3577testcase TC_paging_imsi_a_reset() runs on test_CT {
3578 var BSSMAP_FIELD_CellIdentificationList cid_list;
3579 timer T := 3.0;
3580 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003581 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Welte10985002017-12-12 09:29:15 +01003582
3583 /* Perform a BSSMAP Reset and wait for ACK */
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003584 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 +01003585 alt {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02003586 [] 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 +01003587 [] BSSAP.receive { repeat; }
3588 }
3589
Daniel Willmanncbef3982018-07-30 09:22:40 +02003590 /* Wait to avoid a possible race condition if a paging message is
3591 * received right before the reset ACK. */
3592 f_sleep(0.2);
3593
Harald Welte10985002017-12-12 09:29:15 +01003594 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Philipp Maier1e6b4422018-02-23 14:02:13 +01003595 for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003596 IPA_RSL[i][0].clear;
Philipp Maier1e6b4422018-02-23 14:02:13 +01003597 }
Harald Welte10985002017-12-12 09:29:15 +01003598
3599 /* Wait for 3 seconds if any more PAGING CMD are received on RSL */
3600 T.start;
3601 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003602 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte10985002017-12-12 09:29:15 +01003603 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003604 mtc.stop;
Harald Welte10985002017-12-12 09:29:15 +01003605 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003606 [] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003607 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003608 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003609 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003610 [] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003611 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003612 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003613 }
Harald Welte10985002017-12-12 09:29:15 +01003614 [] T.timeout {
3615 setverdict(pass);
3616 }
3617 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003618
3619 f_shutdown_helper();
Harald Welte10985002017-12-12 09:29:15 +01003620}
Harald Welteae026692017-12-09 01:03:01 +01003621
Philipp Maierf45824a2019-08-14 14:44:10 +02003622/* Verify how we handle unsolicited Paging Response. In case of an unsolicit
3623 * paging response we can not know which MSC is in charge, so we will blindly
3624 * pick the first configured MSC. This behavior is required in order to make
3625 * MT-CSFB calls working because in those cases the BSC can not know that the
3626 * MSC has already paged the subscriver via SGs. So any MT-CSFB call will look
3627 * like an unsolicited Paging Response to the MSC.
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003628 */
3629testcase TC_paging_resp_unsol() runs on test_CT {
3630
3631 f_init(1);
Philipp Maierf45824a2019-08-14 14:44:10 +02003632 timer T := 5.0;
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003633
3634 var BSSAP_N_CONNECT_ind rx_c_ind;
3635 var DchanTuple dt;
3636 var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010008880018'H))));
Philipp Maierf45824a2019-08-14 14:44:10 +02003637 var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003638
3639 /* Send CHAN RQD and wait for allocation; acknowledge it */
3640 dt.rsl_chan_nr := f_chreq_act_ack();
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003641 dt.idx := {0, 0};
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003642
3643 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003644 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 +01003645
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003646
Philipp Maierf45824a2019-08-14 14:44:10 +02003647 /* Expevct a CR with a matching Paging response on the A-Interface */
3648 T.start;
3649 alt {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003650 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
Philipp Maierf45824a2019-08-14 14:44:10 +02003651 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003652 dt.sccp_conn_id := rx_c_ind.connectionId;
3653 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
Philipp Maierf45824a2019-08-14 14:44:10 +02003654 }
3655 [] BSSAP.receive {
3656 setverdict(fail, "Received unexpected message on A-Interface!");
3657 }
3658 [] T.timeout {
3659 setverdict(fail, "Received nothing on A-Interface!");
3660 }
3661 }
3662
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003663 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003664 f_shutdown_helper();
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003665}
3666
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003667/* Verify BSC can schedule N paging requests under one minute if BTS buffer is good enough */
3668function f_TC_paging_Nreq(integer num_subscribers, boolean send_pag_load_ind) runs on test_CT {
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003669 var ASP_RSL_Unitdata rx_rsl_ud;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003670 var Hexstrings imsis := {};
3671 var Booleans rx_paging_done := {};
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003672 var integer rx_paging_num := 0;
3673 var integer i;
3674 timer T_rx := 60.0;
3675 timer T_load_ind := 1.0;
3676
3677 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003678 imsis := imsis & {f_gen_imsi(i)};
3679 rx_paging_done := rx_paging_done & { false };
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003680 }
3681
3682 f_init(1, guard_timeout := 100.0);
3683
3684 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003685 IPA_RSL[0][0].clear;
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003686 if (send_pag_load_ind) {
3687 /* Tell there's plenty of space at the BTS (UINT16_MAX): */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003688 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(65535));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003689 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003690
3691 for (i := 0; i < num_subscribers; i := i + 1) {
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003692 /* Page on LAC-CI of BTS0: */
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003693 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 +02003694 ts_BSSMAP_Paging(imsis[i], valueof(ts_BSSMAP_CIL_LAC_CI({ts_BSSMAP_CI_LAC_CI(1, 0)})),
3695 omit, omit)));
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003696 }
3697
3698 T_rx.start;
3699 T_load_ind.start;
3700 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003701 [] 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 +02003702 var hexstring imsi := rx_rsl_ud.rsl.ies[2].body.ms_identity.mobileIdentityV.oddEvenInd_identity.imsi.digits;
3703 var hexstring imsi_suffix := substr(imsi, lengthof(imsi)-6, 6);
3704 var charstring imsi_str := hex2str(imsi_suffix);
3705 var integer imsi_idx := str2int(imsi_str);
3706 if (rx_paging_done[imsi_idx] == false) {
3707 rx_paging_done[imsi_idx] := true;
3708 rx_paging_num := rx_paging_num + 1;
Pau Espin Pedrolef7ef632022-04-25 13:34:57 +02003709 } else {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003710 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 +02003711 mtc.stop;
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003712 }
3713 if (rx_paging_num < num_subscribers) {
3714 repeat;
3715 }
3716 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003717 [] IPA_RSL[0][0].receive { repeat; }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003718 [] T_load_ind.timeout {
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003719 log("[CCH Load Ind timer] received paging requests so far: ", rx_paging_num);
3720 if (send_pag_load_ind) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003721 f_ipa_tx(ts_RSL_PAGING_LOAD_IND(40));
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003722 }
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003723 T_load_ind.start;
3724 repeat;
3725 }
3726 [] T_rx.timeout {
3727 setverdict(fail, "Timeout expecting paging requests, so far ", rx_paging_num);
3728 mtc.stop;
3729 }
3730 }
3731
Pau Espin Pedrold3339a72022-05-03 11:59:15 +02003732 /* Drop OML connection to have all paging requests flushed: */
3733 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
3734
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003735 f_shutdown_helper();
3736}
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +02003737/* Verify BSC can schedule 500 paging requests under one minute if BTS buffer is good enough */
3738testcase TC_paging_500req() runs on test_CT {
3739 f_TC_paging_Nreq(500, true);
3740}
3741/* Same as TC_paging_500req, but without sending CCCH Load Indication, which
3742 * means BTS is always under CCH Load Threshold, aka capable of sending tons of requests.
3743 * Since No CCCH Load Ind, BSC uses a conservative estimation of BTS load, which
3744 * for current config yields ~8req/sec, so 480req/min maximum. */
3745testcase TC_paging_450req_no_paging_load_ind() runs on test_CT {
3746 f_TC_paging_Nreq(450, false);
3747}
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +02003748
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003749/* Test RSL link drop causes counter increment */
3750testcase TC_rsl_drop_counter() runs on test_CT {
3751 var integer rsl_fail;
3752
Harald Welte89d42e82017-12-17 16:42:41 +01003753 f_init(1);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003754
3755 rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
3756
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003757 f_ipa_rsl_stop(bts[0][0].rsl);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003758
3759 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
3760
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003761 f_shutdown_helper();
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003762}
3763
3764/* TODO: Test OML link drop causes counter increment */
3765
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003766/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
3767function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003768 var IPA_Client client;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003769 timer T := 10.0;
3770
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003771 client.id := "IPA-BTS0-TRX0-RSL";
3772 client.vc_IPA := IPA_Emulation_CT.create(client.id & "-IPA") alive;
3773 client.ccm_pars := c_IPA_default_ccm_pars;
3774 client.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
3775 client.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003776
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01003777 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003778
3779 f_init_mgcp("VirtMSC");
3780
3781 /* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003782 map(client.vc_IPA:IPA_PORT, system:IPA);
3783 connect(client.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0][0]);
3784 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 +01003785
3786 /* wait for IPA OML link to connect and then disconnect */
3787 T.start;
3788 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003789 [] IPA_RSL[0][0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003790 T.stop;
3791 return true;
3792 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003793 [] IPA_RSL[0][0].receive { repeat }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003794 [] T.timeout {
Daniel Willmannafce8662018-07-06 23:11:32 +02003795 return false;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003796 }
3797 }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003798 return false;
3799}
3800
3801/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3802testcase TC_rsl_unknown_unit_id() runs on test_CT {
3803 if (f_ipa_unknown_unit_id(mp_bsc_rsl_port)) {
3804 setverdict(pass);
3805 } else {
3806 setverdict(fail, "Timeout RSL waiting for connection to close");
3807 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003808 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003809}
3810
3811
3812/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3813testcase TC_oml_unknown_unit_id() runs on test_CT {
3814 if (f_ipa_unknown_unit_id(mp_bsc_oml_port)) {
3815 setverdict(pass);
3816 } else {
3817 setverdict(fail, "Timeout OML waiting for connection to close");
3818 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003819 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003820}
3821
3822
Harald Weltec1a2fff2017-12-17 11:06:19 +01003823/***********************************************************************
Harald Welte6811d102019-04-14 22:23:14 +02003824 * "New world" test cases using RSL_Emulation + RAN_Emulation
Harald Weltec1a2fff2017-12-17 11:06:19 +01003825 ***********************************************************************/
3826
Harald Welte6811d102019-04-14 22:23:14 +02003827import from RAN_Emulation all;
Harald Welte47cd0e32020-08-21 12:39:11 +02003828import from BSSAP_LE_Emulation all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01003829import from RSL_Emulation all;
3830import from MSC_ConnectionHandler all;
3831
3832type function void_fn(charstring id) runs on MSC_ConnHdlr;
3833
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003834/* helper function to create and connect a MSC_ConnHdlr component
3835 * TODO: allow connecting to TRX1..N, not only TRX0 */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003836private function f_connect_handler(inout MSC_ConnHdlr vc_conn, integer bssap_idx := 0) runs on test_CT {
3837 connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
Daniel Willmann191e0d92018-01-17 12:44:35 +01003838 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003839 connect(vc_conn:RSL, bts[0][0].rsl.vc_RSL:CLIENT_PT);
3840 connect(vc_conn:RSL_PROC, bts[0][0].rsl.vc_RSL:RSL_PROC);
3841 if (isvalue(bts[1][0])) {
3842 connect(vc_conn:RSL1, bts[1][0].rsl.vc_RSL:CLIENT_PT);
3843 connect(vc_conn:RSL1_PROC, bts[1][0].rsl.vc_RSL:RSL_PROC);
Philipp Maier956a92f2018-02-16 10:58:07 +01003844 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06003845 if (isvalue(bts[2][0])) {
3846 connect(vc_conn:RSL2, bts[2][0].rsl.vc_RSL:CLIENT_PT);
3847 connect(vc_conn:RSL2_PROC, bts[2][0].rsl.vc_RSL:RSL_PROC);
Neels Hofmeyr91401012019-07-11 00:42:35 +02003848 }
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003849 connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02003850 if (mp_enable_lcs_tests) {
3851 connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
3852 connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
3853 }
Daniel Willmann191e0d92018-01-17 12:44:35 +01003854 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02003855 connect(vc_conn:MGCP_MULTI, vc_MGCP:MGCP_CLIENT_MULTI);
Daniel Willmannebdecc02020-08-12 15:30:17 +02003856 connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
Harald Welte336820c2018-05-31 20:34:52 +02003857}
3858
Neels Hofmeyrda436782021-07-20 22:09:06 +02003859function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
Harald Welte336820c2018-05-31 20:34:52 +02003860runs on test_CT return MSC_ConnHdlr {
3861 var charstring id := testcasename();
3862 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003863 var integer bssap_idx := 0;
3864 if (isvalue(pars)) {
3865 bssap_idx := valueof(pars).mscpool.bssap_idx;
3866 }
Harald Welte336820c2018-05-31 20:34:52 +02003867 vc_conn := MSC_ConnHdlr.create(id);
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003868 f_connect_handler(vc_conn, bssap_idx);
Neels Hofmeyrda436782021-07-20 22:09:06 +02003869 return vc_conn;
3870}
3871
3872function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
3873runs on test_CT return MSC_ConnHdlr {
3874 var charstring id := testcasename();
Harald Weltea0630032018-03-20 21:09:55 +01003875 vc_conn.start(f_handler_init(fn, id, pars));
Harald Weltec1a2fff2017-12-17 11:06:19 +01003876 return vc_conn;
3877}
3878
Neels Hofmeyrda436782021-07-20 22:09:06 +02003879function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
3880runs on test_CT return MSC_ConnHdlr {
3881 return f_start_handler_run(f_start_handler_create(pars), fn, pars);
3882}
3883
Harald Weltea0630032018-03-20 21:09:55 +01003884/* first function inside ConnHdlr component; sets g_pars + starts function */
3885private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
3886runs on MSC_ConnHdlr {
3887 if (isvalue(pars)) {
3888 g_pars := valueof(pars);
3889 }
3890 fn.apply(id);
3891}
3892
Oliver Smith26a3db72021-07-09 13:51:29 +02003893private function f_vty_encryption_a5(charstring options) runs on test_CT {
3894 f_vty_transceive(BSCVTY, "configure terminal");
3895 f_vty_transceive(BSCVTY, "network");
3896 f_vty_transceive(BSCVTY, "encryption a5 " & options);
3897 f_vty_transceive(BSCVTY, "exit");
3898 f_vty_transceive(BSCVTY, "exit");
3899}
3900
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01003901const charstring VTY_A5_DEFAULT := "0 1 3";
3902
Oliver Smith26a3db72021-07-09 13:51:29 +02003903private function f_vty_encryption_a5_reset() runs on test_CT {
3904 /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01003905 f_vty_encryption_a5(VTY_A5_DEFAULT);
Oliver Smith26a3db72021-07-09 13:51:29 +02003906}
3907
Harald Welte3c86ea02018-05-10 22:28:05 +02003908/* Establish signalling channel (non-assignment case) followed by cipher mode */
3909private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02003910 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
3911 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte3c86ea02018-05-10 22:28:05 +02003912 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Philipp Maier23000732018-05-18 11:25:37 +02003913 ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode := omit;
3914 ass_cmd.pdu.bssmap.assignmentRequest.aoIPTransportLayer := omit;
3915 exp_compl.pdu.bssmap.assignmentComplete.circuitIdentityCode := omit;
3916 exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
Harald Welte3c86ea02018-05-10 22:28:05 +02003917
Philipp Maier23000732018-05-18 11:25:37 +02003918 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003919 f_perform_clear();
Harald Welte3c86ea02018-05-10 22:28:05 +02003920}
3921testcase TC_ciph_mode_a5_0() runs on test_CT {
3922 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003923 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02003924 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
3925
3926 f_init(1, true);
3927 f_sleep(1.0);
3928 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3929 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003930 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02003931}
3932testcase TC_ciph_mode_a5_1() runs on test_CT {
3933 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003934 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02003935 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
3936
3937 f_init(1, true);
3938 f_sleep(1.0);
3939 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3940 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003941 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02003942}
Oliver Smith50b98122021-07-09 15:00:28 +02003943/* OS#4975: verify that A5/2 is preferred over A5/0 */
3944testcase TC_ciph_mode_a5_2_0() runs on test_CT {
3945 var MSC_ConnHdlr vc_conn;
3946 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3947
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01003948 pars.encr := f_encr_params('05'O, '04'O); /* A5/0 and A5/2 (0x01|0x04)*/
Oliver Smith50b98122021-07-09 15:00:28 +02003949
3950 f_init(1, true);
3951 f_vty_encryption_a5("0 1 2 3");
3952 f_sleep(1.0);
3953 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3954 vc_conn.done;
3955 f_vty_encryption_a5_reset();
3956 f_shutdown_helper();
3957}
Oliver Smith1dff88d2021-07-09 08:45:51 +02003958/* OS#4975: verify that A5/1 is preferred over A5/2 */
3959testcase TC_ciph_mode_a5_2_1() runs on test_CT {
3960 var MSC_ConnHdlr vc_conn;
3961 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3962
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01003963 pars.encr := f_encr_params('06'O, '02'O); /* A5/1 and A5/2 (0x02|0x04)*/
Oliver Smith1dff88d2021-07-09 08:45:51 +02003964
3965 f_init(1, true);
3966 f_vty_encryption_a5("1 2");
3967 f_sleep(1.0);
3968 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3969 vc_conn.done;
3970 f_vty_encryption_a5_reset();
3971 f_shutdown_helper();
3972}
Harald Welte3c86ea02018-05-10 22:28:05 +02003973testcase TC_ciph_mode_a5_3() runs on test_CT {
3974 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003975 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02003976 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
3977
3978 f_init(1, true);
3979 f_sleep(1.0);
3980 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3981 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003982 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02003983}
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003984/* Establish a Signalling channel with A5/4 encryption. */
3985testcase TC_ciph_mode_a5_4() runs on test_CT {
3986 var MSC_ConnHdlr vc_conn;
3987 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3988 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Harald Welte3c86ea02018-05-10 22:28:05 +02003989
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003990 f_init(1, true);
Oliver Smith26a3db72021-07-09 13:51:29 +02003991 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003992 f_sleep(1.0);
3993 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3994 vc_conn.done;
Oliver Smith26a3db72021-07-09 13:51:29 +02003995 f_vty_encryption_a5_reset();
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003996 f_shutdown_helper();
3997}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02003998/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
3999private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
4000 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4001 var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
4002 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4003 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4004
4005 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004006 f_perform_clear();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004007}
4008testcase TC_assignment_aoip_tla_v6() runs on test_CT {
4009 var MSC_ConnHdlr vc_conn;
4010 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4011
4012 f_init(1, true);
4013 f_sleep(1.0);
4014 vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
4015 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004016 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02004017}
4018
Harald Welte3c86ea02018-05-10 22:28:05 +02004019
4020/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
Harald Welte651fcdc2018-05-10 20:23:16 +02004021private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02004022 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4023 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004024
Harald Welte552620d2017-12-16 23:21:36 +01004025 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4026 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte73cd2712017-12-17 00:44:52 +01004027
Harald Weltea0630032018-03-20 21:09:55 +01004028 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004029 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004030}
Harald Welte552620d2017-12-16 23:21:36 +01004031testcase TC_assignment_fr_a5_0() runs on test_CT {
4032 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004033 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004034 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
Harald Welte552620d2017-12-16 23:21:36 +01004035
Harald Welte89d42e82017-12-17 16:42:41 +01004036 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004037 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004038 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004039 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004040 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004041}
Harald Welte552620d2017-12-16 23:21:36 +01004042testcase TC_assignment_fr_a5_1() runs on test_CT {
Harald Weltec1a2fff2017-12-17 11:06:19 +01004043 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004044 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004045 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004046
Harald Welte89d42e82017-12-17 16:42:41 +01004047 f_init(1, true);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004048 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02004049 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4050 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004051 f_shutdown_helper();
Harald Welte651fcdc2018-05-10 20:23:16 +02004052}
4053testcase TC_assignment_fr_a5_3() runs on test_CT {
4054 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02004055 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02004056 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01004057
Harald Welte651fcdc2018-05-10 20:23:16 +02004058 f_init(1, true);
4059 f_sleep(1.0);
4060 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Weltec1a2fff2017-12-17 11:06:19 +01004061 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004062 f_shutdown_helper();
Harald Weltec1a2fff2017-12-17 11:06:19 +01004063}
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004064/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
4065testcase TC_assignment_fr_a5_4() runs on test_CT {
4066 var MSC_ConnHdlr vc_conn;
4067 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4068 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
4069
4070 f_init(1, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02004071 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004072 f_sleep(1.0);
4073 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
4074 vc_conn.done;
Oliver Smith7eabd312021-07-12 14:18:56 +02004075 f_vty_encryption_a5_reset();
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02004076 f_shutdown_helper();
4077}
Harald Weltec1a2fff2017-12-17 11:06:19 +01004078
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +02004079/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
4080testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
4081 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4082 var MSC_ConnHdlr vc_conn;
4083
4084 f_init(1, true);
4085 f_sleep(1.0);
4086
4087 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
4088 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
4089 vc_conn.done;
4090 f_shutdown_helper();
4091}
4092
Harald Welte552620d2017-12-16 23:21:36 +01004093/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
4094private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004095 g_pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004096 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02004097 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004098
4099 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02004100 /* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
4101
Harald Weltea0630032018-03-20 21:09:55 +01004102 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004103 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004104}
Harald Welte552620d2017-12-16 23:21:36 +01004105testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
4106 var MSC_ConnHdlr vc_conn;
4107
Harald Welte89d42e82017-12-17 16:42:41 +01004108 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004109 f_sleep(1.0);
4110
Harald Welte8863fa12018-05-10 20:15:27 +02004111 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
Harald Welte552620d2017-12-16 23:21:36 +01004112 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004113 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004114}
4115
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004116private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
4117 var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
4118 var PDU_BSSAP exp_ass_req := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01004119
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004120 exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4121 exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4122
4123 /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
4124
4125 var BSSMAP_FIELD_CodecType codecType;
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004126
4127 codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
4128 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
4129
4130 f_create_chan_and_exp();
4131 /* we should now have a COMPL_L3 at the MSC */
4132
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004133 /* Start ciphering, expect Cipher Mode Reject */
Neels Hofmeyr6c388f22021-06-11 02:36:56 +02004134 f_cipher_mode(g_pars.encr, exp_fail := true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004135 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01004136}
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004137testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
4138 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01004139 var MSC_ConnHdlr vc_conn;
4140
Harald Welte89d42e82017-12-17 16:42:41 +01004141 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01004142 f_sleep(1.0);
4143
Neels Hofmeyr0588cad2021-06-11 01:38:18 +02004144 pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02004145 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
Harald Welte552620d2017-12-16 23:21:36 +01004146 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004147 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01004148}
4149
4150
Harald Welte4532e0a2017-12-23 02:05:44 +01004151private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02004152 g_pars := f_gen_test_hdlr_pars();
Harald Welte4532e0a2017-12-23 02:05:44 +01004153 var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
Philipp Maier48604732018-10-09 15:00:37 +02004154 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte4532e0a2017-12-23 02:05:44 +01004155 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004156
4157 f_statsd_reset();
Harald Weltea0630032018-03-20 21:09:55 +01004158 f_establish_fully(ass_cmd, exp_compl);
Daniel Willmannebdecc02020-08-12 15:30:17 +02004159
4160 var StatsDExpects expect := {
Daniel Willmannc5398f72020-09-21 10:41:35 +02004161 { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
4162 { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
Daniel Willmannebdecc02020-08-12 15:30:17 +02004163 { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
4164 { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
4165 };
4166 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004167 f_perform_clear();
Harald Welte4532e0a2017-12-23 02:05:44 +01004168}
4169
4170testcase TC_assignment_sign() runs on test_CT {
4171 var MSC_ConnHdlr vc_conn;
4172
4173 f_init(1, true);
4174 f_sleep(1.0);
4175
Harald Welte8863fa12018-05-10 20:15:27 +02004176 vc_conn := f_start_handler(refers(f_tc_assignment_sign));
Harald Welte4532e0a2017-12-23 02:05:44 +01004177 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004178 f_shutdown_helper();
Harald Welte4532e0a2017-12-23 02:05:44 +01004179}
4180
Harald Welte60aa5762018-03-21 19:33:13 +01004181/***********************************************************************
4182 * Codec (list) testing
4183 ***********************************************************************/
4184
4185/* check if the given rsl_mode is compatible with the a_elem */
4186private function f_match_codec(BSSMAP_FIELD_CodecElement a_elem, RSL_IE_ChannelMode rsl_mode)
4187return boolean {
4188 select (a_elem.codecType) {
4189 case (GSM_FR) {
4190 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1))) {
4191 return true;
4192 }
4193 }
4194 case (GSM_HR) {
4195 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1))) {
4196 return true;
4197 }
4198 }
4199 case (GSM_EFR) {
4200 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2))) {
4201 return true;
4202 }
4203 }
4204 case (FR_AMR) {
4205 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3))) {
4206 return true;
4207 }
4208 }
4209 case (HR_AMR) {
4210 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3))) {
4211 return true;
4212 }
4213 }
4214 case else { }
4215 }
4216 return false;
4217}
4218
4219/* check if the given rsl_mode is compatible with the a_list */
4220private function f_match_codecs(BSSMAP_IE_SpeechCodecList a_list, RSL_IE_ChannelMode rsl_mode)
4221return boolean {
4222 for (var integer i := 0; i < sizeof(a_list); i := i+1) {
4223 if (f_match_codec(a_list.codecElements[i], rsl_mode)) {
4224 return true;
4225 }
4226 }
4227 return false;
4228}
4229
4230/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
Philipp Maier61f6b572018-07-06 14:03:38 +02004231function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
Harald Welte60aa5762018-03-21 19:33:13 +01004232return BSSMAP_IE_ChannelType {
4233 /* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
4234 var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
4235 select (a_elem.codecType) {
4236 case (GSM_FR) {
4237 ret.channelRateAndType := ChRate_TCHF;
4238 ret.speechId_DataIndicator := Spdi_TCHF_FR;
4239 }
4240 case (GSM_HR) {
4241 ret.channelRateAndType := ChRate_TCHH;
4242 ret.speechId_DataIndicator := Spdi_TCHH_HR;
4243 }
4244 case (GSM_EFR) {
4245 ret.channelRateAndType := ChRate_TCHF;
4246 ret.speechId_DataIndicator := Spdi_TCHF_EFR;
4247 }
4248 case (FR_AMR) {
4249 ret.channelRateAndType := ChRate_TCHF;
4250 ret.speechId_DataIndicator := Spdi_TCHF_AMR;
4251 }
4252 case (HR_AMR) {
4253 ret.channelRateAndType := ChRate_TCHH;
4254 ret.speechId_DataIndicator := Spdi_TCHH_AMR;
4255 }
4256 case else {
4257 setverdict(fail, "Unsupported codec ", a_elem);
Daniel Willmannafce8662018-07-06 23:11:32 +02004258 mtc.stop;
Harald Welte60aa5762018-03-21 19:33:13 +01004259 }
4260 }
4261 return ret;
4262}
4263
Harald Weltea63b9102018-03-22 20:36:16 +01004264private function f_rsl_chmod_tmpl_from_codec(BSSMAP_FIELD_CodecElement a_elem)
4265return template RSL_IE_Body {
4266 var template RSL_IE_Body mode_ie := {
4267 chan_mode := {
4268 len := ?,
4269 reserved := ?,
4270 dtx_d := ?,
4271 dtx_u := ?,
4272 spd_ind := RSL_SPDI_SPEECH,
4273 ch_rate_type := -,
4274 coding_alg_rate := -
4275 }
4276 }
4277
4278 select (a_elem.codecType) {
4279 case (GSM_FR) {
4280 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
4281 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM1;
4282 }
4283 case (GSM_HR) {
4284 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
4285 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM1;
4286 }
4287 case (GSM_EFR) {
4288 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
4289 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM2;
4290 }
4291 case (FR_AMR) {
4292 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
4293 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM3;
4294 }
4295 case (HR_AMR) {
4296 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
4297 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM3;
4298 }
4299 }
4300 return mode_ie;
4301}
4302
Harald Welte60aa5762018-03-21 19:33:13 +01004303type record CodecListTest {
4304 BSSMAP_IE_SpeechCodecList codec_list,
4305 charstring id
4306}
4307type record of CodecListTest CodecListTests
4308
4309private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004310 f_assignment_codec(id);
4311}
4312
4313private function f_assignment_codec(charstring id, boolean do_perform_clear := true) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02004314 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02004315 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Harald Welte60aa5762018-03-21 19:33:13 +01004316
4317 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004318 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte79f3f542018-05-25 20:02:37 +02004319 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4320 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
4321 g_pars.ass_codec_list.codecElements[0];
Philipp Maierd0e64b02019-03-13 14:15:23 +01004322 if (isvalue(g_pars.expect_mr_s0_s7)) {
4323 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
4324 g_pars.expect_mr_s0_s7;
4325 }
Harald Welte79f3f542018-05-25 20:02:37 +02004326 }
Harald Welte60aa5762018-03-21 19:33:13 +01004327 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4328 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
Harald Welte60aa5762018-03-21 19:33:13 +01004329 log("expecting ASS COMPL like this: ", exp_compl);
4330
4331 f_establish_fully(ass_cmd, exp_compl);
Harald Weltea63b9102018-03-22 20:36:16 +01004332
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004333 if (not g_pars.expect_channel_mode_modify) {
4334 /* Verify that the RSL-side activation actually matches our expectations */
4335 var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
Harald Weltea63b9102018-03-22 20:36:16 +01004336
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004337 var RSL_IE_Body mode_ie;
4338 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
4339 setverdict(fail, "Couldn't find CHAN_MODE IE");
Daniel Willmannafce8662018-07-06 23:11:32 +02004340 mtc.stop;
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004341 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004342 var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
4343 if (not match(mode_ie, t_mode_ie)) {
4344 log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
4345 setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004346 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004347
4348 var RSL_IE_Body mr_conf;
4349 if (g_pars.expect_mr_conf_ie != omit) {
4350 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
4351 setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
4352 mtc.stop;
4353 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004354 log("found RSL MR CONFIG IE: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004355
4356 if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
Vadim Yanitskiy8b189372022-09-14 17:31:17 +07004357 setverdict(fail, "RSL MR CONFIG IE does not match expectation. ",
4358 "Expected: ", g_pars.expect_mr_conf_ie, ", got: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004359 }
4360 } else {
4361 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
4362 log("found RSL MR CONFIG IE: ", mr_conf);
4363 setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
4364 mtc.stop;
4365 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004366 }
4367 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004368
4369 if (do_perform_clear) {
4370 f_perform_clear();
4371 }
Harald Welte60aa5762018-03-21 19:33:13 +01004372}
4373
Philipp Maierd0e64b02019-03-13 14:15:23 +01004374private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
4375
4376 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4377 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4378
4379 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004380 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maierd0e64b02019-03-13 14:15:23 +01004381 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4382 }
4383 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4384 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
4385 log("expecting ASS FAIL like this: ", exp_fail);
4386
4387 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004388 f_perform_clear();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004389}
4390
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004391const CounterNameVals counternames_bsc_bts_assignment := {
4392 { "assignment:attempted", 0 },
4393 { "assignment:completed", 0 },
4394 { "assignment:stopped", 0 },
4395 { "assignment:no_channel", 0 },
4396 { "assignment:timeout", 0 },
4397 { "assignment:failed", 0 },
4398 { "assignment:error", 0 }
4399};
4400
4401const CounterNameVals counternames_bts_assignment := {
4402 { "assignment:attempted_sign", 0 },
4403 { "assignment:attempted_speech", 0 },
4404 { "assignment:completed_sign", 0 },
4405 { "assignment:completed_speech", 0 },
4406 { "assignment:stopped_sign", 0 },
4407 { "assignment:stopped_speech", 0 },
4408 { "assignment:no_channel_sign", 0 },
4409 { "assignment:no_channel_speech", 0 },
4410 { "assignment:timeout_sign", 0 },
4411 { "assignment:timeout_speech", 0 },
4412 { "assignment:failed_sign", 0 },
4413 { "assignment:failed_speech", 0 },
4414 { "assignment:error_sign", 0 },
4415 { "assignment:error_speech", 0 }
4416};
4417
4418function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
4419 var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
4420 f_ctrs_bts_init(bts_count, bts_names);
4421 f_ctrs_bsc_init(counternames_bsc_bts_assignment);
4422}
4423
Harald Welte60aa5762018-03-21 19:33:13 +01004424testcase TC_assignment_codec_fr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004425 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004426 var MSC_ConnHdlr vc_conn;
4427
4428 f_init(1, true);
4429 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004430 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004431
4432 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004433 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004434 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004435
4436 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4437 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4438 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4439 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4440 f_ctrs_bts_verify();
4441
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004442 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004443}
4444
4445testcase TC_assignment_codec_hr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004446 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004447 var MSC_ConnHdlr vc_conn;
4448
4449 f_init(1, true);
4450 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004451 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004452
4453 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004454 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004455 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004456
4457 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4458 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4459 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4460 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4461 f_ctrs_bts_verify();
4462
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004463 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004464}
4465
4466testcase TC_assignment_codec_efr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004467 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004468 var MSC_ConnHdlr vc_conn;
4469
4470 f_init(1, true);
4471 f_sleep(1.0);
4472
4473 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004474 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004475 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004476 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004477}
4478
Philipp Maierd0e64b02019-03-13 14:15:23 +01004479/* Allow 5,90k only (current default config) */
4480private function f_allow_amr_rate_5_90k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004481 f_vty_cfg_msc(BSCVTY, 0, {
4482 "amr-config 12_2k forbidden",
4483 "amr-config 10_2k forbidden",
4484 "amr-config 7_95k forbidden",
4485 "amr-config 7_40k forbidden",
4486 "amr-config 6_70k forbidden",
4487 "amr-config 5_90k allowed",
4488 "amr-config 5_15k forbidden",
4489 "amr-config 4_75k forbidden"
4490 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004491}
4492
4493/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
4494 * ("Config-NB-Code = 1") */
4495private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004496 f_vty_cfg_msc(BSCVTY, 0, {
4497 "amr-config 12_2k allowed",
4498 "amr-config 10_2k forbidden",
4499 "amr-config 7_95k forbidden",
4500 "amr-config 7_40k allowed",
4501 "amr-config 6_70k forbidden",
4502 "amr-config 5_90k allowed",
4503 "amr-config 5_15k forbidden",
4504 "amr-config 4_75k allowed"
4505 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004506}
4507
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004508private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
4509 var charstring tch;
4510 if (fr) {
4511 tch := "tch-f";
4512 } else {
4513 tch := "tch-h";
4514 }
4515 f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
4516}
4517
4518/* Set the AMR start-mode for this TCH back to the default configuration. */
4519private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
4520 f_vty_amr_start_mode_set(fr, "auto");
4521}
4522
Harald Welte60aa5762018-03-21 19:33:13 +01004523testcase TC_assignment_codec_amr_f() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004524 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004525 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004526
4527 /* Note: This setups the codec configuration. The parameter payload in
4528 * mr_conf must be consistant with the parameter codecElements in pars
4529 * and also must match the amr-config in osmo-bsc.cfg! */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004530 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004531 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004532 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004533 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004534
Harald Welte60aa5762018-03-21 19:33:13 +01004535 f_init(1, true);
4536 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004537 f_vty_amr_start_mode_set(true, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004538 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004539
Harald Welte8863fa12018-05-10 20:15:27 +02004540 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004541 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004542
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004543 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4544 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4545 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4546 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4547 f_ctrs_bts_verify();
4548
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004549 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004550 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004551}
4552
4553testcase TC_assignment_codec_amr_h() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004554 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004555 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004556
4557 /* See note above */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004558 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004559 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004560 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07004561 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004562
Harald Welte60aa5762018-03-21 19:33:13 +01004563 f_init(1, true);
4564 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004565 f_vty_amr_start_mode_set(false, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004566 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004567
Harald Welte8863fa12018-05-10 20:15:27 +02004568 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004569 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004570
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004571 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4572 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4573 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4574 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4575 f_ctrs_bts_verify();
4576
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004577 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004578 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004579}
4580
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004581/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
4582testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
4583 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4584 var MSC_ConnHdlr vc_conn;
4585
4586 f_init(1, true);
4587 f_sleep(1.0);
4588
4589 /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
4590 * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
4591 * expecting a Channel Mode Modify if the channel type is compatible. */
4592 f_disable_all_sdcch();
4593 f_disable_all_tch_h();
4594
4595 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4596 pars.expect_channel_mode_modify := true;
4597 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4598 vc_conn.done;
4599
4600 f_enable_all_sdcch();
4601 f_enable_all_tch();
4602 f_shutdown_helper();
4603}
4604
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004605/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
4606testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
4607 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4608 var MSC_ConnHdlr vc_conn;
4609
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004610 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4611 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
4612 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
Vadim Yanitskiy36fe9582022-09-14 15:25:04 +07004613 pars.expect_mr_conf_ie := c_mr_conf_5_90;
4614 pars.expect_mr_conf_ie.multirate_cfg.icmi := false; /* expect ICMI=0, smod=00: */
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004615
4616 f_init(1, true);
4617 f_sleep(1.0);
4618
4619 /* First set nonzero start mode bits */
4620 f_vty_amr_start_mode_set(true, "4");
4621 /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
4622 * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
4623 * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
4624 f_vty_amr_start_mode_set(true, "auto");
4625
4626 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4627 vc_conn.done;
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004628
4629 /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
4630 f_vty_amr_start_mode_set(true, "1");
4631 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004632 f_shutdown_helper();
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004633}
4634
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004635function f_TC_assignment_codec_amr(boolean fr, RSL_IE_MultirateCfg mr_cfg,
4636 bitstring s8_s0, bitstring exp_s8_s0,
4637 charstring start_mode := "1")
Philipp Maierd0e64b02019-03-13 14:15:23 +01004638runs on test_CT {
4639
4640 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4641 var MSC_ConnHdlr vc_conn;
4642
Philipp Maierd0e64b02019-03-13 14:15:23 +01004643 if (fr) {
4644 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4645 } else {
4646 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4647 }
4648 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4649 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004650 pars.expect_mr_conf_ie := { multirate_cfg := mr_cfg };
Philipp Maierd0e64b02019-03-13 14:15:23 +01004651 pars.expect_mr_s0_s7 := exp_s8_s0;
4652
4653 f_init(1, true);
4654 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004655 f_vty_amr_start_mode_set(fr, start_mode);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004656 f_sleep(1.0);
4657
4658 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4659 vc_conn.done;
4660 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004661 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004662}
4663
4664function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
4665runs on test_CT {
4666
4667 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4668 var MSC_ConnHdlr vc_conn;
4669
4670 if (fr) {
4671 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4672 } else {
4673 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4674 }
4675 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4676 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4677
4678 f_init(1, true);
4679 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004680 f_vty_amr_start_mode_set(fr, "1");
Philipp Maierd0e64b02019-03-13 14:15:23 +01004681 f_sleep(1.0);
4682
4683 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
4684 vc_conn.done;
4685 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004686 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004687}
4688
Philipp Maierd0e64b02019-03-13 14:15:23 +01004689/* Set S1, we expect an AMR multirate configuration IE with all four rates
4690 * set. */
4691testcase TC_assignment_codec_amr_f_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004692 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4693 params := '20882208'O));
4694 f_TC_assignment_codec_amr(true, mr_cfg, '00000011'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004695 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004696}
4697
4698/* Set S1, we expect an AMR multirate configuration IE with the lower three
4699 * rates set. */
4700testcase TC_assignment_codec_amr_h_S1() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004701 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4702 params := '208820'O));
4703 f_TC_assignment_codec_amr(false, mr_cfg, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004704 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004705}
4706
4707/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4708 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4709testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004710 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4711 params := '20882208'O));
4712 f_TC_assignment_codec_amr(true, mr_cfg, '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 {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004719 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4720 params := '208820'O));
4721 f_TC_assignment_codec_amr(false, mr_cfg, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004722 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004723}
4724
4725/* The following block of tests selects more and more rates until all four
4726 * possible rates are in the active set (full rate) */
4727testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004728 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4729 f_TC_assignment_codec_amr(true, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004730 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004731}
4732
4733testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004734 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4735 params := '2080'O));
4736 f_TC_assignment_codec_amr(true, mr_cfg, '00000101'B, '00000101'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_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004741 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4742 params := '208820'O));
4743 f_TC_assignment_codec_amr(true, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004744 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004745}
4746
4747testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004748 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4749 params := '20882208'O));
4750 f_TC_assignment_codec_amr(true, mr_cfg, '10010101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004751 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004752}
4753
4754/* The following block of tests selects more and more rates until all three
4755 * possible rates are in the active set (half rate) */
4756testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004757 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
4758 f_TC_assignment_codec_amr(false, mr_cfg, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004759 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004760}
4761
4762testcase TC_assignment_codec_amr_h_S02() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004763 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
4764 params := '2080'O));
4765 f_TC_assignment_codec_amr(false, mr_cfg, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004766 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004767}
4768
4769testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004770 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4771 params := '208820'O));
4772 f_TC_assignment_codec_amr(false, mr_cfg, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004773 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004774}
4775
4776/* The following block tests what happens when the MSC does offer rate
4777 * configurations that are not supported by the BSC. Normally such situations
4778 * should not happen because the MSC gets informed by the BSC in advance via
4779 * the L3 COMPLETE message which rates are applicable. The MSC should not try
4780 * to offer rates that are not applicable anyway. */
4781
4782testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004783 /* Try to include 12,2k in into the active set even though the channel
4784 * is half rate only. The BSC is expected to remove the 12,0k */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004785 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
4786 params := '208820'O));
4787 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'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_S01234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004792 /* See what happens when all rates are selected at once. Since then
4793 * Also S1 is selected, this setting will be prefered and we should
4794 * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004795 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4796 params := '20882208'O));
4797 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004798 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004799}
4800
4801testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004802 /* Same as above, but with S1 missing, the MSC is then expected to
4803 * select the currently supported rates, which are also 12.2k, 7,40k,
4804 * 5,90k, and 4,75k, into the active set. */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004805 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
4806 params := '20882208'O));
4807 f_TC_assignment_codec_amr(true, mr_cfg, '11111101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004808 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004809}
4810
4811testcase TC_assignment_codec_amr_f_zero() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004812 /* Try to select no rates at all */
4813 f_TC_assignment_codec_amr_fail(true, '00000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004814 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004815}
4816
4817testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004818 /* Try to select only unsupported rates */
4819 f_TC_assignment_codec_amr_fail(true, '01101000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004820 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004821}
4822
4823testcase TC_assignment_codec_amr_h_S7() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004824 /* Try to select 12,2k for half rate */
4825 f_TC_assignment_codec_amr_fail(false, '10000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004826 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004827}
4828
Neels Hofmeyr21863562020-11-26 00:34:33 +00004829testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004830 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4831 codec_modes := '10010101'B,
4832 params := '20882208'O));
4833 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004834 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004835}
4836
4837testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004838 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
4839 codec_modes := '00010101'B,
4840 params := '208820'O));
4841 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B,
Neels Hofmeyr21863562020-11-26 00:34:33 +00004842 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004843 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004844}
4845
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004846testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004847 /* "amr tch-f modes 0 2 4 7" => total 4 modes and start mode 4 => '11'B on the wire */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004848 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 3,
4849 codec_modes := '10010101'B,
4850 params := '20882208'O));
4851 f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004852 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004853}
4854
4855testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004856 /* "amr tch-h modes 0 2 4" => total 3 modes and start mode 4 => '10'B on the wire */
Vadim Yanitskiy3998c032022-09-14 17:19:44 +07004857 var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 2,
4858 codec_modes := '00010101'B,
4859 params := '208820'O));
4860 f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B, start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004861 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004862}
4863
Philipp Maierac09bfc2019-01-08 13:41:39 +01004864private function f_disable_all_tch_f() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004865 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 borken");
4866 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 borken");
4867 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 borken");
4868 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004869}
4870
4871private function f_disable_all_tch_h() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004872 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 borken");
4873 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004874}
4875
4876private function f_enable_all_tch() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004877 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 unused");
4878 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 unused");
4879 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 unused");
4880 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 unused");
4881 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 unused");
4882 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004883}
4884
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004885private function f_disable_all_sdcch() runs on test_CT {
4886 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
4887 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
4888 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
4889 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
4890}
4891
4892private function f_enable_all_sdcch() runs on test_CT {
4893 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
4894 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
4895 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
4896 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
4897}
4898
Philipp Maierac09bfc2019-01-08 13:41:39 +01004899/* Allow HR only */
4900private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs on MSC_ConnHdlr {
4901 g_pars := f_gen_test_hdlr_pars();
4902 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4903 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4904 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4905 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
4906 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
4907 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
4908 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004909 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004910}
4911
4912/* Allow FR only */
4913private function f_TC_assignment_codec_xr_exhausted_req_fr(charstring id) runs on MSC_ConnHdlr {
4914 g_pars := f_gen_test_hdlr_pars();
4915 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4916 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4917 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4918 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
4919 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
4920 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4921 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004922 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004923}
4924
4925/* Allow HR only (expect assignment failure) */
4926private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) runs on MSC_ConnHdlr {
4927 g_pars := f_gen_test_hdlr_pars();
4928 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4929 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4930 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4931 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
4932 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
4933 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
4934 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004935 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004936}
4937
4938/* Allow FR only (expect assignment failure) */
4939private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) runs on MSC_ConnHdlr {
4940 g_pars := f_gen_test_hdlr_pars();
4941 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4942 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4943 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4944 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
4945 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
4946 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4947 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004948 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004949}
4950
4951/* Allow FR and HR, but prefer FR */
4952private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
4953 g_pars := f_gen_test_hdlr_pars();
4954 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4955 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4956 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4957 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
4958 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
4959 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
4960 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
4961 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004962 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004963}
4964
4965/* Allow FR and HR, but prefer HR */
4966private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
4967 g_pars := f_gen_test_hdlr_pars();
4968 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4969 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4970 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4971 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
4972 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
4973 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
4974 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
4975 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004976 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004977}
4978
4979/* Allow FR and HR, but prefer FR */
4980private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
4981 g_pars := f_gen_test_hdlr_pars();
4982 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4983 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4984 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4985 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
4986 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
4987 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
4988 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
4989 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004990 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004991}
4992
4993/* Allow FR and HR, but prefer HR */
4994private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
4995 g_pars := f_gen_test_hdlr_pars();
4996 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4997 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4998 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4999 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5000 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5001 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5002 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5003 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005004 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005005}
5006
5007/* Request a HR channel while all FR channels are exhausted, this is expected
5008 * to work without conflicts */
5009testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
5010 var MSC_ConnHdlr vc_conn;
5011 f_init(1, true);
5012 f_sleep(1.0);
5013 f_enable_all_tch();
5014 f_disable_all_tch_f();
5015 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
5016 vc_conn.done;
5017 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005018 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005019}
5020
5021/* Request a FR channel while all FR channels are exhausted, this is expected
5022 * to fail. */
5023testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
5024 var MSC_ConnHdlr vc_conn;
5025 f_init(1, true);
5026 f_sleep(1.0);
5027 f_enable_all_tch();
5028 f_disable_all_tch_f();
5029 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
5030 vc_conn.done;
5031 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005032 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005033}
5034
5035/* Request a FR (prefered) or alternatively a HR channel while all FR channels
5036 * are exhausted, this is expected to be resolved by selecting a HR channel. */
5037testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
5038 var MSC_ConnHdlr vc_conn;
5039 f_init(1, true);
5040 f_sleep(1.0);
5041 f_enable_all_tch();
5042 f_disable_all_tch_f();
5043 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
5044 vc_conn.done;
5045 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005046 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005047}
5048
5049/* Request a HR (prefered) or alternatively a FR channel while all FR channels
5050 * are exhausted, this is expected to work without conflicts. */
5051testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
5052 var MSC_ConnHdlr vc_conn;
5053 f_init(1, true);
5054 f_sleep(1.0);
5055 f_enable_all_tch();
5056 f_disable_all_tch_f();
5057 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
5058 vc_conn.done;
5059 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005060 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005061}
5062
5063/* Request a FR channel while all HR channels are exhausted, this is expected
5064 * to work without conflicts */
5065testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
5066 var MSC_ConnHdlr vc_conn;
5067 f_init(1, true);
5068 f_sleep(1.0);
5069 f_enable_all_tch();
5070 f_disable_all_tch_h();
5071 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
5072 vc_conn.done;
5073 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005074 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005075}
5076
5077/* Request a HR channel while all HR channels are exhausted, this is expected
5078 * to fail. */
5079testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
5080 var MSC_ConnHdlr vc_conn;
5081 f_init(1, true);
5082 f_sleep(1.0);
5083 f_enable_all_tch();
5084 f_disable_all_tch_h();
5085 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
5086 vc_conn.done;
5087 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005088 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005089}
5090
5091/* Request a HR (prefered) or alternatively a FR channel while all HR channels
5092 * are exhausted, this is expected to be resolved by selecting a FR channel. */
5093testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
5094 var MSC_ConnHdlr vc_conn;
5095 f_init(1, true);
5096 f_sleep(1.0);
5097 f_enable_all_tch();
5098 f_disable_all_tch_h();
5099 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
5100 vc_conn.done;
5101 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005102 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005103}
5104
5105/* Request a FR (prefered) or alternatively a HR channel while all HR channels
5106 * are exhausted, this is expected to work without conflicts. */
5107testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
5108 var MSC_ConnHdlr vc_conn;
5109 f_init(1, true);
5110 f_sleep(1.0);
5111 f_enable_all_tch();
5112 f_disable_all_tch_h();
5113 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
5114 vc_conn.done;
5115 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005116 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005117}
5118
5119/* Allow FR and HR, but prefer HR */
5120private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
5121 g_pars := f_gen_test_hdlr_pars();
5122 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5123 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5124 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5125 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
5126 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
5127 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
5128 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
5129 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005130 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005131}
5132
5133/* Allow FR and HR, but prefer FR */
5134private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
5135 g_pars := f_gen_test_hdlr_pars();
5136 var PDU_BSSAP ass_cmd := f_gen_ass_req();
5137 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5138 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5139 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
5140 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
5141 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
5142 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
5143 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005144 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005145}
5146
5147/* Request a HR (prefered) or alternatively a FR channel, it is expected that
5148 * HR, which is the prefered type, is selected. */
5149testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
5150 var MSC_ConnHdlr vc_conn;
5151 f_init(1, true);
5152 f_sleep(1.0);
5153 f_enable_all_tch();
5154 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
5155 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005156 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005157}
5158
5159/* Request a FR (prefered) or alternatively a HR channel, it is expected that
5160 * FR, which is the prefered type, is selected. */
5161testcase TC_assignment_codec_req_fr_hr() runs on test_CT {
5162 var MSC_ConnHdlr vc_conn;
5163 f_init(1, true);
5164 f_sleep(1.0);
5165 f_enable_all_tch();
5166 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_fr_hr));
5167 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005168 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01005169}
5170
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005171/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
5172private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
5173 g_pars := f_gen_test_hdlr_pars();
5174 g_pars.ra := '02'O; /* RA containing reason=LU */
5175
5176 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5177 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5178 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5179 var template uint3_t tsc := ?;
5180
5181 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5182 f_create_bssmap_exp(l3_enc);
5183 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5184 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5185
5186 /* we should now have a COMPL_L3 at the MSC */
5187 timer T := 10.0;
5188 T.start;
5189 alt {
5190 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5191 [] T.timeout {
5192 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5193 }
5194 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005195
5196 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005197}
5198testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
5199 var MSC_ConnHdlr vc_conn;
5200 f_init(1, true);
5201 f_sleep(1.0);
5202 f_disable_all_sdcch();
5203 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
5204 vc_conn.done;
5205 f_enable_all_sdcch();
5206 f_shutdown_helper();
5207}
5208
5209/* Request a signalling channel with all SDCCH exhausted, it is
5210 expected that no TCH will be selected for signalling and assigment will fail
5211 because it's dictated by VTY config */
5212testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
5213 var RSL_Message rsl_unused, rsl_msg;
5214 var GsmRrMessage rr;
5215 f_init(1, false);
5216 f_sleep(1.0);
5217 f_vty_allow_tch_for_signalling(false, 0);
5218 f_disable_all_sdcch();
5219
5220 /* RA containing reason=LU */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005221 f_ipa_tx(ts_RSL_CHAN_RQD('02'O, 2342));
5222 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005223 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
5224 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
5225 setverdict(fail, "Expected reject");
5226 }
5227
5228 f_vty_allow_tch_for_signalling(true, 0);
5229 f_enable_all_sdcch();
5230 f_shutdown_helper();
5231}
5232
5233/* Request a voice channel with all SDCCH exhausted, it is
5234 * expected that TCH channel will be allocated since the VTY option is only
5235 * aimed at signalling requests */
5236private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
5237 g_pars := f_gen_test_hdlr_pars();
5238 g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
5239
5240 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5241 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5242 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5243 var template uint3_t tsc := ?;
5244
5245 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5246 f_create_bssmap_exp(l3_enc);
5247 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5248 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5249
5250 /* we should now have a COMPL_L3 at the MSC */
5251 timer T := 10.0;
5252 T.start;
5253 alt {
5254 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5255 [] T.timeout {
5256 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5257 }
5258 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005259 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005260}
5261testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
5262 var MSC_ConnHdlr vc_conn;
5263 f_init(1, true);
5264 f_sleep(1.0);
5265 f_vty_allow_tch_for_signalling(false, 0);
5266 f_disable_all_sdcch();
5267
5268 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
5269 vc_conn.done;
5270
5271 f_vty_allow_tch_for_signalling(true, 0);
5272 f_enable_all_sdcch();
5273 f_shutdown_helper();
5274}
5275
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005276/* Test Osmux setup BSC<->MSC */
5277testcase TC_assignment_osmux_cn() runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005278 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5279 var MSC_ConnHdlr vc_conn;
5280
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005281 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5282 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5283 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiyb9bf00f2022-09-14 15:35:37 +07005284 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +02005285 pars.use_osmux_cn := true;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005286
Pau Espin Pedrol9b941492022-08-08 18:26:17 +02005287 g_osmux_enabled_cn := true;
5288 f_init(1, true);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005289 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005290 f_vty_amr_start_mode_set(false, "1");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005291
5292 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5293 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005294
5295 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01005296 f_shutdown_helper();
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005297}
5298
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005299/* Test Osmux setup BTS<->BSC */
5300testcase TC_assignment_osmux_bts() runs on test_CT {
5301 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5302 var MSC_ConnHdlr vc_conn;
5303
5304 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5305 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5306 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005307 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005308 pars.use_osmux_bts := true;
5309
5310 g_osmux_enabled_bts := true;
5311 f_init(1, true);
5312 f_sleep(1.0);
5313 f_vty_amr_start_mode_set(false, "1");
5314
5315 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5316 vc_conn.done;
5317
5318 f_vty_amr_start_mode_restore(false);
5319 f_shutdown_helper();
5320}
5321
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +02005322/* Test non-AMR codecs still work fine as RTP when Osmux is enabled BTS<->BSC<->MSC */
5323testcase TC_assignment_codec_hr_osmux_on() runs on test_CT {
5324 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5325 var MSC_ConnHdlr vc_conn;
5326
5327 g_osmux_enabled_cn := true;
5328 g_osmux_enabled_bts := true;
5329 f_init(1, true);
5330 f_sleep(1.0);
5331 f_ctrs_bsc_and_bts_assignment_init(1);
5332
5333 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
5334 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5335 vc_conn.done;
5336
5337 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
5338 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
5339 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
5340 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
5341 f_ctrs_bts_verify();
5342
5343 f_shutdown_helper();
5344}
5345
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005346/* Test Osmux setup BTS<->BSC<->MSC */
5347testcase TC_assignment_osmux() runs on test_CT {
5348 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5349 var MSC_ConnHdlr vc_conn;
5350
5351 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5352 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5353 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
Vadim Yanitskiy59494702022-09-14 15:29:04 +07005354 pars.expect_mr_conf_ie := c_mr_conf_5_90;
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +02005355 pars.use_osmux_cn := true;
5356 pars.use_osmux_bts := true;
5357
5358 g_osmux_enabled_cn := true;
5359 g_osmux_enabled_bts := true;
5360 f_init(1, true);
5361 f_sleep(1.0);
5362 f_vty_amr_start_mode_set(false, "1");
5363
5364 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5365 vc_conn.done;
5366
5367 f_vty_amr_start_mode_restore(false);
5368 f_shutdown_helper();
5369}
5370
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005371/* test the procedure of the MSC requesting a Classmark Update:
5372 * a) BSSMAP Classmark Request should result in RR CLASSMARK ENQUIRY,
5373 * b) L3 RR CLASSMARK CHANGE should result in BSSMAP CLASSMARK UPDATE */
Harald Welte898113b2018-01-31 18:32:21 +01005374private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005375 g_pars := f_gen_test_hdlr_pars();
5376
Harald Weltea0630032018-03-20 21:09:55 +01005377 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005378 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005379
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005380 BSSAP.send(ts_BSSMAP_ClassmarkRequest);
5381 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
5382
Harald Welte898113b2018-01-31 18:32:21 +01005383 f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
5384 BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
5385 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005386
5387 f_perform_clear();
Harald Welte898113b2018-01-31 18:32:21 +01005388}
5389testcase TC_classmark() runs on test_CT {
5390 var MSC_ConnHdlr vc_conn;
5391 f_init(1, true);
5392 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005393 vc_conn := f_start_handler(refers(f_tc_classmark));
Harald Welte898113b2018-01-31 18:32:21 +01005394 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005395 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005396}
5397
Harald Welteeddf0e92020-06-21 19:42:15 +02005398/* Send a CommonID from the simulated MSC and verify that the information is used to
5399 * fill BSC-internal data structures (specifically, bsc_subscr associated with subscr_conn) */
5400private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
5401 g_pars := f_gen_test_hdlr_pars();
5402 f_MscConnHdlr_init_vty();
5403
5404 f_create_chan_and_exp();
5405 /* we should now have a COMPL_L3 at the MSC */
Harald Welteeddf0e92020-06-21 19:42:15 +02005406
5407 /* Send CommonID */
5408 BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
5409
5410 /* Use VTY to verify that the IMSI of the subscr_conn is set */
5411 var charstring regex := "*(IMSI: " & hex2str(g_pars.imsi) & ")*";
5412 f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
5413
5414 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005415
5416 f_perform_clear();
Harald Welteeddf0e92020-06-21 19:42:15 +02005417}
5418testcase TC_common_id() runs on test_CT {
5419 var MSC_ConnHdlr vc_conn;
5420 f_init(1, true);
5421 f_sleep(1.0);
5422 vc_conn := f_start_handler(refers(f_tc_common_id));
5423 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005424 f_shutdown_helper();
Harald Welteeddf0e92020-06-21 19:42:15 +02005425}
5426
Harald Weltee3bd6582018-01-31 22:51:25 +01005427private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005428 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005429 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005430 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005431
Harald Weltee3bd6582018-01-31 22:51:25 +01005432 /* send the single message we want to send */
5433 f_rsl_send_l3(l3);
5434}
5435
5436private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr {
5437 timer T := sec;
5438 var PDU_BSSAP bssap;
Harald Welte898113b2018-01-31 18:32:21 +01005439 T.start;
5440 alt {
Harald Weltee3bd6582018-01-31 22:51:25 +01005441 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap {
5442 setverdict(fail, "Unexpected BSSMAP ", bssap);
Daniel Willmannafce8662018-07-06 23:11:32 +02005443 mtc.stop;
Harald Welte898113b2018-01-31 18:32:21 +01005444 }
5445 [] T.timeout {
5446 setverdict(pass);
5447 }
5448 }
5449}
5450
Harald Weltee3bd6582018-01-31 22:51:25 +01005451/* unsolicited ASSIGNMENT FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5452private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
5453 f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
5454 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005455 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005456}
Harald Welte898113b2018-01-31 18:32:21 +01005457testcase TC_unsol_ass_fail() runs on test_CT {
5458 var MSC_ConnHdlr vc_conn;
5459 f_init(1, true);
5460 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005461 vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
Harald Welte898113b2018-01-31 18:32:21 +01005462 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005463 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005464}
Harald Welte552620d2017-12-16 23:21:36 +01005465
Harald Welteea99a002018-01-31 20:46:43 +01005466
5467/* unsolicited ASSIGNMENT COMPLETE (without ASSIGN) from MS shouldn't bring BSC down */
5468private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005469 f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
5470 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005471 f_perform_clear();
Harald Welteea99a002018-01-31 20:46:43 +01005472}
5473testcase TC_unsol_ass_compl() runs on test_CT {
5474 var MSC_ConnHdlr vc_conn;
5475 f_init(1, true);
5476 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005477 vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
Harald Welteea99a002018-01-31 20:46:43 +01005478 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005479 f_shutdown_helper();
Harald Welteea99a002018-01-31 20:46:43 +01005480}
5481
5482
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005483/* unsolicited HANDOVER FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5484private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005485 f_est_single_l3(ts_RRM_HandoverFailure('00'O));
5486 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005487 f_perform_clear();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005488}
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005489testcase TC_unsol_ho_fail() runs on test_CT {
5490 var MSC_ConnHdlr vc_conn;
5491 f_init(1, true);
5492 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005493 vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005494 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005495 f_shutdown_helper();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005496}
5497
5498
Harald Weltee3bd6582018-01-31 22:51:25 +01005499/* short message from MS should be ignored */
5500private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005501 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005502 f_create_chan_and_exp();
Harald Weltee3bd6582018-01-31 22:51:25 +01005503 /* we should now have a COMPL_L3 at the MSC */
Harald Weltee3bd6582018-01-31 22:51:25 +01005504
5505 /* send short message */
5506 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
5507 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005508 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005509}
5510testcase TC_err_82_short_msg() runs on test_CT {
5511 var MSC_ConnHdlr vc_conn;
5512 f_init(1, true);
5513 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005514 vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
Harald Weltee3bd6582018-01-31 22:51:25 +01005515 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005516 f_shutdown_helper();
Harald Weltee3bd6582018-01-31 22:51:25 +01005517}
5518
5519
Harald Weltee9e02e42018-01-31 23:36:25 +01005520/* 24.008 8.4 Unknown message must trigger RR STATUS */
5521private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
5522 f_est_single_l3(ts_RRM_UL_REL('00'O));
5523 timer T := 3.0
5524 alt {
5525 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
5526 setverdict(pass);
5527 }
5528 [] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
Harald Welte458fd372018-03-21 11:26:23 +01005529 [] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
Harald Weltee9e02e42018-01-31 23:36:25 +01005530 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005531 f_perform_clear();
Harald Weltee9e02e42018-01-31 23:36:25 +01005532}
5533testcase TC_err_84_unknown_msg() runs on test_CT {
5534 var MSC_ConnHdlr vc_conn;
5535 f_init(1, true);
5536 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005537 vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
Harald Weltee9e02e42018-01-31 23:36:25 +01005538 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005539 f_shutdown_helper();
Harald Weltee9e02e42018-01-31 23:36:25 +01005540}
5541
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005542/***********************************************************************
5543 * Handover
5544 ***********************************************************************/
5545
Harald Welte94e0c342018-04-07 11:33:23 +02005546/* execute a "bts <0-255> trx <0-255> timeslot <0-7> " command on given Dchan */
5547private function f_vty_ts_action(charstring suffix, integer bts_nr, integer trx_nr, integer ts_nr)
5548runs on test_CT {
5549 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5550 " timeslot "&int2str(ts_nr)&" ";
5551 f_vty_transceive(BSCVTY, cmd & suffix);
5552}
5553
Harald Welte261af4b2018-02-12 21:20:39 +01005554/* 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 +07005555private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
5556 uint8_t bts_nr, uint8_t trx_nr,
5557 in RslChannelNr chan_nr)
5558{
Harald Welte261af4b2018-02-12 21:20:39 +01005559 /* FIXME: resolve those from component-global state */
5560 var integer ts_nr := chan_nr.tn;
5561 var integer ss_nr;
5562 if (ischosen(chan_nr.u.ch0)) {
5563 ss_nr := 0;
5564 } else if (ischosen(chan_nr.u.lm)) {
5565 ss_nr := chan_nr.u.lm.sub_chan;
5566 } else if (ischosen(chan_nr.u.sdcch4)) {
5567 ss_nr := chan_nr.u.sdcch4.sub_chan;
5568 } else if (ischosen(chan_nr.u.sdcch8)) {
5569 ss_nr := chan_nr.u.sdcch8.sub_chan;
5570 } else {
5571 setverdict(fail, "Invalid ChanNr ", chan_nr);
Daniel Willmannafce8662018-07-06 23:11:32 +02005572 mtc.stop;
Harald Welte261af4b2018-02-12 21:20:39 +01005573 }
5574
5575 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5576 " timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005577 f_vty_transceive(pt, cmd & suffix);
Harald Welte261af4b2018-02-12 21:20:39 +01005578}
5579
Neels Hofmeyr91401012019-07-11 00:42:35 +02005580/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
5581 * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor
5582 * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
5583 * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
5584 * pair, not really to a specific BTS number. */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005585private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
5586 in RslChannelNr chan_nr, uint8_t new_bts_nr)
5587{
5588 f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
Harald Welte261af4b2018-02-12 21:20:39 +01005589}
5590
5591/* intra-BSC hand-over between BTS0 and BTS1 */
5592private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02005593 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5594 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte261af4b2018-02-12 21:20:39 +01005595
5596 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5597 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5598
Harald Weltea0630032018-03-20 21:09:55 +01005599 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005600 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Harald Welte261af4b2018-02-12 21:20:39 +01005601
5602 var HandoverState hs := {
5603 rr_ho_cmpl_seen := false,
5604 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005605 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005606 expect_target_tsc := c_BtsParams[1].tsc
Harald Welte261af4b2018-02-12 21:20:39 +01005607 };
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005608 /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005609 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
Harald Welte261af4b2018-02-12 21:20:39 +01005610 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5611 f_rslem_suspend(RSL1_PROC);
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005612
5613 /* From the MGW perspective, a handover is is characterized by
5614 * performing one MDCX operation with the MGW. So we expect to see
5615 * one more MDCX during handover. */
5616 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5617
Harald Welte261af4b2018-02-12 21:20:39 +01005618 alt {
5619 [] as_handover(hs);
Harald Welte261af4b2018-02-12 21:20:39 +01005620 }
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005621
Philipp Maier4dae0652018-11-12 12:03:26 +01005622 /* Since this is an internal handover we expect the BSC to inform the
5623 * MSC about the event */
5624 BSSAP.receive(tr_BSSMAP_HandoverPerformed);
5625
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005626 /* Check the amount of MGCP transactions is still consistant with the
5627 * test expectation */
5628 f_check_mgcp_expectations()
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005629
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005630 var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
5631
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005632 /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
5633 * 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 +02005634 f_verify_encr_info(chan_act);
5635
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005636 f_chan_act_verify_tsc(chan_act, c_BtsParams[1].tsc);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005637
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005638 f_perform_clear(RSL1, RSL1_PROC);
5639
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005640 f_sleep(0.5);
Harald Welte261af4b2018-02-12 21:20:39 +01005641}
5642
5643testcase TC_ho_int() runs on test_CT {
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005644 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte261af4b2018-02-12 21:20:39 +01005645 var MSC_ConnHdlr vc_conn;
5646 f_init(2, true);
5647 f_sleep(1.0);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005648
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005649 pars.expect_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005650
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005651 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005652
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005653 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
Harald Welte261af4b2018-02-12 21:20:39 +01005654 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005655
5656 /* from f_establish_fully() */
5657 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5658 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5659 /* from handover */
5660 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5661 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5662 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5663 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005664 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5665 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005666 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005667 f_shutdown_helper();
Harald Welte261af4b2018-02-12 21:20:39 +01005668}
Harald Weltee9e02e42018-01-31 23:36:25 +01005669
Oliver Smith7eabd312021-07-12 14:18:56 +02005670function 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 +02005671 var MSC_ConnHdlr vc_conn;
5672 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5673 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
5674
5675 f_init(2, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02005676 f_vty_encryption_a5(enc_a5);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005677 f_sleep(1.0);
5678
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005679 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005680
5681 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
5682 vc_conn.done;
5683
5684 /* from f_establish_fully() */
5685 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5686 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5687 /* from handover */
5688 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5689 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5690 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5691 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005692 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5693 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005694 f_ctrs_bsc_and_bts_verify();
Oliver Smith7eabd312021-07-12 14:18:56 +02005695 f_vty_encryption_a5_reset();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005696 f_shutdown_helper();
5697}
5698
5699testcase TC_ho_int_a5_0() runs on test_CT {
5700 f_tc_ho_int_a5('01'O);
5701}
5702
5703testcase TC_ho_int_a5_1() runs on test_CT {
5704 f_tc_ho_int_a5('02'O);
5705}
5706
5707testcase TC_ho_int_a5_3() runs on test_CT {
5708 f_tc_ho_int_a5('08'O);
5709}
5710
5711testcase TC_ho_int_a5_4() runs on test_CT {
Oliver Smith7eabd312021-07-12 14:18:56 +02005712 f_tc_ho_int_a5('10'O, "0 1 3 4");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005713}
5714
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005715/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
5716private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
5717 g_pars := f_gen_test_hdlr_pars();
5718 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5719 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005720
5721 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5722 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5723
5724 f_establish_fully(ass_cmd, exp_compl);
5725 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
5726
5727 var HandoverState hs := {
5728 rr_ho_cmpl_seen := false,
5729 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005730 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06005731 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005732 };
5733 /* issue hand-over command on VTY */
5734 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
5735 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5736 f_rslem_suspend(RSL1_PROC);
5737
5738 /* From the MGW perspective, a handover is is characterized by
5739 * performing one MDCX operation with the MGW. So we expect to see
5740 * one more MDCX during handover. */
5741 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5742
5743 var RSL_Message rsl;
5744 var PDU_ML3_NW_MS l3;
5745 var RslChannelNr new_chan_nr;
5746 var GsmArfcn arfcn;
5747 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
5748 l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
5749 if (not ischosen(l3.msgs.rrm.handoverCommand)) {
5750 setverdict(fail, "Expected handoverCommand");
5751 mtc.stop;
5752 }
5753 }
5754 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
5755 new_chan_nr, arfcn);
5756
5757 f_rslem_register(0, new_chan_nr, RSL1_PROC);
5758
5759 /* resume processing of RSL DChan messages, which was temporarily suspended
5760 * before performing a hand-over */
5761 f_rslem_resume(RSL1_PROC);
5762 RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
5763
5764 f_sleep(1.0);
5765
5766 /* Handover fails because no HANDO DET appears on the new lchan,
5767 * and the old lchan reports a Radio Link Failure. */
5768 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
5769
5770 var PDU_BSSAP rx_clear_request;
5771 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5772 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5773 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5774
5775 var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
5776
5777 var MgcpCommand mgcp;
5778 interleave {
5779 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
5780 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005781 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005782 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005783 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005784 }
5785 [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005786 [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005787 RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005788 f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005789 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005790 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5791 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5792 }
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005793 }
5794
5795 f_sleep(0.5);
5796 setverdict(pass);
5797}
5798testcase TC_ho_int_radio_link_failure() runs on test_CT {
5799 var MSC_ConnHdlr vc_conn;
5800 f_init(2, true);
5801 f_sleep(1.0);
5802
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005803 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005804
5805 vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
5806 vc_conn.done;
5807
5808 /* from f_establish_fully() */
5809 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5810 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5811 /* from handover */
5812 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5813 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
5814 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5815 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005816 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5817 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005818 f_ctrs_bsc_and_bts_verify();
5819 f_shutdown_helper();
5820}
5821
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005822/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005823private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005824 var MgcpCommand mgcp;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005825 var template MgcpResponse mgcp_resp;
5826 var MGCP_RecvFrom mrf;
5827 var template MgcpMessage msg_resp;
5828 var template MgcpMessage msg_dlcx := {
5829 command := tr_DLCX()
5830 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005831
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005832 if (g_pars.aoip) {
5833 MGCP.receive(tr_DLCX()) -> value mgcp {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005834 log("Got first DLCX: ", mgcp);
5835 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005836 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005837
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005838 MGCP.receive(tr_DLCX()) -> value mgcp {
5839 log("Got second DLCX: ", mgcp);
5840 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
5841 };
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005842 } else {
5843 /* For SCCPLite, BSC doesn't handle the MSC-side */
5844 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
5845 log("Got first DLCX: ", mrf.msg.command);
5846 msg_resp := {
5847 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
5848 }
5849 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
5850 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005851 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005852}
5853
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005854private 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 +01005855
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01005856 var NcellReports neighbor_rep := {
5857 { rxlev := 20, bcch_freq := 0, bsic := 11 }
5858 };
5859 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
5860 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
5861 l3_mr, 0));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005862
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005863 BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005864
5865 f_sleep(0.5);
5866 /* The MSC negotiates Handover Request and Handover Request Ack with
5867 * the other BSS and comes back with a BSSMAP Handover Command
5868 * containing an RR Handover Command coming from the target BSS... */
5869
5870 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5871 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
5872 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5873 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
5874 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
5875
5876 /* expect the Handover Command to go out on RR */
5877 var RSL_Message rsl_ho_cmd
5878 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
5879 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
5880 var RSL_IE_Body rsl_ho_cmd_l3;
5881 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
5882 log("RSL message contains no L3 Info IE, expected RR Handover Command");
5883 setverdict(fail);
5884 } else {
5885 log("Found L3 Info: ", rsl_ho_cmd_l3);
5886 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
5887 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
5888 setverdict(fail);
5889 } else {
5890 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
5891 setverdict(pass);
5892 }
5893 }
5894
5895 /* When the other BSS has reported a completed handover, this side is
5896 * torn down. */
5897
5898 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_HANDOVER_SUCCESSFUL;
5899 var BssmapCause cause := enum2int(cause_val);
5900 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5901
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005902 f_expect_dlcx_conns();
Pau Espin Pedrol06199952021-06-15 11:30:00 +02005903
5904 interleave {
5905 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
5906 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
5907 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005908 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5909 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5910 }
Pau Espin Pedrol06199952021-06-15 11:30:00 +02005911 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005912 setverdict(pass);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005913}
5914
5915private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
5916 g_pars := f_gen_test_hdlr_pars();
5917 var PDU_BSSAP ass_req := f_gen_ass_req();
5918 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5919 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5920 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5921 f_establish_fully(ass_req, exp_compl);
5922
5923 f_ho_out_of_this_bsc();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005924}
5925testcase TC_ho_out_of_this_bsc() runs on test_CT {
5926 var MSC_ConnHdlr vc_conn;
5927
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01005928 f_init_vty();
5929 f_bts_0_cfg(BSCVTY,
5930 {"neighbor-list mode automatic",
5931 "handover 1",
5932 "handover algorithm 2",
5933 "handover2 window rxlev averaging 1",
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01005934 "no neighbors",
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01005935 "neighbor lac 99 arfcn 123 bsic any"});
5936 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
5937
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005938 f_init(1, true);
5939 f_sleep(1.0);
5940
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005941 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005942
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005943 vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
5944 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005945
5946 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5947 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5948 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5949 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5950 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
5951 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
5952 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005953 f_shutdown_helper();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005954}
5955
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005956private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
5957 template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
Vadim Yanitskiy2ef6a2f2020-10-08 23:17:32 +07005958 template (present) OCT1 dlci := ?,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07005959 octetstring l3 := '0123456789'O)
5960runs on MSC_ConnHdlr {
Neels Hofmeyr43654812020-09-25 01:35:35 +02005961 /* The old lchan and conn should still be active. See that arbitrary L3
5962 * is still going through. */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005963 rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
Neels Hofmeyr43654812020-09-25 01:35:35 +02005964 var template PDU_BSSAP exp_data := {
5965 discriminator := '1'B,
5966 spare := '0000000'B,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07005967 dlci := dlci,
5968 lengthIndicator := lengthof(l3),
Neels Hofmeyr43654812020-09-25 01:35:35 +02005969 pdu := {
5970 dtap := l3
5971 }
5972 };
5973 BSSAP.receive(exp_data);
5974 setverdict(pass);
5975}
5976
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005977private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
5978 template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07005979 template (value) OCT1 dlci := '00'O,
5980 octetstring l3 := '0123456789'O)
5981runs on MSC_ConnHdlr {
5982 BSSAP.send(PDU_BSSAP:{
5983 discriminator := '1'B,
5984 spare := '0000000'B,
5985 dlci := dlci,
5986 lengthIndicator := lengthof(l3),
5987 pdu := {
5988 dtap := l3
5989 }
5990 });
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005991 rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07005992 setverdict(pass);
5993}
5994
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005995/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
5996 * simply never sends a BSSMAP Handover Command. */
5997private function f_tc_ho_out_fail_no_msc_response(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 /* osmo-bsc should time out 10 seconds after the handover started.
6012 * Let's give it a bit extra. */
6013 f_sleep(15.0);
6014
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006015 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006016 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006017 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006018}
6019testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
6020 var MSC_ConnHdlr vc_conn;
6021
6022 f_init(1, true);
6023 f_sleep(1.0);
6024
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006025 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006026
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006027 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
6028 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006029
6030 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6031 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6032 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6033 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6034 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6035 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6036 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006037 f_shutdown_helper();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006038}
6039
6040/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
6041 * RR Handover Failure. */
6042private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006043 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006044
6045 var PDU_BSSAP ass_req := f_gen_ass_req();
6046 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6047 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6048 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6049 f_establish_fully(ass_req, exp_compl);
6050
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006051 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006052 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6053
6054 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6055
6056 f_sleep(0.5);
6057 /* The MSC negotiates Handover Request and Handover Request Ack with
6058 * the other BSS and comes back with a BSSMAP Handover Command
6059 * containing an RR Handover Command coming from the target BSS... */
6060
6061 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6062 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6063 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6064 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6065 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6066
6067 /* expect the Handover Command to go out on RR */
6068 var RSL_Message rsl_ho_cmd
6069 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6070 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6071 var RSL_IE_Body rsl_ho_cmd_l3;
6072 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6073 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6074 setverdict(fail);
6075 } else {
6076 log("Found L3 Info: ", rsl_ho_cmd_l3);
6077 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6078 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6079 setverdict(fail);
6080 } else {
6081 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6082 setverdict(pass);
6083 }
6084 }
6085
6086 f_sleep(0.2);
6087 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
6088
6089 /* Should tell the MSC about the failure */
6090 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6091
6092 f_sleep(1.0);
6093
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07006094 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006095 f_sleep(1.0);
6096
6097 setverdict(pass);
6098 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006099 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006100}
6101testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
6102 var MSC_ConnHdlr vc_conn;
6103
6104 f_init(1, true);
6105 f_sleep(1.0);
6106
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006107 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006108
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006109 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
6110 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006111
6112 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6113 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6114 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6115 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6116 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6117 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
6118 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006119 f_shutdown_helper();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006120}
6121
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006122/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
6123 * (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 +02006124 * and the lchan is released. */
6125private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01006126 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006127
6128 var PDU_BSSAP ass_req := f_gen_ass_req();
6129 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6130 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6131 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6132 f_establish_fully(ass_req, exp_compl);
6133
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006134 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006135 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
6136
6137 BSSAP.receive(tr_BSSMAP_HandoverRequired);
6138
6139 f_sleep(0.5);
6140 /* The MSC negotiates Handover Request and Handover Request Ack with
6141 * the other BSS and comes back with a BSSMAP Handover Command
6142 * containing an RR Handover Command coming from the target BSS... */
6143
6144 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6145 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
6146 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6147 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
6148 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
6149
6150 /* expect the Handover Command to go out on RR */
6151 var RSL_Message rsl_ho_cmd
6152 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
6153 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
6154 var RSL_IE_Body rsl_ho_cmd_l3;
6155 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
6156 log("RSL message contains no L3 Info IE, expected RR Handover Command");
6157 setverdict(fail);
6158 } else {
6159 log("Found L3 Info: ", rsl_ho_cmd_l3);
6160 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
6161 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
6162 setverdict(fail);
6163 } else {
6164 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
6165 setverdict(pass);
6166 }
6167 }
6168
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02006169 /* We get neither success nor failure report from the remote BSS. Eventually T8 times out and we run into 3GPP
6170 * TS 48.008 3.1.5.3.3 "Abnormal Conditions": Clear Request should go to the MSC, and RR should be released
6171 * after Clear Command */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006172
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006173 var PDU_BSSAP rx_clear_request;
Neels Hofmeyre1797aa2019-07-09 19:34:04 +02006174 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
6175 log("Got BSSMAP Clear Request");
6176 /* Instruct BSC to clear channel */
6177 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6178 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6179
6180 var MgcpCommand mgcp;
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006181 interleave {
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01006182 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
6183 log("Got Deact SACCH");
6184 }
Harald Welte924b6ea2019-02-04 01:05:34 +01006185 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
Neels Hofmeyr211169d2018-11-07 00:37:29 +01006186 log("Got RR Release");
6187 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02006188 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006189 log("Got RF Chan Rel");
6190 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02006191 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006192 }
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006193 }
6194
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006195 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006196 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006197 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006198
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006199 setverdict(pass);
6200 f_sleep(1.0);
6201}
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006202testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006203 var MSC_ConnHdlr vc_conn;
6204
6205 f_init(1, true);
6206 f_sleep(1.0);
6207
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006208 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006209
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02006210 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006211 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006212
6213 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6214 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6215 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6216 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6217 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6218 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6219 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006220 f_shutdown_helper();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02006221}
6222
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006223private 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 +01006224 var PDU_BSSAP rx_bssap;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006225 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6226 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6227 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6228 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6229 * before we get started. */
6230 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6231 f_rslem_register(0, new_chan_nr);
6232 g_chan_nr := new_chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06006233 var uint3_t expect_target_tsc := c_BtsParams[0].tsc;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006234 f_sleep(1.0);
6235
6236 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6237 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006238 var default as_media := activate(as_Media());
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006239
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01006240 var PDU_BSSAP ho_req := f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
6241 cell_id_source := g_pars.cell_id_source,
6242 oldToNewBSSIEs := oldToNewBSSIEs,
6243 enc := g_pars.encr);
6244 if (g_pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr) {
6245 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, ho_req));
6246 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6247 } else {
6248 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, omit));
6249 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
6250 BSSAP.send(ho_req);
6251 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006252
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006253 alt {
6254 [] BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap {
6255 if (g_pars.expect_ho_fail) {
6256 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6257 "Expected Handover Request to fail, but got Handover Request Ack")
6258 }
6259 }
6260 [] BSSAP.receive(tr_BSSMAP_HandoverFailure) -> value rx_bssap {
6261 if (not g_pars.expect_ho_fail) {
6262 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6263 "Expected Handover Request to succeed, but got Handover Failure")
6264 }
6265 // TODO: evaluate correct cause value. But osmo-bsc doesn't seem to send meaningful causes yet!
6266 // For now just accept any cause.
6267 BSSAP.receive(tr_BSSMAP_ClearRequest);
6268 setverdict(pass);
6269 return;
6270 }
6271 }
6272
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006273 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6274
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006275 /* we're sure that the channel activation is done now, verify the parameters in it */
6276 var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
6277 f_verify_encr_info(chan_act);
6278 f_chan_act_verify_tsc(chan_act, expect_target_tsc);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006279
Neels Hofmeyr46e16e52022-02-23 17:04:00 +01006280 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.codecList)) {
6281 if (not g_pars.aoip) {
6282 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6283 "handoverRequestAck: Expected no Speech Codec List (BSS Supported), because this is not AoIP");
6284 }
6285 /* TODO: check actual codecs? */
6286 } else {
6287 if (g_pars.aoip) {
6288 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6289 "handoverRequestAck: Expected Speech Codec List (BSS Supported), but none found");
6290 }
6291 }
6292
6293 if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.speechCodec)) {
6294 if (not g_pars.aoip) {
6295 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6296 "handoverRequestAck: Expected no Speech Codec (Chosen), because this is not AoIP");
6297 }
6298 /* TODO: check actual codec? */
6299 } else {
6300 if (g_pars.aoip) {
6301 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
6302 "handoverRequestAck: Expected Speech Codec (Chosen), but none found");
6303 }
6304 }
6305
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006306 var octetstring ho_command_str;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006307 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6308 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6309 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6310 log("L3 Info in HO Request Ack is ", ho_command);
6311
6312 var GsmArfcn arfcn;
6313 var RslChannelNr actual_new_chan_nr;
6314 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6315 actual_new_chan_nr, arfcn);
6316
6317 if (actual_new_chan_nr != new_chan_nr) {
6318 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6319 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6320 setverdict(fail);
6321 return;
6322 }
6323 log("Handover Command chan_nr is", actual_new_chan_nr);
6324
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006325 var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
6326 if (not match(got_tsc, expect_target_tsc)) {
6327 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6328 expect_target_tsc, " got ", got_tsc);
6329 mtc.stop;
6330 } else {
6331 log("handoverCommand: verified TSC = ", got_tsc);
6332 }
6333
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006334 /* Check the Cipher Mode Setting IE (shall be present during inter-RAT handover) */
6335 if (ispresent(ho_command.msgs.rrm.handoverCommand.cipherModeSetting)) {
6336 var CipherModeSetting_TV cms := ho_command.msgs.rrm.handoverCommand.cipherModeSetting;
6337 var template (present) CipherModeSetting_TV tr_cms := {
6338 sC := '0'B, /* no ciphering by default */
6339 algorithmIdentifier := '000'B,
6340 elementIdentifier := ?
6341 };
6342 if (ispresent(g_pars.encr) and g_pars.encr.enc_alg_expect != '01'O) { /* A5/N */
6343 tr_cms.algorithmIdentifier := f_cipher_mode_bssmap_to_rr(g_pars.encr.enc_alg_expect);
6344 tr_cms.sC := '1'B;
6345 }
6346 if (not match(cms, tr_cms)) {
6347 setverdict(fail, "RR Handover Command: unexpected Cipher Mode Setting IE: ",
6348 cms, ", expected: ", tr_cms);
6349 }
6350 } else {
6351 setverdict(fail, "RR Handover Command: Cipher Mode Setting IE is not present");
6352 }
6353
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006354 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6355 * tells the MS to handover to the new lchan. Here comes the new MS on
6356 * the new lchan with a Handover RACH: */
6357
6358 /* send handover detect */
6359
6360 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6361
6362 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6363
6364 /* send handover complete over the new channel */
6365
6366 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_HandoverComplete('00'O));
6367 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
6368 enc_PDU_ML3_MS_NW(l3_tx)));
6369
6370 BSSAP.receive(tr_BSSMAP_HandoverComplete);
Neels Hofmeyr2677b872022-04-12 01:44:43 +02006371 deactivate(as_media);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006372 setverdict(pass);
6373}
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006374
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006375private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006376 var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006377 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
6378 if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
6379 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006380 }
6381 if (g_pars.exp_fast_return) {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006382 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006383 } else {
6384 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006385 }
6386 f_ho_into_this_bsc(id, oldToNewBSSIEs);
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006387 if (g_pars.expect_ho_fail) {
6388 f_perform_clear_no_lchan();
6389 } else {
6390 f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
6391 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006392 setverdict(pass);
6393}
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006394function 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 +01006395 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006396
6397 f_init(1, true);
6398 f_sleep(1.0);
6399
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006400 f_vty_encryption_a5(vty_a5_cfg);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006401 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006402
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006403 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6404 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006405
6406 vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
6407 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006408
6409 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006410 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006411 if (pars.expect_ho_fail) {
6412 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6413 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:failed");
6414 } else {
6415 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6416 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
6417 }
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006418 f_ctrs_bsc_and_bts_verify();
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006419
6420 f_vty_encryption_a5_reset();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006421}
6422
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006423testcase TC_ho_into_this_bsc() runs on test_CT {
6424 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6425 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006426 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006427}
6428
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006429function f_tc_ho_into_this_bsc_a5(TestHdlrEncrParams encr, charstring vty_a5_cfg := VTY_A5_DEFAULT,
6430 boolean expect_fail := false) runs on test_CT {
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006431 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006432 pars.encr := encr;
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006433 pars.expect_ho_fail := expect_fail;
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006434 f_tc_ho_into_this_bsc_main(pars, vty_a5_cfg);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006435 f_shutdown_helper();
6436}
6437
6438testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006439 f_tc_ho_into_this_bsc_a5(f_encr_params('01'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006440}
6441
6442testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006443 f_tc_ho_into_this_bsc_a5(f_encr_params('02'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006444}
6445
6446testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
Neels Hofmeyrd23e8a02022-02-17 01:55:59 +01006447 f_tc_ho_into_this_bsc_a5(f_encr_params('08'O));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006448}
6449
6450testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
Neels Hofmeyr731ddc52022-02-17 21:56:15 +01006451 f_tc_ho_into_this_bsc_a5(f_encr_params('10'O, kc128 := true), "3 4");
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006452}
6453
Neels Hofmeyr1951be22022-02-16 16:21:07 +01006454/* Report: in inter-BSC incoming handover, when the MSC omits the Chosen Encryption Algorithm IE in the Handover Request
6455 * message, then osmo-bsc starts an unencrypted lchan even if A5/0 is not permitted.
6456 *
6457 * This test verifies that the Encryption Information is present in the Channel Activation when the Chosen Enc Alg is
6458 * omitted.
6459 *
6460 * Related: SYS#5839
6461 */
6462testcase TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() runs on test_CT {
6463 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O, alg_chosen := omit));
6464}
6465
6466testcase TC_ho_into_this_bsc_a5_1_3() runs on test_CT {
6467 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O));
6468}
6469
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01006470/* Send a permitted algo mask that does not intersect with osmo-bsc.cfg */
6471testcase TC_ho_into_this_bsc_a5_mismatch() runs on test_CT {
6472 f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '18'O, alg_expect := '10'O), "0 1",
6473 expect_fail := true); // 0x18 = A5/3 and A5/4
6474}
6475
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006476testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
6477 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6478 pars.host_aoip_tla := "::6";
6479 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006480 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006481}
6482
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006483/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006484 to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006485 channel is later released (RR CHannel Release), should trigger inclusion of
6486 IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
6487 neighbors. */
6488testcase TC_srvcc_eutran_to_geran() runs on test_CT {
6489 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6490 pars.last_used_eutran_plmn := '323454'O;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006491 pars.exp_fast_return := true;
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006492 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006493
6494 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6495 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6496 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006497 f_shutdown_helper();
6498}
6499
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +03006500/* Same as TC_srvcc_eutran_to_geran, but enables ciphering on the target channel. */
6501testcase TC_srvcc_eutran_to_geran_a5_3() runs on test_CT {
6502 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6503 pars.encr := f_encr_params('08'O); /* only A5/3 */
6504 pars.last_used_eutran_plmn := '323454'O;
6505 pars.exp_fast_return := true;
6506 f_tc_ho_into_this_bsc_main(pars);
6507
6508 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6509 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6510 f_ctrs_bsc_and_bts_verify();
6511 f_shutdown_helper();
6512}
6513
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006514/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
6515 on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
6516 list when the channel is released. */
6517testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
6518 f_init_vty();
6519 f_vty_allow_srvcc_fast_return(true, 0)
6520
6521 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6522 pars.last_used_eutran_plmn := '323454'O;
6523 pars.exp_fast_return := false;
6524 f_tc_ho_into_this_bsc_main(pars);
6525 f_vty_allow_srvcc_fast_return(false, 0);
6526 f_shutdown_helper();
6527}
6528
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +01006529/* Same as TC_srvcc_eutran_to_geran, but using SAI as serving Cell Identifier. SYS#5838 */
6530testcase TC_srvcc_eutran_to_geran_src_sai() runs on test_CT {
6531 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6532 pars.last_used_eutran_plmn := '323454'O;
6533 pars.cell_id_source := valueof(ts_CellID_SAI('123456'O, 300, 444));
6534 f_tc_ho_into_this_bsc_main(pars);
6535
6536 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6537 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6538 f_ctrs_bsc_and_bts_verify();
6539 f_shutdown_helper();
6540}
6541
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006542private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
6543 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
6544 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
6545 f_ho_into_this_bsc(id, oldToNewBSSIEs);
6546 f_ho_out_of_this_bsc(oldToNewBSSIEs);
6547 setverdict(pass);
6548}
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006549
6550private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
6551 runs on test_CT {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006552 var MSC_ConnHdlr vc_conn;
6553 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6554
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006555 f_init_vty();
6556 f_bts_0_cfg(BSCVTY,
6557 {"neighbor-list mode automatic",
6558 "handover 1",
6559 "handover algorithm 2",
6560 "handover2 window rxlev averaging 1",
6561 "no neighbors",
6562 "neighbor lac 99 arfcn 123 bsic any"});
6563 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6564
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006565 f_init(1, true);
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006566 if (disable_fast_return) {
6567 f_vty_allow_srvcc_fast_return(true, 0);
6568 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006569 f_sleep(1.0);
6570
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006571 f_ctrs_bsc_and_bts_handover_init();
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006572
6573 pars.last_used_eutran_plmn := '323454'O;
6574 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6575 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
6576
6577 vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
6578 vc_conn.done;
6579
6580 f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
6581 f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
6582 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
6583 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
6584 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
6585 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006586
6587 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
6588 f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006589 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006590
6591 if (disable_fast_return) {
6592 f_vty_allow_srvcc_fast_return(false, 0);
6593 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006594 f_shutdown_helper();
6595}
6596
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006597/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
6598 BSS Information" IE with "Last Used E-UTRAN PLMN Id".
6599 Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
6600 IE with "Last Used E-UTRAN PLMN Id" from first step. */
6601testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
6602 f_tc_srvcc_eutran_to_geran_ho_out_main(false);
6603}
6604/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
6605 * independently of fast-reture allowed/forbidden in local BTS */
6606testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
6607 f_tc_srvcc_eutran_to_geran_ho_out_main(true);
6608}
6609
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006610private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
6611 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6612 f_rslem_register(0, new_chan_nr);
6613 g_chan_nr := new_chan_nr;
6614 f_sleep(1.0);
6615
6616 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6617 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6618 activate(as_Media());
6619
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006620 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006621 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006622 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006623
6624 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6625
6626 var PDU_BSSAP rx_bssap;
6627 var octetstring ho_command_str;
6628
6629 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6630
6631 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6632 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6633 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6634 log("L3 Info in HO Request Ack is ", ho_command);
6635
6636 var GsmArfcn arfcn;
6637 var RslChannelNr actual_new_chan_nr;
6638 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6639 actual_new_chan_nr, arfcn);
6640
6641 if (actual_new_chan_nr != new_chan_nr) {
6642 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6643 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6644 setverdict(fail);
6645 return;
6646 }
6647 log("Handover Command chan_nr is", actual_new_chan_nr);
6648
Neels Hofmeyr61ca08d2019-05-06 23:52:22 +02006649 /* For deterministic test results, give some time for the MGW endpoint to be configured */
6650 f_sleep(1.0);
6651
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006652 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6653 * tells the MS to handover to the new lchan. In this case, the MS
6654 * reports a Handover Failure to the old BSS, which forwards a BSSMAP
6655 * Handover Failure to the MSC. The procedure according to 3GPP TS
6656 * 48.008 3.1.5.3.2 "Handover Failure" is then that the MSC sends a
6657 * BSSMAP Clear Command: */
6658
6659 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6660 var BssmapCause cause := enum2int(cause_val);
6661 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6662
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006663 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006664 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006665 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006666
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006667 setverdict(pass);
6668 f_sleep(1.0);
6669
6670 setverdict(pass);
6671}
6672testcase TC_ho_in_fail_msc_clears() runs on test_CT {
6673 var MSC_ConnHdlr vc_conn;
6674 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6675
6676 f_init(1, true);
6677 f_sleep(1.0);
6678
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006679 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006680
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006681 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6682 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006683
6684 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
6685 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006686
6687 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6688 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6689 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6690 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6691 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006692 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006693}
6694
6695private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
6696 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6697 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6698 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6699 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6700 * before we get started. */
6701 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6702 f_rslem_register(0, new_chan_nr);
6703 g_chan_nr := new_chan_nr;
6704 f_sleep(1.0);
6705
6706 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6707 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6708 activate(as_Media());
6709
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006710 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006711 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006712 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006713
6714 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6715
6716 var PDU_BSSAP rx_bssap;
6717 var octetstring ho_command_str;
6718
6719 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6720
6721 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6722 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6723 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6724 log("L3 Info in HO Request Ack is ", ho_command);
6725
6726 var GsmArfcn arfcn;
6727 var RslChannelNr actual_new_chan_nr;
6728 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6729 actual_new_chan_nr, arfcn);
6730
6731 if (actual_new_chan_nr != new_chan_nr) {
6732 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6733 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6734 setverdict(fail);
6735 return;
6736 }
6737 log("Handover Command chan_nr is", actual_new_chan_nr);
6738
6739 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6740 * tells the MS to handover to the new lchan. Here comes the new MS on
6741 * the new lchan with a Handover RACH: */
6742
6743 /* send handover detect */
6744
6745 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6746
6747 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6748
6749 /* The MSC chooses to clear the connection now, maybe we got the
6750 * Handover RACH on the new cell but the MS still signaled Handover
6751 * Failure to the old BSS? */
6752
6753 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6754 var BssmapCause cause := enum2int(cause_val);
6755 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6756
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006757 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006758 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006759 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006760
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006761 f_sleep(1.0);
6762}
6763testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
6764 var MSC_ConnHdlr vc_conn;
6765 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6766
6767 f_init(1, true);
6768 f_sleep(1.0);
6769
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006770 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006771
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006772 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6773 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006774
6775 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
6776 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006777
6778 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6779 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6780 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6781 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6782 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006783 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006784}
6785
6786/* The new BSS's lchan times out before the MSC decides that handover failed. */
6787private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
6788 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6789 f_rslem_register(0, new_chan_nr);
6790 g_chan_nr := new_chan_nr;
6791 f_sleep(1.0);
6792
6793 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6794 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr9b320c12022-04-07 00:19:01 +02006795 activate(as_Media(fail_on_dlcx := false));
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006796
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006797 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006798 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006799 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006800
6801 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6802
6803 var PDU_BSSAP rx_bssap;
6804 var octetstring ho_command_str;
6805
6806 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6807
6808 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6809 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6810 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6811 log("L3 Info in HO Request Ack is ", ho_command);
6812
6813 var GsmArfcn arfcn;
6814 var RslChannelNr actual_new_chan_nr;
6815 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6816 actual_new_chan_nr, arfcn);
6817
6818 if (actual_new_chan_nr != new_chan_nr) {
6819 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6820 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6821 setverdict(fail);
6822 return;
6823 }
6824 log("Handover Command chan_nr is", actual_new_chan_nr);
6825
6826 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6827 * tells the MS to handover to the new lchan. But the MS never shows up
6828 * on the new lchan. */
6829
6830 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6831
6832 /* Did osmo-bsc also send a Clear Request? */
6833 timer T := 0.5;
6834 T.start;
6835 alt {
6836 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
6837 [] T.timeout { }
6838 }
6839
6840 /* MSC plays along with a Clear Command (no matter whether osmo-bsc
6841 * asked for it, this is a Handover Failure after all). */
6842
6843 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6844 var BssmapCause cause := enum2int(cause_val);
6845 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6846
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006847 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006848 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006849 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006850
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006851 f_sleep(1.0);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006852}
6853testcase TC_ho_in_fail_no_detect() runs on test_CT {
6854 var MSC_ConnHdlr vc_conn;
6855 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6856
6857 f_init(1, true);
6858 f_sleep(1.0);
6859
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006860 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006861
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006862 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6863 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006864
6865 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect), pars);
6866 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006867
6868 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6869 f_ctrs_bsc_and_bts_add(0, "handover:error");
6870 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6871 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
6872 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006873 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006874}
6875
6876/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
6877private function f_tc_ho_in_fail_no_detect2(charstring id) runs on MSC_ConnHdlr {
6878 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6879 f_rslem_register(0, new_chan_nr);
6880 g_chan_nr := new_chan_nr;
6881 f_sleep(1.0);
6882
6883 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6884 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr9b320c12022-04-07 00:19:01 +02006885 activate(as_Media(fail_on_dlcx := false));
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006886
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006887 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006888 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006889 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006890
6891 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6892
6893 var PDU_BSSAP rx_bssap;
6894 var octetstring ho_command_str;
6895
6896 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6897
6898 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6899 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6900 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6901 log("L3 Info in HO Request Ack is ", ho_command);
6902
6903 var GsmArfcn arfcn;
6904 var RslChannelNr actual_new_chan_nr;
6905 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6906 actual_new_chan_nr, arfcn);
6907
6908 if (actual_new_chan_nr != new_chan_nr) {
6909 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6910 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6911 setverdict(fail);
6912 return;
6913 }
6914 log("Handover Command chan_nr is", actual_new_chan_nr);
6915
6916 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6917 * tells the MS to handover to the new lchan. But the MS never shows up
6918 * on the new lchan. */
6919
6920 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6921
6922 /* MSC plays dumb and sends no Clear Command */
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006923 var PDU_BSSAP rx_clear_request;
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006924
6925 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request {
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006926 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6927 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6928 };
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006929 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006930 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006931 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006932
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006933 f_sleep(1.0);
6934}
6935testcase TC_ho_in_fail_no_detect2() runs on test_CT {
6936 var MSC_ConnHdlr vc_conn;
6937 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6938
6939 f_init(1, true);
6940 f_sleep(1.0);
6941
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006942 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006943
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006944 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6945 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006946
6947 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
6948 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006949
6950 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6951 f_ctrs_bsc_and_bts_add(0, "handover:error");
6952 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6953 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
6954 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006955 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006956}
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006957
Neels Hofmeyra23f3b12022-03-02 19:57:12 +01006958/* An incoming inter-BSC HO can either issue the Handover Request message attached to the initial SCCP N-Connect (as in
6959 * the other tests we have so far), or the first CR can be "empty" with the BSSAP request following later. Test the
6960 * empty N-Connect case. */
6961testcase TC_ho_into_this_bsc_sccp_cr_without_bssap() runs on test_CT {
6962 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6963 pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr := false;
6964 f_tc_ho_into_this_bsc_main(pars);
6965 f_shutdown_helper();
6966}
6967
Neels Hofmeyr91401012019-07-11 00:42:35 +02006968type record of charstring Commands;
6969
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006970private function f_bts_0_cfg(TELNETasp_PT pt, Commands cmds := {})
Neels Hofmeyr91401012019-07-11 00:42:35 +02006971{
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006972 f_vty_enter_cfg_bts(pt, 0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006973 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006974 f_vty_transceive(pt, cmds[i]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006975 }
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006976 f_vty_transceive(pt, "end");
Neels Hofmeyr91401012019-07-11 00:42:35 +02006977}
6978
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01006979private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
6980{
6981 f_vty_enter_cfg_cs7_inst(pt, 0);
6982 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
6983 f_vty_transceive(pt, cmds[i]);
6984 }
6985 f_vty_transceive(pt, "end");
6986}
6987
Neels Hofmeyr91401012019-07-11 00:42:35 +02006988private function f_probe_for_handover(charstring log_label,
6989 charstring log_descr,
6990 charstring handover_vty_cmd,
6991 boolean expect_handover,
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006992 boolean is_inter_bsc_handover := false,
6993 template uint3_t expect_target_tsc := ?)
Neels Hofmeyr91401012019-07-11 00:42:35 +02006994runs on MSC_ConnHdlr
6995{
Neels Hofmeyrb3fc8982020-05-11 00:16:42 +02006996 /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
6997 * lchans to be established on bts 1 or bts 2. */
6998 f_rslem_suspend(RSL1_PROC);
6999 f_rslem_suspend(RSL2_PROC);
7000
Neels Hofmeyr91401012019-07-11 00:42:35 +02007001 var RSL_Message rsl;
7002
7003 var charstring log_msg := " (expecting handover)"
7004 if (not expect_handover) {
7005 log_msg := " (expecting NO handover)";
7006 }
7007 log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg);
7008 f_vty_transceive(BSCVTY, handover_vty_cmd);
7009
Neels Hofmeyr91401012019-07-11 00:42:35 +02007010 timer T := 2.0;
7011 T.start;
7012
7013 alt {
7014 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
7015 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
7016 log("Rx L3 from net: ", l3);
7017 if (ischosen(l3.msgs.rrm.handoverCommand)) {
7018 var RslChannelNr new_chan_nr;
7019 var GsmArfcn arfcn;
7020 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
7021 new_chan_nr, arfcn);
7022 log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
7023 log(l3.msgs.rrm.handoverCommand);
7024
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007025 /* Verify correct TSC in handoverCommand */
7026 var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
7027 if (not match(got_tsc, expect_target_tsc)) {
7028 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
7029 expect_target_tsc, " got ", got_tsc);
7030 mtc.stop;
7031 } else {
7032 log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
7033 expect_target_tsc, ")");
7034 }
7035
Neels Hofmeyr91401012019-07-11 00:42:35 +02007036 /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
7037 * matter on which BTS it really is, we're not going to follow through an entire handover
7038 * anyway. */
7039 f_rslem_register(0, new_chan_nr, RSL1_PROC);
7040 f_rslem_resume(RSL1_PROC);
7041 f_rslem_register(0, new_chan_nr, RSL2_PROC);
7042 f_rslem_resume(RSL2_PROC);
7043
7044 if (expect_handover and not is_inter_bsc_handover) {
7045 setverdict(pass);
7046 log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected.");
7047 } else {
7048 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. "
7049 & log_label & ": " & log_descr);
7050 }
7051
7052 log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
7053 /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with
7054 * Handover Failure. */
7055 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
7056
7057 /* target BTS is told to release lchan again; don't care which BTS nor what messages. */
7058 f_sleep(0.5);
7059 RSL1.clear;
7060 RSL2.clear;
7061 log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)");
7062 break;
7063 } else {
7064 repeat;
7065 }
7066 }
7067 [] BSSAP.receive(tr_BSSMAP_HandoverRequired) {
7068 if (expect_handover and is_inter_bsc_handover) {
7069 setverdict(pass);
7070 log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected.");
7071 } else {
7072 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. "
7073 & log_label & ": " & log_descr);
7074 }
7075
7076 log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)");
7077
7078 /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to
7079 * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required,
7080 * setting a short timeout and waiting is the only way. */
7081 log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out...");
7082 f_sleep(1.5);
7083 log("f_probe_for_handover(" & log_label & "): ...done");
7084
7085 break;
7086 }
7087 [] T.timeout {
7088 if (expect_handover) {
7089 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. "
7090 & log_label & ": " & log_descr);
7091 } else {
7092 setverdict(pass);
7093 log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected.");
7094 }
7095 log("f_probe_for_handover(" & log_label & "): done (got no Handover)");
7096 break;
7097 }
7098 }
7099
7100 f_rslem_resume(RSL1_PROC);
7101 f_rslem_resume(RSL2_PROC);
7102 f_sleep(3.0);
7103 RSL.clear;
7104
7105 log("f_probe_for_handover(" & log_label & "): done clearing");
7106}
7107
7108/* Test the effect of various neighbor configuration scenarios:
7109 *
7110 * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0.
7111 * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO.
7112 */
7113private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
7114 g_pars := f_gen_test_hdlr_pars();
7115 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
7116 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007117
7118 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
7119 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
7120
7121 /* Establish lchan at bts 0 */
7122 f_establish_fully(ass_cmd, exp_compl);
7123
7124 /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */
7125 f_vty_enter_cfg_network(BSCVTY);
7126 f_vty_transceive(BSCVTY, "timer T7 1");
7127 f_vty_transceive(BSCVTY, "end");
7128}
7129
7130private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
7131 f_tc_ho_neighbor_config_start();
7132
7133 /*
7134 * bts 0 ARFCN 871 BSIC 10
7135 * bts 1 ARFCN 871 BSIC 11
7136 * bts 2 ARFCN 871 BSIC 12
7137 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7138 */
7139
7140 log("f_tc_ho_neighbor_config: 1. No 'neighbor' config");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007141 f_bts_0_cfg(BSCVTY, {"no neighbors"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007142 f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
7143 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007144 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007145
7146 f_probe_for_handover("1.b", "HO to unknown cell does not start",
7147 "handover any to arfcn 13 bsic 39",
7148 false);
7149
7150 f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error",
7151 "handover any to arfcn 871 bsic 12",
7152 false);
7153
7154 f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
7155 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007156 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007157
7158 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007159}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007160testcase TC_ho_neighbor_config_1() runs on test_CT {
7161 var MSC_ConnHdlr vc_conn;
7162 f_init(3, true, guard_timeout := 60.0);
7163 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007164 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007165 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
7166 vc_conn.done;
7167
7168 /* f_tc_ho_neighbor_config_start() */
7169 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7170 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7171
7172 /* 1.a */
7173 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7174 * handover quickly by sending a Handover Failure message. */
7175 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7176 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7177 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7178 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007179 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7180 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007181
7182 /* 1.b */
7183 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7184 f_ctrs_bsc_and_bts_add(0, "handover:error");
7185
7186 /* 1.c */
7187 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7188 f_ctrs_bsc_and_bts_add(0, "handover:error");
7189
7190 /* 1.d */
7191 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7192 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7193 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7194 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007195 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7196 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007197
7198 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007199 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007200}
7201
Neels Hofmeyr91401012019-07-11 00:42:35 +02007202private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
7203 f_tc_ho_neighbor_config_start();
7204
7205 /*
7206 * bts 0 ARFCN 871 BSIC 10
7207 * bts 1 ARFCN 871 BSIC 11
7208 * bts 2 ARFCN 871 BSIC 12
7209 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7210 */
7211
7212 log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007213 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007214 f_sleep(0.5);
7215
7216 f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
7217 "handover any to arfcn 871 bsic 11",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007218 true, expect_target_tsc := c_BtsParams[1].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007219
7220 f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
7221 "handover any to arfcn 871 bsic 12",
7222 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007223 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007224}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007225testcase TC_ho_neighbor_config_2() runs on test_CT {
7226 var MSC_ConnHdlr vc_conn;
7227 f_init(3, true, guard_timeout := 50.0);
7228 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007229 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007230 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
7231 vc_conn.done;
7232
7233 /* f_tc_ho_neighbor_config_start() */
7234 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7235 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7236
7237 /* 2.a */
7238 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7239 * handover quickly by sending a Handover Failure message. */
7240 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7241 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7242 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7243 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007244 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
7245 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007246
7247 /* 2.b */
7248 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7249 f_ctrs_bsc_and_bts_add(0, "handover:error");
7250
7251 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007252 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007253}
7254
Neels Hofmeyr91401012019-07-11 00:42:35 +02007255private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
7256 f_tc_ho_neighbor_config_start();
7257
7258 /*
7259 * bts 0 ARFCN 871 BSIC 10
7260 * bts 1 ARFCN 871 BSIC 11
7261 * bts 2 ARFCN 871 BSIC 12
7262 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7263 */
7264
7265 log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007266 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007267 f_sleep(0.5);
7268
7269 f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor",
7270 "handover any to arfcn 871 bsic 11",
7271 false);
7272 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",
7273 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007274 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007275 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007276}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007277testcase TC_ho_neighbor_config_3() runs on test_CT {
7278 var MSC_ConnHdlr vc_conn;
7279 f_init(3, true, guard_timeout := 50.0);
7280 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007281 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007282 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
7283 vc_conn.done;
7284
7285 /* f_tc_ho_neighbor_config_start() */
7286 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7287 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7288
7289 /* 3.a */
7290 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7291 f_ctrs_bsc_and_bts_add(0, "handover:error");
7292
7293 /* 3.b */
7294 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7295 * handover quickly by sending a Handover Failure message. */
7296 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7297 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7298 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7299 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007300 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7301 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007302
7303 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007304 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007305}
7306
Neels Hofmeyr91401012019-07-11 00:42:35 +02007307private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
7308 f_tc_ho_neighbor_config_start();
7309
7310 /*
7311 * bts 0 ARFCN 871 BSIC 10
7312 * bts 1 ARFCN 871 BSIC 11
7313 * bts 2 ARFCN 871 BSIC 12
7314 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7315 */
7316
7317 log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007318 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007319 f_sleep(0.5);
7320
7321 f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor",
7322 "handover any to arfcn 871 bsic 11",
7323 false);
7324 f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor",
7325 "handover any to arfcn 871 bsic 12",
7326 false);
7327 f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
7328 "handover any to arfcn 123 bsic 45",
7329 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007330 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007331}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007332testcase TC_ho_neighbor_config_4() runs on test_CT {
7333 var MSC_ConnHdlr vc_conn;
7334 f_init(3, true, guard_timeout := 50.0);
7335 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007336 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007337 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
7338 vc_conn.done;
7339
7340 /* f_tc_ho_neighbor_config_start() */
7341 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7342 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7343
7344 /* 4.a */
7345 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7346 f_ctrs_bsc_and_bts_add(0, "handover:error");
7347
7348 /* 4.b */
7349 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7350 f_ctrs_bsc_and_bts_add(0, "handover:error");
7351
7352 /* 4.c */
7353 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7354 * handover quickly by timing out after the Handover Required message */
7355 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7356 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7357 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7358 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7359
7360 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007361 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007362}
7363
Neels Hofmeyr91401012019-07-11 00:42:35 +02007364private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
7365 f_tc_ho_neighbor_config_start();
7366
7367 /*
7368 * bts 0 ARFCN 871 BSIC 10
7369 * bts 1 ARFCN 871 BSIC 11
7370 * bts 2 ARFCN 871 BSIC 12
7371 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7372 */
7373
7374 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 +02007375 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007376 f_sleep(0.5);
7377
7378 f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
7379 "handover any to arfcn 871 bsic 12",
7380 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007381 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007382}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007383testcase TC_ho_neighbor_config_5() runs on test_CT {
7384 var MSC_ConnHdlr vc_conn;
7385 f_init(3, true);
7386 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007387 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007388 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
7389 vc_conn.done;
7390
7391 /* f_tc_ho_neighbor_config_start() */
7392 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7393 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7394
7395 /* 5 */
7396 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7397 * handover quickly by timing out after the Handover Required message */
7398 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7399 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7400 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7401 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7402
7403 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007404 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007405}
7406
Neels Hofmeyr91401012019-07-11 00:42:35 +02007407private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
7408 f_tc_ho_neighbor_config_start();
7409
7410 /*
7411 * bts 0 ARFCN 871 BSIC 10
7412 * bts 1 ARFCN 871 BSIC 11
7413 * bts 2 ARFCN 871 BSIC 12
7414 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7415 */
7416
7417 log("f_tc_ho_neighbor_config: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:"
7418 & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007419 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007420 f_sleep(0.5);
7421
7422 f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
7423 "handover any to arfcn 871 bsic 12",
7424 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007425 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007426}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007427testcase TC_ho_neighbor_config_6() runs on test_CT {
7428 var MSC_ConnHdlr vc_conn;
7429 f_init(3, true);
7430 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007431 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007432 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
7433 vc_conn.done;
7434
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 /* 6.a */
7440 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7441 * handover quickly by timing out after the Handover Required message */
7442 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7443 f_ctrs_bsc_and_bts_add(0, "handover:error");
7444
7445 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007446 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007447}
7448
Neels Hofmeyr91401012019-07-11 00:42:35 +02007449private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
7450 f_tc_ho_neighbor_config_start();
7451
7452 /*
7453 * bts 0 ARFCN 871 BSIC 10
7454 * bts 1 ARFCN 871 BSIC 11
7455 * bts 2 ARFCN 871 BSIC 12
7456 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7457 */
7458
7459 log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:"
7460 & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007461 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007462 f_sleep(0.5);
7463
7464 f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
7465 "handover any to arfcn 871 bsic 12",
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007466 true, expect_target_tsc := c_BtsParams[2].tsc);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007467 f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
7468 "handover any to arfcn 123 bsic 45",
7469 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007470 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007471}
Neels Hofmeyr91401012019-07-11 00:42:35 +02007472testcase TC_ho_neighbor_config_7() runs on test_CT {
7473 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf2b88032020-06-16 00:35:04 +02007474 f_init(3, true, guard_timeout := 50.0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007475 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007476 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007477 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
7478 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007479
7480 /* f_tc_ho_neighbor_config_start() */
7481 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7482 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7483
7484 /* 7.a */
7485 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7486 * handover quickly by sending a Handover Failure message. */
7487 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7488 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7489 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7490 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007491 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7492 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007493
7494 /* 7.b */
7495 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7496 * handover quickly by timing out after the Handover Required message */
7497 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7498 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7499 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7500 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7501
7502 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007503 f_shutdown_helper();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007504}
7505
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007506/* OS#3041: Open and close N connections in a normal fashion, and expect no
7507 * BSSMAP Reset just because of that. */
7508testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
7509 var default d;
7510 var integer i;
7511 var DchanTuple dt;
7512
7513 f_init();
7514
7515 /* Wait for initial BSSMAP Reset to pass */
7516 f_sleep(4.0);
7517
7518 d := activate(no_bssmap_reset());
7519
7520 /* Setup up a number of connections and RLSD them again from the MSC
7521 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7522 * Let's do it some more times for good measure. */
Harald Weltec3260d92018-06-11 17:48:16 +02007523 for (i := 0; i < 4; i := i+1) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007524 /* Since we're doing a lot of runs, give each one a fresh
7525 * T_guard from the top. */
7526 T_guard.start;
7527
7528 /* Setup a BSSAP connection and clear it right away. This is
7529 * the MSC telling the BSC about a planned release, it's not an
7530 * erratic loss of a connection. */
Harald Weltea1897182018-06-11 13:53:09 +02007531 dt := f_est_dchan(int2oct(i,1), 23+i, '00010203040506'O);
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007532
7533 /* MSC disconnects (RLSD). */
7534 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
7535 }
7536
7537 /* In the buggy behavior, a timeout of 2 seconds happens between above
7538 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7539 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7540 f_sleep(4.0);
7541
7542 deactivate(d);
7543 f_shutdown_helper();
7544}
Harald Welte552620d2017-12-16 23:21:36 +01007545
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007546/* OS#3041: Open and close N connections in a normal fashion, and expect no
7547 * BSSMAP Reset just because of that. Invoke the release by a BSSMAP Clear from
7548 * the MSC. */
7549testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
7550 var default d;
7551 var integer i;
7552 var DchanTuple dt;
7553 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007554 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
7555 var BssmapCause cause := enum2int(cause_val);
7556
7557 f_init();
7558
7559 /* Wait for initial BSSMAP Reset to pass */
7560 f_sleep(4.0);
7561
7562 d := activate(no_bssmap_reset());
7563
7564 /* Setup up a number of connections and RLSD them again from the MSC
7565 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7566 * Let's do it some more times for good measure. */
7567 for (i := 0; i < 8; i := i+1) {
7568 /* Since we're doing a lot of runs, give each one a fresh
7569 * T_guard from the top. */
7570 T_guard.start;
7571
7572 /* Setup a BSSAP connection and clear it right away. This is
7573 * the MSC telling the BSC about a planned release, it's not an
7574 * erratic loss of a connection. */
Harald Weltea1897182018-06-11 13:53:09 +02007575 dt := f_est_dchan(int2oct(i,1), 23+i, '00010203040506'O);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007576
7577 /* Instruct BSC to clear channel */
7578 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7579
7580 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007581 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007582 }
7583
7584 /* In the buggy behavior, a timeout of 2 seconds happens between above
7585 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7586 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7587 f_sleep(4.0);
7588
7589 deactivate(d);
7590 f_shutdown_helper();
7591}
7592
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007593/* OS#3041: Open and close N connections in a normal fashion, and expect no
7594 * BSSMAP Reset just because of that. Close connections from the MS side with a
7595 * Release Ind on RSL. */
7596testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
7597 var default d;
7598 var integer i;
7599 var DchanTuple dt;
7600 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007601 var integer j;
7602
7603 f_init();
7604
7605 /* Wait for initial BSSMAP Reset to pass */
7606 f_sleep(4.0);
7607
7608 d := activate(no_bssmap_reset());
7609
7610 /* Setup up a number of connections and RLSD them again from the MSC
7611 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7612 * Let's do it some more times for good measure. */
7613 for (i := 0; i < 8; i := i+1) {
7614 /* Since we're doing a lot of runs, give each one a fresh
7615 * T_guard from the top. */
7616 T_guard.start;
7617
7618 /* Setup a BSSAP connection and clear it right away. This is
7619 * the MSC telling the BSC about a planned release, it's not an
7620 * erratic loss of a connection. */
7621 dt := f_est_dchan('23'O, 23, '00010203040506'O);
7622
7623 /* simulate RLL REL IND */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007624 f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007625
7626 /* expect Clear Request on MSC side */
7627 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
7628
7629 /* Instruct BSC to clear channel */
7630 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
7631 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7632
7633 /* expect BSC to disable the channel */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007634 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007635 }
7636
7637 /* In the buggy behavior, a timeout of 2 seconds happens between above
7638 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7639 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7640 f_sleep(4.0);
7641
7642 deactivate(d);
7643 f_shutdown_helper();
7644}
7645
Harald Welte94e0c342018-04-07 11:33:23 +02007646/***********************************************************************
7647 * IPA style dynamic PDCH
7648 ***********************************************************************/
7649
7650private function f_dyn_ipa_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7651 template (omit) RSL_Cause nack := omit)
7652runs on test_CT {
7653 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7654 var RSL_Message rsl_unused;
7655 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7656 f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
7657 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007658 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007659 if (istemplatekind(nack, "omit")) {
7660 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007661 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007662 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007663 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007664 }
7665}
7666
7667private function f_dyn_ipa_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7668 template (omit) RSL_Cause nack := omit)
7669runs on test_CT {
7670 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7671 var RSL_Message rsl_unused;
7672 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7673 f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
7674 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007675 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_DEACT(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007676 if (istemplatekind(nack, "omit")) {
7677 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007678 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007679 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007680 f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007681 }
7682}
7683
7684private function f_ts_dyn_mode_get(integer bts_nr, integer trx_nr, integer ts_nr)
7685runs on test_CT return charstring {
7686 var charstring cmd, resp;
7687 cmd := "show timeslot "&int2str(bts_nr)&" "&int2str(trx_nr)&" "&int2str(ts_nr);
Stefan Sperlingcff13562018-11-13 15:24:06 +01007688 return f_vty_transceive_match_regexp_retry(BSCVTY, cmd, "*\((*)\)*", 0, 4, 1.0);
Harald Welte94e0c342018-04-07 11:33:23 +02007689}
7690
7691private function f_ts_dyn_mode_assert(integer bts_nr, integer trx_nr, integer ts_nr,
7692 template charstring exp)
7693runs on test_CT {
7694 var charstring mode := f_ts_dyn_mode_get(bts_nr, trx_nr, ts_nr);
7695 if (not match(mode, exp)) {
7696 setverdict(fail, "Unexpected TS Mode: ", mode);
Daniel Willmannafce8662018-07-06 23:11:32 +02007697 mtc.stop;
Harald Welte94e0c342018-04-07 11:33:23 +02007698 }
7699}
7700
7701private function f_ts_set_chcomb(integer bts_nr, integer trx_nr, integer ts_nr, charstring chcomb)
7702runs on test_CT {
7703 f_vty_enter_cfg_ts(BSCVTY, bts_nr, trx_nr, ts_nr);
7704 f_vty_transceive(BSCVTY, "phys_chan_config " & chcomb);
7705 f_vty_transceive(BSCVTY, "end");
7706}
7707
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007708
7709private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
7710 var integer i;
7711 for (i := 0; i < 8; i := i + 1) {
7712 f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
7713 }
7714}
7715
Harald Welte94e0c342018-04-07 11:33:23 +02007716private const charstring TCHF_MODE := "TCH/F mode";
7717private const charstring TCHH_MODE := "TCH/H mode";
7718private const charstring PDCH_MODE := "PDCH mode";
7719private const charstring NONE_MODE := "NONE mode";
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007720private const charstring SDCCH8_MODE := "SDCCH8 mode";
Harald Welte94e0c342018-04-07 11:33:23 +02007721
7722/* Test IPA PDCH activation / deactivation triggered by VTY */
7723testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
7724 var RSL_Message rsl_unused;
7725
7726 /* change Timeslot 6 before f_init() starts RSL */
7727 f_init_vty();
7728 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7729 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7730
7731 f_init(1, false);
7732 f_sleep(1.0);
7733
7734 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7735
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007736 log("TCH/F_PDCH pchan starts out in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007737 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7738 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007739 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7740 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007741 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007742 log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007743 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);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007748 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007749 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7750
7751 /* re-activate it via VTY */
7752 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn);
7753 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007754 log("TCH/F_PDCH pchan, PDCH ACT via VTY, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007755 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7756
7757 /* and finally de-activate it again */
7758 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7759 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007760 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007761 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7762
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007763 /* clean up config */
7764 f_ts_set_chcomb(0, 0, 6, "PDCH");
7765
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007766 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007767}
7768
7769/* Test IPA PDCH activation NACK */
7770testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
7771 var RSL_Message rsl_unused;
7772
7773 /* change Timeslot 6 before f_init() starts RSL */
7774 f_init_vty();
7775 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7776 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7777
7778 f_init(1, false);
7779 f_sleep(1.0);
7780
7781 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7782
7783 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7784 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007785 rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
7786 f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
Harald Welte94e0c342018-04-07 11:33:23 +02007787 f_sleep(1.0);
7788 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7789
7790 /* De-activate it via VTY */
7791 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7792 f_sleep(1.0);
7793 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7794
7795 /* re-activate it via VTY, but fail that; check BSC still assumes TCH/F mode */
7796 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn, RSL_ERR_EQUIPMENT_FAIL);
7797 f_sleep(1.0);
7798 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7799
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007800 /* clean up config */
7801 f_ts_set_chcomb(0, 0, 6, "PDCH");
7802
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007803 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007804}
7805
7806
7807/***********************************************************************
7808 * Osmocom style dynamic PDCH
7809 ***********************************************************************/
7810
7811private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7812 template (omit) RSL_Cause nack := omit)
7813runs on test_CT {
7814 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7815 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007816 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007817 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7818 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007819 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT(chan_nr, ?));
Harald Welte94e0c342018-04-07 11:33:23 +02007820 if (istemplatekind(nack, "omit")) {
7821 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007822 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02007823 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007824 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007825 }
7826}
7827
7828private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7829 template (omit) RSL_Cause nack := omit)
7830runs on test_CT {
7831 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7832 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007833 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007834 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7835 /* expect the BSC to issue the related RSL command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007836 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007837 if (istemplatekind(nack, "omit")) {
7838 /* respond with a related acknowledgement */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007839 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007840 } else {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007841 //f_ipa_tx(ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
Harald Welte94e0c342018-04-07 11:33:23 +02007842 }
7843}
7844
7845/* Test Osmocom dyn PDCH activation / deactivation triggered by VTY */
7846testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
7847 var RSL_Message rsl_unused;
7848
7849 /* change Timeslot 6 before f_init() starts RSL */
7850 f_init_vty();
7851 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
7852 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7853
7854 f_init(1, false);
7855 f_sleep(1.0);
7856
7857 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
7858
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007859 log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007860 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
7861 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007862 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007863
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007864 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Harald Welte94e0c342018-04-07 11:33:23 +02007865 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007866 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 +02007867 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7868
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007869 /* clean up config */
7870 f_ts_set_chcomb(0, 0, 6, "PDCH");
7871
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007872 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007873}
7874
7875/* Test Osmocom dyn PDCH activation NACK behavior */
7876testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
7877 var RSL_Message rsl_unused;
7878
7879 /* change Timeslot 6 before f_init() starts RSL */
7880 f_init_vty();
7881 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
7882 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7883
7884 f_init(1, false);
7885 f_sleep(1.0);
7886
7887 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
7888
7889 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
7890 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007891 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007892
7893 /* NACK this activation and expect the "show timeslot" mode still to be NONE */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007894 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
Harald Welte94e0c342018-04-07 11:33:23 +02007895 f_sleep(1.0);
7896 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
7897
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007898 /* clean up config */
7899 f_ts_set_chcomb(0, 0, 6, "PDCH");
7900
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007901 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007902}
7903
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007904/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
7905testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
7906 var RSL_Message rsl_unused, rsl_msg;
7907 var DchanTuple dt;
7908 var BSSAP_N_CONNECT_ind rx_c_ind;
7909
7910 /* change Timeslot 6 before f_init() starts RSL */
7911 f_init_vty();
7912 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
7913 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7914
7915 f_init(1, false);
7916 f_sleep(1.0);
7917
7918 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
7919
7920 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
7921 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
7922 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007923 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007924
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007925 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007926 f_sleep(1.0);
7927 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
7928 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7929
7930 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
7931 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007932 var DchanTuples sdcch_cleanup := {};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007933 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02007934 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007935 dt := f_est_dchan('23'O, i, '00010203040506'O);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007936 sdcch_cleanup := sdcch_cleanup & { dt };
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007937 }
7938
7939 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007940 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
7941 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
7942 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007943
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007944 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007945 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007946 dt.idx := {0, 0};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007947
7948 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007949 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
7950 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007951 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
7952
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007953 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 +02007954 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
7955 dt.sccp_conn_id := rx_c_ind.connectionId;
7956 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
7957
7958 /* Instruct BSC to clear channel */
7959 var BssmapCause cause := 0;
7960 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007961 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007962
7963 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06007964 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
7965 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007966 f_sleep(1.0);
7967 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7968
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007969 /* Clean up SDCCH lchans */
7970 for (i := 0; i < lengthof(sdcch_cleanup); i := i + 1) {
7971 f_perform_clear_test_ct(sdcch_cleanup[i]);
7972 }
7973
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007974 /* clean up config */
7975 f_ts_set_chcomb(0, 0, 6, "PDCH");
7976
7977 f_shutdown_helper();
7978}
7979
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007980/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
7981testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
7982 var ASP_RSL_Unitdata rsl_ud;
7983 var integer i;
7984 var integer chreq_total, chreq_nochan;
7985
7986 f_init_vty();
7987 for (i := 1; i < 8; i := i + 1) {
7988 if (i == 2) {
7989 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
7990 } else {
7991 f_ts_set_chcomb(0, 0, i, "PDCH");
7992 }
7993 }
7994 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7995
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007996 f_init(1, guard_timeout := 60.0);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007997
7998 /* The dyn TS want to activate PDCH mode, ACK that. */
7999 var RslChannelNr chan_nr;
8000 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008001 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
8002 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008003
8004 f_sleep(1.0);
8005
8006 /* Exhaust all dedicated SDCCH lchans.
8007 /* GSM 44.018 Table 9.1.8.2:
8008 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
8009 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008010 var DchanTuples chan_cleanup := {};
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008011 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008012 chan_cleanup := chan_cleanup & { f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008013 }
8014
8015 /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008016 chan_cleanup := chan_cleanup & { f_est_dchan_dyn('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008017 /* Also occupy the seven other SDCCH of the dyn TS */
8018 for (i := 0; i < 7; i := i+1) {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008019 chan_cleanup := chan_cleanup & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
8020 }
8021
8022 /* Clean up SDCCH lchans */
8023 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8024 f_perform_clear_test_ct(chan_cleanup[i]);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02008025 }
8026
8027 /* clean up config */
8028 f_ts_reset_chcomb(0);
8029
8030 f_shutdown_helper();
8031}
8032
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008033/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
8034 SDCCH8 would end up in having no free TCH, then BSC should decide to activate
8035 it as TCH directly instead. SYS#5309. */
8036testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
8037 var RSL_Message rsl_unused, rsl_msg;
8038 var DchanTuple dt;
8039 var BSSAP_N_CONNECT_ind rx_c_ind;
8040 var integer i;
8041
8042 /* change Timeslot 6 before f_init() starts RSL */
8043 f_init_vty();
8044 for (i := 1; i < 8; i := i + 1) {
8045 if (i == 6) {
8046 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
8047 } else {
8048 f_ts_set_chcomb(0, 0, i, "PDCH");
8049 }
8050 }
8051 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8052
8053 f_init(1, false);
8054 f_sleep(1.0);
8055
8056 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8057
8058 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8059 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8060 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008061 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008062
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008063 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008064 f_sleep(1.0);
8065 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8066 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8067
8068 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8069 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008070 var DchanTuples chan_cleanup := {};
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02008071 var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008072 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02008073 dt := f_est_dchan(ra, i, '00010203040506'O);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008074 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008075 }
8076
8077 /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008078 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
8079 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8080 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008081
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008082 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008083 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008084 dt.idx := {0, 0};
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008085
8086 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008087 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
8088 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008089 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
8090
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008091 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 +02008092 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
8093 dt.sccp_conn_id := rx_c_ind.connectionId;
8094 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
8095
8096 /* Instruct BSC to clear channel */
8097 var BssmapCause cause := 0;
8098 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008099 f_exp_chan_rel_and_clear(dt);
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008100
8101 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008102 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8103 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008104 f_sleep(1.0);
8105 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8106
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008107 /* Clean up SDCCH lchans */
8108 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8109 f_perform_clear_test_ct(chan_cleanup[i]);
8110 }
8111
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02008112 /* clean up config */
8113 f_ts_reset_chcomb(0);
8114 /* TODO: clean up other channels? */
8115
8116 f_shutdown_helper();
8117}
8118
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008119/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
8120testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
8121 var RSL_Message rsl_unused, rsl_msg;
8122 var DchanTuple dt;
8123 var BSSAP_N_CONNECT_ind rx_c_ind;
8124 var GsmRrMessage rr;
8125
8126 /* change Timeslot 6 before f_init() starts RSL */
8127 f_init_vty();
8128 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
8129 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8130
8131 f_init(1, false);
8132 f_sleep(1.0);
8133
8134 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
8135
8136 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
8137 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
8138 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008139 rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008140
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008141 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008142 f_sleep(1.0);
8143 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
8144 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
8145
8146 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
8147 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008148 var DchanTuples chan_cleanup := {};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008149 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02008150 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008151 dt := f_est_dchan('23'O, i, '00010203040506'O);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008152 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008153 }
8154
8155 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008156 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
8157 rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
8158 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008159
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008160 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008161 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008162 dt.idx := {0, 0};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008163
8164 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008165 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
8166 rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008167 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
8168 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
8169 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
8170 }
8171
8172 /* FIXME? Currently the TS stays in state BORKEN: */
8173
8174 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008175 /* rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
8176 * f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008177 * f_sleep(1.0);
8178 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
8179 */
8180
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008181 /* Clean up SDCCH lchans */
8182 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
8183 f_perform_clear_test_ct(chan_cleanup[i]);
8184 }
8185
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02008186 /* clean up config */
8187 f_ts_set_chcomb(0, 0, 6, "PDCH");
8188
8189 f_shutdown_helper();
8190}
8191
Stefan Sperling0796a822018-10-05 13:01:39 +02008192testcase TC_chopped_ipa_ping() runs on test_CT {
Stefan Sperling554123f2018-10-09 14:12:30 +02008193 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port, mp_bsc_ctrl_port};
Stefan Sperling0796a822018-10-05 13:01:39 +02008194 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8195 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8196 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008197 f_shutdown_helper();
Stefan Sperling0796a822018-10-05 13:01:39 +02008198}
8199
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008200testcase TC_chopped_ipa_payload() runs on test_CT {
8201 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port
8202 /* TODO: mp_bsc_ctrl_port does not work yet */};
8203 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
8204 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
8205 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008206 f_shutdown_helper();
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008207}
8208
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008209/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
8210 the BTS does autonomous MS power control loop */
8211testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
8212 var MSC_ConnHdlr vc_conn;
8213 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8214 //pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
8215 pars.exp_ms_power_params := true;
8216
8217 f_init(1, true);
8218 f_sleep(1.0);
8219 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
8220 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008221 f_shutdown_helper();
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01008222}
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02008223
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008224/* Verify activation and deactivation of the BCCH carrier power reduction mode */
8225testcase TC_c0_power_red_mode() runs on test_CT {
8226 f_init(1);
8227
8228 for (var integer red := 6; red >= 0; red := red - 2) {
8229 /* Configure BCCH carrier power reduction mode via the VTY */
8230 f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
8231
8232 /* Expect Osmocom specific BS Power Control message on the RSL */
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +03008233 var template (present) RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008234 chan_nr := t_RslChanNr_BCCH(0),
8235 bs_power := tr_RSL_IE_BS_Power(red / 2));
8236 tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008237 var RSL_Message unused := f_exp_ipa_rx(tr_rsl_pdu);
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02008238
8239 /* Additionally verify the applied value over the CTRL interface */
8240 var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
8241 if (cred != int2str(red)) {
8242 setverdict(fail, "Unexpected BCCH carrier power reduction value ",
8243 cred, " (expected ", red, ")");
8244 }
8245 }
8246
8247 f_shutdown_helper();
8248}
8249
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008250/***********************************************************************
8251 * MSC Pooling
8252 ***********************************************************************/
8253
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008254template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
Harald Weltebf397612021-01-14 20:39:46 +01008255 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 +02008256
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008257private 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 +02008258runs on MSC_ConnHdlr {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008259 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008260 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008261 f_logp(BSCVTY, "Got RSL RR Release");
8262 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008263 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008264 f_logp(BSCVTY, "Got RSL Deact SACCH");
8265 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008266 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008267 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008268 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8269 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02008270 break;
8271 }
8272 }
8273}
8274
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008275private altstep as_mgcp_ack_all_dlcx() runs on MSC_ConnHdlr {
8276 var MgcpCommand mgcp_cmd;
8277 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
8278 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
8279 repeat;
8280 }
8281}
8282
8283private altstep as_rsl_ack_all_rel_req() runs on MSC_ConnHdlr {
8284 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
8285 [] RSL.receive(tr_RSL_REL_REQ(g_chan_nr, ?)) {
8286 RSL.send(ts_RSL_REL_CONF(g_chan_nr, main_dcch));
8287 repeat;
8288 }
8289}
8290
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008291friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
8292 template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02008293runs on MSC_ConnHdlr {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008294 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8295 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008296 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008297 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8298 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008299 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008300 f_logp(BSCVTY, "Got RSL RR Release");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008301 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008302 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008303 f_logp(BSCVTY, "Got RSL Deact SACCH");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008304 }
8305 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008306 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008307 /* Also drop the SCCP connection */
8308 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8309 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02008310 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008311 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008312 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8313 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008314 }
8315 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01008316 deactivate(ack_dlcx);
8317 deactivate(ack_rel_req);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008318}
8319
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01008320friend function f_perform_clear_no_rr_rel(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC)
8321runs on MSC_ConnHdlr {
8322 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
8323 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
8324 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8325 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8326 interleave {
8327 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
8328 f_logp(BSCVTY, "Got RSL Deact SACCH");
8329 }
8330 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
8331 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8332 /* Also drop the SCCP connection */
8333 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8334 }
8335 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
8336 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
8337 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
8338 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
8339 }
8340 }
8341 deactivate(ack_dlcx);
8342 deactivate(ack_rel_req);
8343}
8344
Neels Hofmeyr907b23b2022-02-17 21:58:47 +01008345friend function f_perform_clear_no_lchan()
8346runs on MSC_ConnHdlr {
8347 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
8348 BSSAP.send(ts_BSSMAP_ClearCommand(0));
8349 BSSAP.receive(tr_BSSMAP_ClearComplete);
8350 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
8351 /* Also drop the SCCP connection */
8352 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
8353}
8354
Vadim Yanitskiy65d879d2022-06-23 18:15:39 +07008355friend function f_perform_clear_test_ct(DchanTuple dt)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008356 runs on test_CT
8357{
8358 /* Instruct BSC to clear channel */
8359 var BssmapCause cause := 0;
8360 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06008361 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008362}
8363
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008364private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
8365 template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008366runs on MSC_ConnHdlr {
8367 timer T := 10.0;
8368 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
8369
Neels Hofmeyr767548a2020-08-09 20:26:07 +00008370 f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008371 f_create_bssmap_exp(l3_enc);
8372
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008373 /* RSL_Emulation.f_chan_est() on rsl_pt:
8374 * This is basically code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008375 * RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
8376 */
8377 var RSL_Message rx_rsl;
8378 var GsmRrMessage rr;
8379
8380 /* request a channel to be established */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008381 rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008382 /* expect immediate assignment.
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008383 * Code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008384 * rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
8385 */
8386 timer Tt := 10.0;
8387
8388 /* request a channel to be established */
8389 Tt.start;
8390 alt {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008391 [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008392 Tt.stop;
8393 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008394 [] rsl_pt.receive {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008395 setverdict(fail, "Unexpected RSL message on DCHAN");
8396 mtc.stop;
8397 }
8398 [] Tt.timeout {
8399 setverdict(fail, "Timeout waiting for RSL on DCHAN");
8400 mtc.stop;
8401 }
8402 }
8403 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
8404 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008405 rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008406
8407
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008408 if (expect_bssmap_l3) {
8409 f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
8410 var template PDU_BSSAP exp_l3_compl;
8411 exp_l3_compl := tr_BSSMAP_ComplL3()
8412 if (g_pars.aoip == false) {
8413 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
8414 } else {
8415 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
8416 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008417
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008418 var PDU_BSSAP bssap;
8419 T.start;
8420 alt {
8421 [] BSSAP.receive(exp_l3_compl) -> value bssap {
8422 f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
8423 log("rx exp_l3_compl = ", bssap);
8424 }
8425 [] BSSAP.receive(tr_BSSMAP_ComplL3) {
8426 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
8427 }
8428 [] T.timeout {
8429 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
8430 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008431 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008432
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008433 /* start ciphering, if requested */
8434 if (ispresent(g_pars.encr)) {
8435 f_logp(BSCVTY, "start ciphering");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008436 f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008437 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008438 }
8439
8440 if (do_clear) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008441 f_perform_clear(rsl_pt, rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008442 }
8443 setverdict(pass);
8444 f_sleep(1.0);
8445}
8446
8447private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
8448 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8449 if (g_pars.mscpool.rsl_idx == 0) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008450 f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008451 } else if (g_pars.mscpool.rsl_idx == 1) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008452 f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008453 } else if (g_pars.mscpool.rsl_idx == 2) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008454 f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008455 }
8456}
8457
8458/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
8459private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
8460 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008461 f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
8462 f_perform_compl_l3(RSL, RSL_PROC, ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_IMSI_LV('001010000000002'H))) );
8463 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))) );
8464 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 +02008465}
8466testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
8467
8468 f_init(1, true);
8469 f_sleep(1.0);
8470 var MSC_ConnHdlr vc_conn;
8471 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008472
8473 f_ctrs_msc_init();
8474
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008475 vc_conn := f_start_handler(refers(f_tc_mscpool_L3Compl_on_1_msc), pars);
8476 vc_conn.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008477
8478 f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008479 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008480}
8481
8482/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
8483/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8484 * just as well using only RSL. */
8485testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
8486
8487 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8488 f_sleep(1.0);
8489
8490 /* Control which MSC gets chosen next by the round-robin, otherwise
8491 * would be randomly affected by which other tests ran before this. */
8492 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8493
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008494 f_ctrs_msc_init();
8495
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008496 var MSC_ConnHdlr vc_conn1;
8497 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8498 pars1.mscpool.rsl_idx := 0;
8499 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8500 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8501 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008502 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008503
8504 var MSC_ConnHdlr vc_conn2;
8505 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8506 pars2.mscpool.rsl_idx := 1;
8507 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8508 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8509 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008510 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008511
8512 /* Test round-robin wrap to the first MSC */
8513 var MSC_ConnHdlr vc_conn3;
8514 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8515 pars3.mscpool.rsl_idx := 2;
8516 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
8517 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8518 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008519 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008520 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008521}
8522
8523/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 0
8524 * (configured in osmo-bsc.cfg). */
8525/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8526 * just as well using only RSL. */
8527testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
8528
8529 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8530 f_sleep(1.0);
8531
8532 /* Control which MSC gets chosen next by the round-robin, otherwise
8533 * would be randomly affected by which other tests ran before this. */
8534 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8535
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008536 f_ctrs_msc_init();
8537
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008538 var MSC_ConnHdlr vc_conn1;
8539 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8540 pars1.mscpool.rsl_idx := 0;
8541 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8542 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8543 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008544 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008545
8546 var MSC_ConnHdlr vc_conn2;
8547 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8548 pars2.mscpool.rsl_idx := 1;
8549 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8550 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8551 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008552 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008553
8554 /* Test round-robin wrap to the first MSC */
8555 var MSC_ConnHdlr vc_conn3;
8556 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8557 pars3.mscpool.rsl_idx := 2;
8558 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8559 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8560 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008561 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008562 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008563}
8564
8565/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
8566 * (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
8567 * NULL-NRI setting is stronger than that. */
8568/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8569 * just as well using only RSL. */
8570testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
8571
8572 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8573 f_sleep(1.0);
8574
8575 /* Control which MSC gets chosen next by the round-robin, otherwise
8576 * would be randomly affected by which other tests ran before this. */
8577 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8578
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008579 f_ctrs_msc_init();
8580
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008581 var MSC_ConnHdlr vc_conn1;
8582 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8583 pars1.mscpool.rsl_idx := 0;
8584 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8585 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8586 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008587 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008588
8589 var MSC_ConnHdlr vc_conn2;
8590 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8591 pars2.mscpool.rsl_idx := 1;
8592 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8593 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8594 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008595 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008596
8597 /* Test round-robin wrap to the first MSC */
8598 var MSC_ConnHdlr vc_conn3;
8599 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8600 pars3.mscpool.rsl_idx := 2;
8601 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
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:reattach");
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 not
8609 * assigned to any MSC (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_unassigned_nri_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 not assigned to any MSC */
8627 pars1.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(1023))));
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_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008631
8632 var MSC_ConnHdlr vc_conn2;
8633 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8634 pars2.mscpool.rsl_idx := 1;
8635 /* An NRI that is not assigned to any MSC */
8636 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(768)), '00F110'O));
8637 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8638 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008639 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008640
8641 /* Test round-robin wrap to the first MSC */
8642 var MSC_ConnHdlr vc_conn3;
8643 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8644 pars3.mscpool.rsl_idx := 2;
8645 /* An NRI that is not assigned to any MSC */
8646 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, valueof(ts_MI_TMSI_NRI_LV(819))));
8647 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8648 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008649 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008650 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008651}
8652
8653/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
8654 * assigned to an MSC that is currently not connected (configured in osmo-bsc.cfg). */
8655/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8656 * just as well using only RSL. */
8657testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
8658
8659 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8660 f_sleep(1.0);
8661
8662 /* Control which MSC gets chosen next by the round-robin, otherwise
8663 * would be randomly affected by which other tests ran before this. */
8664 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8665
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008666 f_ctrs_msc_init();
8667
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008668 var MSC_ConnHdlr vc_conn1;
8669 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8670 pars1.mscpool.rsl_idx := 0;
8671 /* An NRI that is assigned to an unconnected MSC */
8672 pars1.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(512))));
8673 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8674 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008675 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8676 f_ctrs_msc_add(0, "mscpool:subscr:new");
8677 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008678
8679 var MSC_ConnHdlr vc_conn2;
8680 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8681 pars2.mscpool.rsl_idx := 1;
8682 /* An NRI that is assigned to an unconnected MSC */
8683 pars2.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(767))));
8684 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8685 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008686 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8687 f_ctrs_msc_add(1, "mscpool:subscr:new");
8688 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008689
8690 /* Test round-robin wrap to the first MSC */
8691 var MSC_ConnHdlr vc_conn3;
8692 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8693 pars3.mscpool.rsl_idx := 2;
8694 /* An NRI that is assigned to an unconnected MSC */
8695 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(750)), '00F110'O));
8696 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8697 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008698 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8699 f_ctrs_msc_add(0, "mscpool:subscr:new");
8700 f_ctrs_msc_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008701 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008702}
8703
8704/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
8705 * osmo-bsc.cfg). */
8706/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8707 * just as well using only RSL. */
8708testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
8709
8710 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8711 f_sleep(1.0);
8712
8713 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
8714 * this is not using round-robin. */
8715 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8716
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008717 f_ctrs_msc_init();
8718
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008719 var MSC_ConnHdlr vc_conn1;
8720 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8721 pars1.mscpool.rsl_idx := 0;
8722 /* An NRI of the second MSC's range (256-511) */
8723 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(256))));
8724 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8725 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008726 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008727
8728 var MSC_ConnHdlr vc_conn2;
8729 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8730 pars2.mscpool.rsl_idx := 1;
8731 /* An NRI of the second MSC's range (256-511) */
8732 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(260))));
8733 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8734 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008735 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008736
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 /* An NRI of the second MSC's range (256-511) */
8741 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(511)), '00F110'O));
8742 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8743 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008744 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008745 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008746}
8747
8748/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
8749 * while a round-robin remains unaffected by that. */
8750/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8751 * just as well using only RSL. */
8752testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
8753
8754 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8755 f_sleep(1.0);
8756
8757 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
8758 * this is not using round-robin. */
8759 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8760
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008761 f_ctrs_msc_init();
8762
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008763 var MSC_ConnHdlr vc_conn1;
8764 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 2);
8765 pars1.mscpool.rsl_idx := 0;
8766 /* An NRI of the third MSC's range (512-767) */
8767 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(512))));
8768 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8769 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008770 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008771
8772 var MSC_ConnHdlr vc_conn2;
8773 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8774 pars2.mscpool.rsl_idx := 1;
8775 /* An NRI of the third MSC's range (512-767) */
8776 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(678))));
8777 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8778 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008779 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008780
8781 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
8782 var MSC_ConnHdlr vc_conn3;
8783 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8784 pars3.mscpool.rsl_idx := 2;
8785 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000013'H)), '00F110'O));
8786 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8787 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008788 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008789 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008790}
8791
8792/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
8793/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8794 * just as well using only RSL. */
8795testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
8796
8797 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8798 f_sleep(1.0);
8799
8800 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
8801 * instead, and hits msc 0. */
8802 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8803
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008804 f_ctrs_msc_init();
8805
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008806 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-bsc.cfg */
8807 var MSC_ConnHdlr vc_conn1;
8808 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8809 pars1.mscpool.rsl_idx := 0;
8810 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(260)), '99F999'O));
8811 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8812 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008813 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008814
8815 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
8816 var MSC_ConnHdlr vc_conn2;
8817 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8818 pars2.mscpool.rsl_idx := 1;
8819 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(555)), '00F110'O));
8820 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8821 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008822 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008823 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008824}
8825
8826/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
8827 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
8828private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
8829 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
8830 //cid_list := { cIl_allInBSS := ''O };
8831 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
8832 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
8833 var BSSAP_N_UNITDATA_req paging;
8834 var hexstring imsi := '001010000000123'H;
8835
8836 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8837
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008838 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008839 valueof(ts_BSSMAP_Paging(imsi, cid_list, omit, bssmap_chneed))));
8840 BSSAP.send(paging);
8841
8842 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
8843 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
8844 * channel number is picked here. */
8845 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
8846 f_rslem_register(0, new_chan_nr);
8847 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(imsi)));
8848 f_rslem_unregister(0, new_chan_nr);
8849
8850 /* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
8851 * causes this Paging Response to go to the first MSC (bssap_idx := 0). */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008852 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV(imsi))) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008853 f_sleep(1.0);
8854}
8855testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
8856 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
8857 f_sleep(1.0);
8858
8859 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
8860 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
8861 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8862
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008863 f_ctrs_msc_init();
8864
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008865 var MSC_ConnHdlr vc_conn1;
8866 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8867 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008868 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
8869 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008870 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
8871 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008872 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008873 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008874}
8875
8876/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
8877 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
8878private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
8879 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
8880 //cid_list := { cIl_allInBSS := ''O };
8881 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
8882 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
8883 var integer nri_v := 300; /* <-- second MSC's NRI */
Harald Weltebf397612021-01-14 20:39:46 +01008884 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008885 var BSSAP_N_UNITDATA_req paging;
8886
8887 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8888
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008889 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008890 valueof(ts_BSSMAP_Paging('001010000000011'H, cid_list, tmsi, bssmap_chneed))));
8891 BSSAP.send(paging);
8892
8893 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
8894 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
8895 * channel number is picked here. */
8896 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
8897 f_rslem_register(0, new_chan_nr);
8898 RSL.receive(tr_RSL_PAGING_CMD(t_MI_TMSI(tmsi)));
8899 f_rslem_unregister(0, new_chan_nr);
8900
8901 /* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
8902 * third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
8903 * the first MSC (bssap_idx := 0). */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008904 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 +02008905 f_sleep(1.0);
8906}
8907testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
8908 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
8909 f_sleep(1.0);
8910
8911 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
8912 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
8913 f_vty_transceive(BSCVTY, "mscpool roundrobin next 2");
8914
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008915 f_ctrs_msc_init();
8916
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008917 var MSC_ConnHdlr vc_conn1;
8918 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8919 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008920 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
8921 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008922 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
8923 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008924 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008925 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008926}
8927
8928/* For round-robin, skip an MSC that has 'no allow-attach' set. */
8929/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8930 * just as well using only RSL. */
8931testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
8932
8933 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8934 f_sleep(1.0);
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00008935 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
8936 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008937
8938 /* Control which MSC gets chosen next by the round-robin, otherwise
8939 * would be randomly affected by which other tests ran before this. */
8940 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8941
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008942 f_ctrs_msc_init();
8943
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008944 var MSC_ConnHdlr vc_conn1;
8945 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8946 pars1.mscpool.rsl_idx := 0;
8947 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8948 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8949 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008950 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008951
8952 var MSC_ConnHdlr vc_conn2;
8953 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8954 pars2.mscpool.rsl_idx := 1;
8955 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8956 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8957 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008958 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008959
8960 var MSC_ConnHdlr vc_conn3;
8961 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8962 pars3.mscpool.rsl_idx := 2;
8963 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
8964 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8965 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008966 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008967 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008968}
8969
8970/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
8971 * TMSI NRI. */
8972testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
8973
8974 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8975 f_sleep(1.0);
8976
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00008977 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
8978 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
8979
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008980 /* Control which MSC gets chosen next by the round-robin, otherwise
8981 * would be randomly affected by which other tests ran before this. */
8982 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8983
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008984 f_ctrs_msc_init();
8985
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008986 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
8987 var MSC_ConnHdlr vc_conn1;
8988 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8989 pars1.mscpool.rsl_idx := 0;
8990 /* An NRI of the second MSC's range (256-511) */
8991 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_TMSI_NRI_LV(260))));
8992 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8993 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008994 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008995
8996 var MSC_ConnHdlr vc_conn2;
8997 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
8998 pars2.mscpool.rsl_idx := 1;
8999 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
9000 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
9001 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009002 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009003
9004 var MSC_ConnHdlr vc_conn3;
9005 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 2);
9006 pars3.mscpool.rsl_idx := 2;
9007 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000003'H))));
9008 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
9009 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02009010 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009011 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02009012}
9013
Philipp Maier783681c2020-07-16 16:47:06 +02009014/* Allow/Deny emergency calls globally via VTY */
9015private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
9016 f_vty_enter_cfg_msc(BSCVTY, 0);
9017 if (allow) {
9018 f_vty_transceive(BSCVTY, "allow-emergency allow");
9019 } else {
9020 f_vty_transceive(BSCVTY, "allow-emergency deny");
9021 }
9022 f_vty_transceive(BSCVTY, "exit");
9023 f_vty_transceive(BSCVTY, "exit");
9024}
9025
9026/* Allow/Deny emergency calls per BTS via VTY */
9027private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
9028 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9029 if (allow) {
9030 f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
9031 } else {
9032 f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
9033 }
9034 f_vty_transceive(BSCVTY, "exit");
9035 f_vty_transceive(BSCVTY, "exit");
Neels Hofmeyrb6ed80c2020-10-12 22:52:39 +00009036 f_vty_transceive(BSCVTY, "exit");
Philipp Maier783681c2020-07-16 16:47:06 +02009037}
9038
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02009039/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
9040private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
9041 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9042 if (allow) {
9043 f_vty_transceive(BSCVTY, "srvcc fast-return allow");
9044 } else {
9045 f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
9046 }
9047 f_vty_transceive(BSCVTY, "exit");
9048 f_vty_transceive(BSCVTY, "exit");
9049 f_vty_transceive(BSCVTY, "exit");
9050}
9051
Pau Espin Pedrol14475352021-07-22 15:48:16 +02009052/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
9053private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
9054 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9055 if (allow) {
9056 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
9057 } else {
9058 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
9059 }
9060 f_vty_transceive(BSCVTY, "exit");
9061 f_vty_transceive(BSCVTY, "exit");
9062 f_vty_transceive(BSCVTY, "exit");
9063}
9064
Philipp Maier783681c2020-07-16 16:47:06 +02009065/* Begin assignmet procedure and send an EMERGENCY SETUP (RR) */
9066private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
9067 var PDU_ML3_MS_NW emerg_setup;
9068 var octetstring emerg_setup_enc;
9069 var RSL_Message emerg_setup_data_ind;
9070
9071 f_establish_fully(omit, omit);
9072
9073 emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
9074 emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
9075 emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
9076
9077 RSL.send(emerg_setup_data_ind);
9078}
9079
9080/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
9081 * CALLS are permitted by the BSC config. */
9082private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
9083 var PDU_BSSAP emerg_setup_data_ind_bssap;
9084 var PDU_ML3_MS_NW emerg_setup;
9085 timer T := 3.0;
9086
9087 f_assignment_emerg_setup()
9088
9089 T.start;
9090 alt {
9091 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
9092 emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
9093 if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
9094 setverdict(fail, "no emergency setup");
9095 }
9096 }
9097 [] BSSAP.receive {
9098 setverdict(fail, "unexpected BSSAP message!");
9099 }
9100 [] T.timeout {
9101 setverdict(fail, "timout waiting for EMERGENCY SETUP!");
9102 }
9103 }
9104
9105 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009106 f_perform_clear();
Philipp Maier783681c2020-07-16 16:47:06 +02009107}
9108
9109/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
9110 * forbidden by the BSC config. */
9111private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
9112 var PDU_BSSAP emerg_setup_data_ind_bssap;
9113 timer T := 3.0;
9114
9115 f_assignment_emerg_setup()
9116
9117 T.start;
9118 alt {
9119 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
9120 setverdict(pass);
9121 }
9122 [] RSL.receive {
9123 setverdict(fail, "unexpected RSL message!");
9124 }
9125 [] T.timeout {
9126 setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
9127 }
9128 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009129 BSSAP.receive(tr_BSSMAP_ClearRequest);
Neels Hofmeyrc3c6ee62022-01-26 01:22:12 +01009130 f_perform_clear_no_rr_rel();
Philipp Maier783681c2020-07-16 16:47:06 +02009131}
9132
9133/* EMERGENCY CALL situation #1, allowed globally and by BTS */
9134testcase TC_assignment_emerg_setup_allow() runs on test_CT {
9135 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9136 var MSC_ConnHdlr vc_conn;
9137
9138 f_init(1, true);
9139 f_sleep(1.0);
9140
9141 f_vty_allow_emerg_msc(true);
9142 f_vty_allow_emerg_bts(true, 0);
9143 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
9144 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009145 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009146}
9147
9148/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
9149testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
9150 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9151 var MSC_ConnHdlr vc_conn;
9152
9153 f_init(1, true);
9154 f_sleep(1.0);
9155
9156 f_vty_allow_emerg_msc(false);
9157 f_vty_allow_emerg_bts(true, 0);
9158 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9159 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009160 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009161}
9162
9163/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS */
9164testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
9165 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9166 var MSC_ConnHdlr vc_conn;
9167
9168 /* Note: This simulates a spec violation by the MS, correct MS
9169 * implementations would not try to establish an emergency call because
9170 * the system information tells in advance that emergency calls are
9171 * not forbidden */
9172
9173 f_init(1, true);
9174 f_sleep(1.0);
9175
9176 f_vty_allow_emerg_msc(true);
9177 f_vty_allow_emerg_bts(false, 0);
9178 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
9179 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009180 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02009181}
9182
Philipp Maier82812002020-08-13 18:48:27 +02009183/* Test what happens when an emergency call arrives while all TCH channels are
9184 * busy, the BSC is expected to terminate one call in favor of the incoming
9185 * emergency call */
9186testcase TC_emerg_premption() runs on test_CT {
9187 var ASP_RSL_Unitdata rsl_ud;
9188 var integer i;
9189 var integer chreq_total, chreq_nochan;
9190 var RSL_Message rx_rsl;
Philipp Maier82812002020-08-13 18:48:27 +02009191
9192 f_init(1);
9193 f_sleep(1.0);
9194
9195 f_vty_allow_emerg_msc(true);
9196 f_vty_allow_emerg_bts(true, 0);
9197
9198 /* Fill up all channels on the BTS */
9199 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
9200 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
9201 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 +02009202 f_chreq_act_ack('33'O, i);
Philipp Maier82812002020-08-13 18:48:27 +02009203 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009204 IPA_RSL[0][0].clear;
Philipp Maier82812002020-08-13 18:48:27 +02009205 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
9206 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
9207
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009208 /* Send EST IND for the first TCH, so we get to test the RR release cause */
9209 var RslChannelNr first_tch := valueof(t_RslChanNr_Bm(1));
9210 var octetstring l3 := '00010203040506'O;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009211 f_ipa_tx(ts_RSL_EST_IND(first_tch, valueof(ts_RslLinkID_DCCH(0)), l3));
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009212
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009213 /* Accept BSSAP conn, so we get to test the Clear Request cause */
9214 var BSSAP_N_CONNECT_ind rx_c_ind;
9215 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
9216 var integer sccp_conn_id := rx_c_ind.connectionId;
9217 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
9218
Philipp Maier82812002020-08-13 18:48:27 +02009219 /* Send Channel request for emegergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009220 f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
Philipp Maier82812002020-08-13 18:48:27 +02009221
9222 /* Expect the BSC to release one (the first) TCH/F on the BTS */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009223 f_expect_chan_rel(first_tch, expect_rr_chan_rel := true, expect_rll_rel_req := false,
Neels Hofmeyrace698c2022-04-24 00:30:21 +02009224 expect_rr_cause := GSM48_RR_CAUSE_PREMPTIVE_REL);
Philipp Maier82812002020-08-13 18:48:27 +02009225
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009226 /* Also expect a BSSMAP Clear Request with PREEMPTION */
9227 var BSSAP_N_DATA_ind rx_clear_req;
9228 const myBSSMAP_Cause preemption := GSM0808_CAUSE_PREEMPTION;
9229 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_clear_req;
9230 log("XXX ", rx_clear_req);
9231 if (rx_clear_req.userData.pdu.bssmap.clearRequest.cause.causeValue != int2bit(enum2int(preemption), 7)) {
9232 setverdict(fail, "BSSMAP Clear Request: expected cause PREEMPTION");
9233 }
9234
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009235 /* Expect the BSC to send activate/assign the channel for the emergency call */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009236 rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr32ef5912022-04-24 00:29:04 +02009237 if (first_tch != rx_rsl.ies[0].body.chan_nr) {
9238 setverdict(fail, "different TCH lchan activated than expected");
9239 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009240 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(first_tch, 33));
9241 rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Philipp Maier104f4c02020-09-11 18:12:18 +02009242
Neels Hofmeyrde564b12022-04-24 23:11:46 +02009243 /* complete the BSSMAP Clear to satisfy the conn leak check */
9244 BSSAP.send(ts_BSSAP_DATA_req(sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(preemption))));
9245 BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearComplete)) {
9246 BSSAP.send(ts_BSSAP_DISC_req(sccp_conn_id, 0));
9247 }
9248
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02009249 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009250}
9251
9252/* Hopping parameters per a timeslot */
Vadim Yanitskiybc6654a2020-09-13 01:27:40 +07009253private type record length(0..64) of GsmArfcn ArfcnList;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009254private type record FHParamsTs {
9255 boolean enabled,
9256 uint6_t hsn,
9257 uint6_t maio,
9258 ArfcnList ma
9259};
9260
9261/* Hopping parameters per a transceiver */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009262private type record FHParamsTrx {
Philipp Maier798d8952021-10-19 14:43:19 +02009263 GsmBandArfcn arfcn,
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009264 FHParamsTs ts[8]
9265};
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009266
9267/* Randomly generate the hopping parameters for the given timeslot numbers */
9268private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
9269runs on test_CT return FHParamsTrx {
9270 var FHParamsTrx fhp;
9271
Philipp Maier798d8952021-10-19 14:43:19 +02009272 /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
9273 * fall in the GSM900 band. */
9274 fhp.arfcn.arfcn := f_rnd_int(3);
9275 fhp.arfcn.pcs := false;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009276
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009277 for (var integer tn := 0; tn < 8; tn := tn + 1) {
9278 if (not match(tn, tr_tn)) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009279 fhp.ts[tn].enabled := false;
9280 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009281 continue;
9282 }
9283
9284 /* Random HSN / MAIO values: 0..63 */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009285 fhp.ts[tn].hsn := f_rnd_int(64);
9286 fhp.ts[tn].maio := f_rnd_int(64);
9287 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009288
9289 /* Random Mobile Allocation (hopping channels) */
9290 var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
9291 var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
9292 for (var integer i := 1; i <= ma_len; i := i + 1) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009293 fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009294 }
9295
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009296 fhp.ts[tn].enabled := true;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009297 }
9298
9299 log("f_TC_fh_params_gen(): ", fhp);
9300 return fhp;
9301}
9302
9303/* Make sure that the given Channel Description IE matches the hopping configuration */
9304private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
9305{
9306 var template (present) ChannelDescription tr_cd;
9307 var template (present) MaioHsn tr_maio_hsn;
9308 var uint3_t tn := cd.chan_nr.tn;
9309
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009310 if (fhp.ts[tn].enabled) {
9311 tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009312 tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
9313 } else {
Philipp Maier798d8952021-10-19 14:43:19 +02009314 tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009315 }
9316
9317 if (not match(cd, tr_cd)) {
9318 setverdict(fail, "Channel Description IE does not match: ",
9319 cd, " vs expected ", tr_cd);
9320 }
9321}
9322
9323/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
9324private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
9325 in MobileAllocationLV ma)
9326{
9327 var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
9328
9329 if (not match(ma, tr_ma)) {
9330 setverdict(fail, "Mobile Allocation IE does not match (tn := ",
9331 tn, "): ", ma, " vs expected: ", tr_ma);
9332 } else {
9333 setverdict(pass);
9334 }
9335}
9336
9337private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
9338 in MobileAllocationLV ma)
9339return template MobileAllocationLV {
9340 /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009341 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009342 return { len := 0, ma := ''B };
9343 }
9344
9345 var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
9346 var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
9347 var bitstring ma_mask := ''B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009348
9349 /* Compose the full bit-mask (all channels, up to 1024 entries) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009350 for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
9351 for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
9352 if (full_mask[fhp.ts[i].ma[j]] == '1'B)
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009353 { continue; }
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009354 full_mask[fhp.ts[i].ma[j]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009355 }
9356 }
9357
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009358 /* Take ARFCN of the TRX itself into account */
Philipp Maier798d8952021-10-19 14:43:19 +02009359 full_mask[fhp.arfcn.arfcn] := '1'B;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009360
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009361 /* Compose a bit-mask for the given timeslot number */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009362 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9363 slot_mask[fhp.ts[tn].ma[i]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009364 }
9365
9366 /* Finally, compose the Mobile Allocation bit-mask */
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009367 for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009368 if (full_mask[i] != '1'B)
9369 { continue; }
9370
9371 /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
9372 if (slot_mask[i] == '1'B) {
9373 ma_mask := ma_mask & '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009374 } else {
9375 ma_mask := ma_mask & '0'B;
9376 }
9377 }
9378
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07009379 /* ARFCN 0 (if present) goes to the last position of the bit-mask */
9380 if (full_mask[0] == '1'B) {
9381 /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
9382 if (slot_mask[0] == '1'B) {
9383 ma_mask := ma_mask & '1'B;
9384 } else {
9385 ma_mask := ma_mask & '0'B;
9386 }
9387 }
9388
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009389 /* Ensure that ma_mask is octet-aligned */
Vadim Yanitskiy2aa02522020-09-06 14:05:23 +07009390 var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009391 ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
9392
9393 return { len := ma_mask_len, ma := ma_mask };
9394}
9395
Philipp Maier798d8952021-10-19 14:43:19 +02009396/* Configure the appropriate band for a given arfcn, exc */
9397private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
9398{
9399 var charstring band;
9400 var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
9401
9402 select (arfcn_) {
9403 case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
9404 case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
9405 case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
9406 case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
9407 case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
9408 case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
9409 case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
9410 case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
9411 case else { return; }
9412 }
9413
9414 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
9415 f_vty_transceive(BSCVTY, "band " & band);
9416 f_vty_transceive(BSCVTY, "end");
9417}
9418
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009419/* Configure the hopping parameters in accordance with the given record */
9420private function f_TC_fh_params_set(in FHParamsTrx fhp,
9421 uint8_t bts_nr := 0,
9422 uint8_t trx_nr := 0)
9423runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009424
9425 f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
9426
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009427 /* Enter the configuration node for the given BTS/TRX numbers */
9428 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9429
Philipp Maier798d8952021-10-19 14:43:19 +02009430 f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009431
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009432 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009433 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9434
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009435 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009436 f_vty_transceive(BSCVTY, "hopping enabled 0");
9437 f_vty_transceive(BSCVTY, "exit"); /* go back */
9438 continue;
9439 }
9440
9441 /* Configure HSN / MAIO values */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009442 f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
9443 f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009444
9445 /* Configure the Mobile Allocation (hopping channels) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009446 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9447 f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009448 }
9449
9450 f_vty_transceive(BSCVTY, "hopping enabled 1");
9451 f_vty_transceive(BSCVTY, "exit"); /* go back */
9452 }
9453
9454 f_vty_transceive(BSCVTY, "end");
9455}
9456
9457/* Disable frequency hopping on all timeslots */
9458private function f_TC_fh_params_unset(in FHParamsTrx fhp,
9459 uint8_t bts_nr := 0,
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009460 uint8_t trx_nr := 0,
Philipp Maier798d8952021-10-19 14:43:19 +02009461 GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009462runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009463
9464 f_TC_set_band_by_arfcn(bts_nr, arfcn);
9465
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009466 /* Enter the configuration node for the given BTS/TRX numbers */
9467 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9468
Philipp Maier798d8952021-10-19 14:43:19 +02009469 f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009470
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009471 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009472 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9473
9474 /* Delete all ARFCNs from the Mobile Allocation (if any) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009475 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9476 f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009477 }
9478
9479 f_vty_transceive(BSCVTY, "hopping enabled 0");
9480 f_vty_transceive(BSCVTY, "exit"); /* go back */
9481 }
9482
9483 f_vty_transceive(BSCVTY, "end");
9484 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9485}
9486
9487/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
9488 * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
9489testcase TC_fh_params_chan_activ() runs on test_CT {
9490 var FHParamsTrx fhp := f_TC_fh_params_gen();
9491 var RSL_Message rsl_msg;
9492 var RSL_IE_Body ie;
9493
9494 f_init_vty();
9495
9496 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9497 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9498
9499 f_init(1);
9500
9501 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9502 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009503 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9504 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009505
9506 /* Make sure that Channel Identification IE is present */
9507 if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
9508 setverdict(fail, "RSL Channel Identification IE is absent");
9509 continue;
9510 }
9511
9512 /* Make sure that hopping parameters (HSN/MAIO) match */
9513 f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
9514
9515 /* "Mobile Allocation shall be included but empty" - let's check this */
9516 if (ie.chan_ident.ma.v.len != 0) {
9517 setverdict(fail, "Mobile Allocation IE is not empty: ",
9518 ie.chan_ident.ma, ", despite it shall be");
9519 continue;
9520 }
9521 }
9522
9523 /* Disable frequency hopping */
9524 f_TC_fh_params_unset(fhp);
9525
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009526 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009527}
9528
9529/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
9530testcase TC_fh_params_imm_ass() runs on test_CT {
9531 var FHParamsTrx fhp := f_TC_fh_params_gen();
9532 var RSL_Message rsl_msg;
9533 var RSL_IE_Body ie;
9534
9535 f_init_vty();
9536
9537 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9538 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9539
9540 f_init(1);
9541
9542 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9543 for (var integer i := 0; i < 9; i := i + 1) {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009544 f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9545 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009546
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009547 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9548 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009549
9550 /* Make sure that Full Immediate Assign Info IE is present */
9551 if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
9552 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
9553 continue;
9554 }
9555
9556 /* Decode the actual Immediate Assignment message */
9557 var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
9558 if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
9559 setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
9560 continue;
9561 }
9562
9563 /* Make sure that hopping parameters (HSN/MAIO) match */
9564 f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
9565
9566 /* Make sure that the Mobile Allocation IE matches */
9567 f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
9568 rr_msg.payload.imm_ass.mobile_allocation);
9569 }
9570
9571 /* Disable frequency hopping */
9572 f_TC_fh_params_unset(fhp);
Philipp Maier82812002020-08-13 18:48:27 +02009573
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009574 f_shutdown_helper();
Philipp Maier82812002020-08-13 18:48:27 +02009575}
9576
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009577/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
9578testcase TC_fh_params_assignment_cmd() runs on test_CT {
9579 var FHParamsTrx fhp := f_TC_fh_params_gen();
9580 var RSL_Message rsl_msg;
9581 var RSL_IE_Body ie;
9582
9583 f_init_vty();
9584
9585 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9586 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9587
9588 f_init(1);
9589
9590 /* HACK: work around "Couldn't find Expect for CRCX" */
9591 vc_MGCP.stop;
9592
9593 var template PDU_BSSAP ass_cmd := f_gen_ass_req();
9594 ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
9595
9596 /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
9597 * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
9598 for (var integer i := 0; i < 3; i := i + 1) {
9599 /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
9600 var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, f_rnd_octstring(16));
9601
9602 /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
9603 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009604 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009605
9606 /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009607 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9608 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009609
9610 /* Make sure that L3 Information IE is present */
9611 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9612 setverdict(fail, "RSL L3 Information IE is absent");
9613 continue;
9614 }
9615
9616 /* Decode the L3 message and make sure it is (RR) Assignment Command */
9617 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9618 if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
9619 setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
9620 continue;
9621 }
9622
9623 /* Make sure that hopping parameters (HSN/MAIO) match */
9624 var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
9625 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9626
9627 /* Make sure that Cell Channel Description IE is present if FH is enabled */
9628 if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
Vadim Yanitskiy38d069d2020-09-02 17:18:57 +07009629 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009630 continue;
9631 }
9632
9633 /* Make sure that the Mobile Allocation IE matches (if present) */
9634 var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
9635 if (chan_desc.h and ma_present) {
9636 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9637 l3_msg.payload.ass_cmd.mobile_allocation.v);
9638 } else if (chan_desc.h and not ma_present) {
9639 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9640 continue;
9641 } else if (not chan_desc.h and ma_present) {
9642 setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
9643 continue;
9644 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009645
9646 f_perform_clear_test_ct(dt);
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009647 }
9648
9649 /* Give the IUT some time to release all channels */
9650 f_sleep(3.0);
9651
9652 /* Disable frequency hopping */
9653 f_TC_fh_params_unset(fhp);
9654
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009655 f_shutdown_helper();
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009656}
9657
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009658/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
9659private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
9660runs on test_CT {
9661 var RSL_Message rsl_msg;
9662 var RSL_IE_Body ie;
9663 var DchanTuple dt;
9664
9665 /* Establish a dedicated channel, so we can trigger handover */
9666 dt := f_est_dchan(f_rnd_ra_cs(), 23, f_rnd_octstring(16));
Vadim Yanitskiyc18ff472021-11-18 20:15:37 +03009667 f_sleep(0.5);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009668
9669 /* Trigger handover from BTS0 to BTS1 */
9670 f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
9671 f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
9672
9673 /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009674 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx := {1, 0});
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009675
9676 /* ACKnowledge channel activation and expect (RR) Handover Command */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009677 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33), idx := {1, 0});
9678 rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009679
9680 /* Make sure that L3 Information IE is present */
9681 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9682 setverdict(fail, "RSL L3 Information IE is absent");
9683 return;
9684 }
9685
9686 /* Decode the L3 message and make sure it is (RR) Handover Command */
9687 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9688 if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
9689 setverdict(fail, "Failed to match Handover Command: ", l3_msg);
9690 return;
9691 }
9692
9693 /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
9694 var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
9695 if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
9696 setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
9697 return;
9698 }
9699
9700 /* Make sure that hopping parameters (HSN/MAIO) match */
9701 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9702
9703 /* Make sure that Cell Channel Description IE is present */
9704 if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
9705 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
9706 return;
9707 }
9708
9709 /* Make sure that the Mobile Allocation (after time) IE is present and matches */
9710 var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
9711 if (ma_present) {
9712 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9713 l3_msg.payload.ho_cmd.mobile_allocation.v);
9714 } else {
9715 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9716 return;
9717 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009718
9719 f_perform_clear_test_ct(dt);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009720}
9721testcase TC_fh_params_handover_cmd() runs on test_CT {
9722 var FHParamsTrx fhp := f_TC_fh_params_gen();
9723
9724 f_init_vty();
9725
9726 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
9727 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
9728
9729 f_vty_transceive(BSCVTY, "timeslot 0");
9730 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
9731 f_vty_transceive(BSCVTY, "exit"); /* go back */
9732
9733 f_vty_transceive(BSCVTY, "timeslot 1");
9734 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
9735 f_vty_transceive(BSCVTY, "end"); /* we're done */
9736
9737 f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
9738 f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
9739
9740 f_init(2);
9741
9742 f_TC_fh_params_handover_cmd(fhp);
9743
9744 /* Disable frequency hopping on BTS1 */
9745 f_TC_fh_params_unset(fhp, 1);
9746
9747 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
9748 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
9749
9750 f_vty_transceive(BSCVTY, "timeslot 0");
9751 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
9752 f_vty_transceive(BSCVTY, "exit"); /* go back */
9753
9754 f_vty_transceive(BSCVTY, "timeslot 1");
9755 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
9756 f_vty_transceive(BSCVTY, "end"); /* we're done */
9757
9758 f_shutdown_helper();
9759}
9760
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009761/* Verify the hopping parameters in System Information Type 4 */
9762testcase TC_fh_params_si4_cbch() runs on test_CT {
9763 var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
9764 var ASP_RSL_Unitdata rx_rsl_ud;
9765 timer T := 5.0;
9766
9767 f_init_vty();
9768
9769 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
9770 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
9771
9772 f_vty_transceive(BSCVTY, "timeslot 0");
9773 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
9774 f_vty_transceive(BSCVTY, "exit"); /* go back */
9775
9776 f_vty_transceive(BSCVTY, "timeslot 1");
9777 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
9778 f_vty_transceive(BSCVTY, "end"); /* we're done */
9779
9780 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9781 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9782
9783 f_init(1);
9784
9785 T.start;
9786 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009787 [] 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 +07009788 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
9789 var SystemInformation si := dec_SystemInformation(ie.other.payload);
9790
9791 /* Make sure that what we decoded is System Information Type 4 */
9792 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
9793 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
9794 repeat;
9795 }
9796
9797 /* Make sure that CBCH Channel Description IE is present */
9798 if (not ispresent(si.payload.si4.cbch_chan_desc)) {
9799 setverdict(fail, "CBCH Channel Description IE is absent");
9800 break;
9801 }
9802
9803 /* Finally, check the hopping parameters (HSN, MAIO) */
9804 var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
9805 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9806
9807 /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
9808 * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
9809 if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
9810 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9811 break;
9812 } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
9813 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9814 si.payload.si4.cbch_mobile_alloc.v);
9815 }
9816 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +06009817 [] IPA_RSL[0][0].receive { repeat; }
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009818 [] T.timeout {
9819 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
9820 }
9821 }
9822
9823 /* Disable frequency hopping */
9824 f_TC_fh_params_unset(fhp);
9825
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +07009826 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009827 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
9828
9829 f_vty_transceive(BSCVTY, "timeslot 0");
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +07009830 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009831 f_vty_transceive(BSCVTY, "exit"); /* go back */
9832
9833 f_vty_transceive(BSCVTY, "timeslot 1");
9834 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
9835 f_vty_transceive(BSCVTY, "end"); /* we're done */
9836
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009837 f_shutdown_helper();
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009838}
9839
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009840template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
9841 := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
9842
9843private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
9844 template (present) BSSLAP_PDU expect_bsslap)
9845{
9846 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
9847 if (not match(bsslap, expect_bsslap)) {
9848 log("EXPECTING BSSLAP: ", expect_bsslap);
9849 log("GOT BSSLAP: ", bsslap);
9850 setverdict(fail, "BSSLAP is not as expected");
9851 mtc.stop;
9852 }
9853 setverdict(pass);
9854}
9855
9856/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
9857const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
9858
9859private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
9860 var PDU_BSSAP_LE rx_bsslap;
9861 BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
9862 f_match_bsslap(rx_bsslap, expect_rx_bsslap);
9863}
9864
9865/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9866 * Request on Lb interface. Either with or without the SMLC doing a BSSLAP TA Request. */
9867private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
9868 f_sleep(1.0);
9869
9870 f_establish_fully(omit, omit);
9871 f_bssap_le_register_imsi(g_pars.imsi, omit);
9872
9873 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9874 ts_CellId_CGI('262'H, '42'H, 23, 42))));
9875
9876 var PDU_BSSAP_LE plr;
9877 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9878
9879 if (not do_ta_request) {
9880 /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
9881 var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
9882 if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
9883 log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
9884 log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
9885 setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
9886 mtc.stop;
9887 }
9888 var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
9889 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
9890 if (not match(bsslap, expect_ta_layer3)) {
9891 log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
9892 log("GOT BSSLAP: ", bsslap);
9893 setverdict(fail, "BSSLAP is not as expected");
9894 mtc.stop;
9895 }
9896 /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
9897 * has no need to request the TA from the BSC and directly responds. */
9898 } else {
9899 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9900 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9901 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
9902 }
9903
9904 /* SMLC got the TA from the BSC, now responds with geo information data. */
9905 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
9906 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9907 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
9908
9909 /* The LCS was using an active A-interface conn. It should still remain active after this. */
9910 f_mo_l3_transceive();
9911
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009912 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009913
9914 f_sleep(2.0);
9915 setverdict(pass);
9916}
9917
9918/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9919 * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
9920private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
9921 f_lcs_loc_req_for_active_ms(false);
9922}
9923testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
9924 var MSC_ConnHdlr vc_conn;
9925 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9926
9927 f_init(1, true);
9928 f_sleep(1.0);
9929 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
9930 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009931 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009932}
9933
9934/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9935 * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
9936private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
9937 f_lcs_loc_req_for_active_ms(true);
9938}
9939testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
9940 var MSC_ConnHdlr vc_conn;
9941 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9942
9943 f_init(1, true);
9944 f_sleep(1.0);
9945 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
9946 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009947 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009948}
9949
9950/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
9951 * conn without an active lchan. */
9952private function f_clear_A_conn() runs on MSC_ConnHdlr
9953{
9954 var BssmapCause cause := 0;
9955 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
9956 BSSAP.receive(tr_BSSMAP_ClearComplete);
9957 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
9958
9959 timer no_more_bssap := 5.0;
9960 no_more_bssap.start;
9961 alt {
9962 [] no_more_bssap.timeout { break; }
9963 [] BSSAP.receive(tr_BSSAP_BSSMAP) {
9964 setverdict(fail, "Expected no more BSSAP after Clear Complete");
9965 mtc.stop;
9966 }
9967 }
9968 setverdict(pass);
9969}
9970
9971/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
9972 * for LCS, for cases where there is only an A conn without an active lchan. */
9973private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
9974{
9975 f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
9976
9977 /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
9978 * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
9979 * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
9980 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9981 ts_CellId_CGI('262'H, '42'H, 23, 42))));
9982 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
9983
9984 /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
9985 f_clear_A_conn();
9986 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
9987 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9988}
9989
9990/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9991 * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
9992 */
9993private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
9994 f_sleep(1.0);
9995
9996 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9997 f_bssap_le_register_imsi(g_pars.imsi, omit);
9998
9999 /* Register to receive the Paging Command */
10000 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10001 g_chan_nr := new_chan_nr;
10002 f_rslem_register(0, g_chan_nr);
10003
10004 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10005 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10006 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10007 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10008
10009 var PDU_BSSAP_LE plr;
10010 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10011
10012 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10013 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10014
10015 /* OsmoBSC needs to Page */
10016 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
10017 f_logp(BSCVTY, "got Paging Command");
10018
10019 /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
10020 * the MSC, and releases the lchan directly. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010021 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);
10022 f_expect_lchan_rel(RSL, RSL_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010023
10024 /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
10025
10026 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10027
10028 /* SMLC got the TA from the BSC, now responds with geo information data. */
10029 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10030 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10031
10032 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10033
10034 /* The lchan is gone, the A-interface conn was created for the LCS only.
10035 * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
10036 f_verify_active_A_conn_and_clear();
10037
10038 f_sleep(2.0);
10039 setverdict(pass);
10040}
10041testcase TC_lcs_loc_req_for_idle_ms() runs on test_CT {
10042 var MSC_ConnHdlr vc_conn;
10043 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10044
10045 f_init(1, true);
10046 f_sleep(1.0);
10047
10048 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10049 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10050
10051 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
10052 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010053 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010054}
10055
10056/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
10057 */
10058private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
10059 f_sleep(1.0);
10060
10061 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10062 f_bssap_le_register_imsi(g_pars.imsi, omit);
10063
10064 /* provoke an abort by omitting both IMSI and IMEI */
10065 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10066 valueof(ts_BSSMAP_Perform_Location_Request(omit,
10067 ts_CellId_CGI('262'H, '42'H, 23, 42)))));
10068 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10069
10070 /* BSC tells MSC about failure */
10071 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10072 locationEstimate := omit, positioningData := omit,
10073 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
10074
10075 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10076 f_verify_active_A_conn_and_clear();
10077
10078 f_sleep(2.0);
10079 setverdict(pass);
10080}
10081testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
10082 var MSC_ConnHdlr vc_conn;
10083 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10084
10085 f_init(1, true);
10086 f_sleep(1.0);
10087
10088 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10089 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10090
10091 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
10092 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010093 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010094}
10095
10096/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10097 * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
10098private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
10099 f_sleep(1.0);
10100
10101 f_establish_fully(omit, omit);
10102 f_bssap_le_register_imsi(g_pars.imsi, omit);
10103
10104 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10105 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10106
10107 var PDU_BSSAP_LE plr;
10108 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10109
10110 if (do_ta) {
10111 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10112 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10113 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10114 }
10115
10116 /* SMLC fails to respond, BSC runs into timeout */
10117 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
10118 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10119
10120 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10121 locationEstimate := omit, positioningData := omit,
10122 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
10123
10124 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10125 f_verify_active_A_conn_and_clear();
10126
10127 f_sleep(2.0);
10128 setverdict(pass);
10129}
10130
10131/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10132 * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
10133private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
10134 f_lcs_loc_req_for_active_ms_le_timeout(false);
10135}
10136
10137testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
10138 var MSC_ConnHdlr vc_conn;
10139 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10140
10141 f_init(1, true);
10142 f_sleep(1.0);
10143 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
10144 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010145 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010146}
10147
10148/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
10149 * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
10150private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
10151 f_lcs_loc_req_for_active_ms_le_timeout(true);
10152}
10153
10154testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
10155 var MSC_ConnHdlr vc_conn;
10156 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10157
10158 f_init(1, true);
10159 f_sleep(1.0);
10160 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
10161 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010162 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010163}
10164
10165/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
10166private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
10167 f_sleep(1.0);
10168
10169 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10170 f_bssap_le_register_imsi(g_pars.imsi, omit);
10171
10172 /* Register to receive the Paging Command */
10173 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10174 g_chan_nr := new_chan_nr;
10175 f_rslem_register(0, g_chan_nr);
10176
10177 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10178 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10179 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10180 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10181
10182 var PDU_BSSAP_LE plr;
10183 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10184
10185 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10186 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10187
10188 /* OsmoBSC needs to Page */
10189 var PDU_BSSAP_LE rx_bsslap;
10190 alt {
10191 [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
10192 f_logp(BSCVTY, "got Paging Command");
10193 repeat;
10194 }
10195 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10196 /* MS does not respond to Paging, TA Req runs into timeout. */
10197 f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
10198 }
10199 }
10200
10201 /* SMLC responds with failure */
10202 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
10203 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10204
10205 /* BSC tells MSC about failure */
10206 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
10207 locationEstimate := omit, positioningData := omit,
10208 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
10209
10210 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
10211 f_verify_active_A_conn_and_clear();
10212
10213 f_sleep(2.0);
10214 setverdict(pass);
10215}
10216testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
10217 var MSC_ConnHdlr vc_conn;
10218 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10219
10220 f_init(1, true);
10221 f_sleep(1.0);
10222
10223 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10224 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10225
10226 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
10227 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010228 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010229}
10230
10231/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
10232 * over. */
10233private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10234 f_sleep(1.0);
10235
10236 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10237 f_bssap_le_register_imsi(g_pars.imsi, omit);
10238
10239 /* Register to receive the Paging Command */
10240 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
10241 g_chan_nr := new_chan_nr;
10242 f_rslem_register(0, g_chan_nr);
10243
10244 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
10245 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10246 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
10247 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
10248
10249 var PDU_BSSAP_LE plr;
10250 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10251
10252 /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
10253 * and establish Layer 3. It should use the existing A-interface conn. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010254 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 +020010255 do_clear := false, expect_bssmap_l3 := true);
10256
10257 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
10258 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
10259
10260 /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
10261 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
10262
10263 /* SMLC got the TA from the BSC, now responds with geo information data. */
10264 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10265 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10266 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10267
10268 /* The lchan should still exist, it was from a CM Service Request. */
10269 f_mo_l3_transceive();
10270
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010271 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010272
10273 f_sleep(2.0);
10274 setverdict(pass);
10275}
10276testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
10277 var MSC_ConnHdlr vc_conn;
10278 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10279
10280 f_init(1, true);
10281 f_sleep(1.0);
10282
10283 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
10284 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
10285
10286 vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
10287 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010288 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010289}
10290
10291/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
10292 * the new lchan after handover. */
10293private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
10294 f_sleep(1.0);
10295
10296 f_establish_fully(omit, omit);
10297 f_bssap_le_register_imsi(g_pars.imsi, omit);
10298
10299 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10300 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10301
10302 var PDU_BSSAP_LE plr;
10303 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
10304
10305 /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
10306 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
10307
10308 var HandoverState hs := {
10309 rr_ho_cmpl_seen := false,
10310 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +020010311 old_chan_nr := -,
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010312 expect_target_tsc := c_BtsParams[1].tsc
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010313 };
10314 /* issue hand-over command on VTY */
10315 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
10316 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
10317 f_rslem_suspend(RSL1_PROC);
10318
10319 /* From the MGW perspective, a handover is is characterized by
10320 * performing one MDCX operation with the MGW. So we expect to see
10321 * one more MDCX during handover. */
10322 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
10323
10324 alt {
10325 [] as_handover(hs);
10326 }
10327
10328 var PDU_BSSAP_LE rx_bsslap;
10329
10330 interleave {
10331 /* Expect the BSC to inform the MSC about the handover */
10332 [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
10333
10334 /* Expect the BSC to inform the SMLC about the handover */
10335 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
10336 f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
10337 }
10338 }
10339
10340 /* SMLC now responds with geo information data. */
10341 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10342 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10343 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10344
10345 /* lchan still active */
10346 f_mo_l3_transceive(RSL1);
10347
10348 /* MSC decides it is done now. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +020010349 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010350
10351 f_sleep(2.0);
10352 setverdict(pass);
10353}
10354testcase TC_ho_during_lcs_loc_req() runs on test_CT {
10355 var MSC_ConnHdlr vc_conn;
10356 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10357
10358 f_init(2, true);
10359 f_sleep(1.0);
10360 vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
10361 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010362 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020010363}
10364
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020010365private function f_tc_emerg_call_and_lcs_loc_req(charstring id) runs on MSC_ConnHdlr
10366{
10367 /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
10368 * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
10369 * another lchan. */
10370 g_pars.ra := 'b7'O;
10371 f_assignment_emerg_setup();
10372
10373 var PDU_BSSAP emerg_setup_data_ind_bssap;
10374 timer T := 3.0;
10375 T.start;
10376 alt {
10377 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
10378 var PDU_ML3_MS_NW verify_emerg_setup;
10379 verify_emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
10380 if (not isbound(verify_emerg_setup.msgs.cc.emergencySetup)) {
10381 setverdict(fail, "no emergency setup");
10382 }
10383 }
10384 [] BSSAP.receive {
10385 setverdict(fail, "unexpected BSSAP message!");
10386 }
10387 [] T.timeout {
10388 setverdict(fail, "timeout waiting for EMERGENCY SETUP!");
10389 }
10390 }
10391
10392 /* Here would usually be a CC Call Proceeding from the MSC, but what does the BSC care about DTAP. */
10393
10394 /* Do a Location Request in-between the CC call setup */
10395 f_bssap_le_register_imsi(g_pars.imsi, omit);
10396 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10397 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10398 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10399 /* SMLC got the TA from the BSC, now responds with geo information data. */
10400 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10401 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10402 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10403
10404 /* Go on with voice call assignment */
10405 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
10406 var PDU_BSSAP ass_cmd := f_gen_ass_req();
10407
10408 /* Below speechOrDataIndicator and codecList are copied from an emergency call captured during tests.
10409 * They seem a bit weird (AMR-WB, and the order differ between speechId_DataIndicator and the codecList), but
10410 * seems a good idea to see how osmo-bsc reacts to this. */
10411 ass_cmd.pdu.bssmap.assignmentRequest.channelType := {
10412 elementIdentifier := '0B'O, /* overwritten */
10413 lengthIndicator := 0, /* overwritten */
10414 speechOrDataIndicator := '0001'B, /* speech */
10415 spare1_4 := '0000'B,
10416 channelRateAndType := ChRate_TCHForH_Fpref,
10417 speechId_DataIndicator := 'c2918105'O
10418 };
10419 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({
10420 ts_CodecHR, ts_CodecAMR_WB, ts_CodecEFR, ts_CodecFR}));
10421
10422 f_rslem_dchan_queue_enable();
10423
10424 var ExpectCriteria mgcpcrit := {
10425 connid := omit,
10426 endpoint := omit,
10427 transid := omit
10428 };
10429 f_create_mgcp_expect(mgcpcrit);
10430
10431 BSSAP.send(ass_cmd);
10432
10433 var AssignmentState st := valueof(ts_AssignmentStateInit);
10434 st.voice_call := true;
10435 st.is_assignment := false;
10436 alt {
10437 [] as_modify(st);
10438 [] as_Media();
10439 [st.modify_done] BSSAP.receive(exp_compl) {
10440 setverdict(pass);
10441 }
10442 }
10443
10444 /* Voice call carries on ... */
10445 f_sleep(2.0);
10446
10447 setverdict(pass);
10448 f_perform_clear();
10449}
10450
10451testcase TC_emerg_call_and_lcs_loc_req() runs on test_CT {
10452 var MSC_ConnHdlr vc_conn;
10453 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10454
10455 f_init(1, true);
10456 f_sleep(1.0);
10457 f_vty_allow_emerg_msc(true);
10458 f_vty_allow_emerg_bts(true, 0);
10459 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req), pars);
10460 vc_conn.done;
10461 f_shutdown_helper();
10462}
10463
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020010464private altstep no_bssmap_clear_req() runs on MSC_ConnHdlr {
10465 [] BSSAP.receive(tr_BSSMAP_ClearRequest) {
10466 setverdict(fail, "unexpected BSSMAP Clear Request");
10467 mtc.stop;
10468 }
10469}
10470
10471private type enumerated RslRel {
10472 RSLREL_REL_IND,
10473 RSLREL_CONN_FAIL
10474};
10475
10476private function f_emerg_call_and_lcs_loc_req_early_lchan_release(RslRel rsl_rel) runs on MSC_ConnHdlr
10477{
10478 g_pars.ra := f_rnd_ra_emerg();
10479 f_assignment_emerg_setup();
10480
10481 var PDU_BSSAP emerg_setup_data_ind_bssap;
10482 timer T := 3.0;
10483 T.start;
10484 alt {
10485 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
10486 var PDU_ML3_MS_NW verify_emerg_setup;
10487 verify_emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
10488 if (not ischosen(verify_emerg_setup.msgs.cc.emergencySetup)) {
10489 setverdict(fail, "no emergency setup");
10490 }
10491 }
10492 [] BSSAP.receive {
10493 setverdict(fail, "unexpected BSSAP message!");
10494 }
10495 [] T.timeout {
10496 setverdict(fail, "timeout waiting for EMERGENCY SETUP!");
10497 }
10498 }
10499
10500 /* Start a Location Request to locate the emergency */
10501 f_bssap_le_register_imsi(g_pars.imsi, omit);
10502 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
10503 ts_CellId_CGI('262'H, '42'H, 23, 42))));
10504 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
10505
10506 /* 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
10507 * do a Clear Command when the Location Response arrives. */
10508 activate(no_bssmap_clear_req());
10509
10510 /* the lchan gets interrupted while the Location Request has no response */
10511 select (rsl_rel) {
10512 case (RSLREL_REL_IND) {
10513 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
10514 f_expect_lchan_rel(RSL, RSL_PROC);
10515 }
10516 case (RSLREL_CONN_FAIL) {
10517 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
10518 }
10519 case else {
10520 setverdict(fail, "Unknown RslRel type");
10521 mtc.stop;
10522 }
10523 }
10524
10525 /* Still expect the Location Response to find its way to the MSC. */
10526 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
10527 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
10528 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
10529
10530 setverdict(pass);
10531
10532 select (rsl_rel) {
10533 case (RSLREL_REL_IND) {
10534 f_perform_clear_no_lchan();
10535 }
10536 case (RSLREL_CONN_FAIL) {
10537 f_perform_clear();
10538 }
10539 }
10540}
10541
10542private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind(charstring id) runs on MSC_ConnHdlr
10543{
10544 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_REL_IND);
10545}
10546
10547testcase TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() runs on test_CT {
10548 var MSC_ConnHdlr vc_conn;
10549 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10550
10551 f_init(1, true);
10552 f_sleep(1.0);
10553 f_vty_allow_emerg_msc(true);
10554 f_vty_allow_emerg_bts(true, 0);
10555 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind), pars);
10556 vc_conn.done;
10557 f_shutdown_helper();
10558}
10559
10560private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail(charstring id) runs on MSC_ConnHdlr
10561{
10562 f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_CONN_FAIL);
10563}
10564
10565testcase TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() runs on test_CT {
10566 var MSC_ConnHdlr vc_conn;
10567 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10568
10569 f_init(1, true);
10570 f_sleep(1.0);
10571 f_vty_allow_emerg_msc(true);
10572 f_vty_allow_emerg_bts(true, 0);
10573 vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail), pars);
10574 vc_conn.done;
10575 f_shutdown_helper();
10576}
10577
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010578/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
10579private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
10580 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
10581
10582 /* Also disable attach for the single connected MSC */
10583 f_vty_msc_allow_attach(BSCVTY, { false });
10584
10585 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) ));
10586 f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
10587
10588 /* No MSC is found, expecting a proper release on RSL */
10589 interleave {
10590 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
10591 f_logp(BSCVTY, "Got RSL RR Release");
10592 }
10593 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10594 f_logp(BSCVTY, "Got RSL Deact SACCH");
10595 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010596 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010597 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
10598 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010599 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010600 }
10601 }
10602 setverdict(pass);
10603}
10604testcase TC_no_msc() runs on test_CT {
10605
10606 f_init(1, true);
10607 f_sleep(1.0);
10608 var MSC_ConnHdlr vc_conn;
10609 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10610
10611 f_ctrs_bsc_init(counternames_bsc_mscpool);
10612
10613 vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
10614 vc_conn.done;
10615
10616 f_ctrs_bsc_add("mscpool:subscr:no_msc");
10617 f_ctrs_bsc_verify();
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +010010618 f_shutdown_helper();
Neels Hofmeyrbf037052020-10-28 22:52:02 +000010619}
10620
Harald Welte0ea2d5e2018-04-07 21:40:29 +020010621/* Dyn PDCH todo:
10622 * activate OSMO as TCH/F
10623 * activate OSMO as TCH/H
10624 * does the BSC-located PCU socket get the updated INFO?
10625 * what if no PCU is connected at the time?
10626 * is the info correct on delayed PCU (re)connect?
10627 */
Harald Welte94e0c342018-04-07 11:33:23 +020010628
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010629private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrolf967afc2022-08-08 18:17:20 +020010630 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020010631 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010632
10633 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
10634 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10635 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
10636 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
10637 g_pars.ass_codec_list.codecElements[0];
10638 if (isvalue(g_pars.expect_mr_s0_s7)) {
10639 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
10640 g_pars.expect_mr_s0_s7;
10641 }
10642 }
10643 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
10644 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
10645 log("expecting ASS COMPL like this: ", exp_compl);
10646
10647 f_establish_fully(ass_cmd, exp_compl);
10648
Neels Hofmeyr8746b0d2021-06-01 17:25:39 +020010649 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 +000010650
10651 var RSL_Message rsl;
10652
10653 timer T := 5.0;
10654 T.start;
10655 alt {
10656 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
10657 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
10658 log("Rx L3 from net: ", l3);
10659 if (ischosen(l3.msgs.rrm.channelModeModify)) {
10660 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10661 mtc.stop;
10662 }
10663 }
10664 [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
10665 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10666 mtc.stop;
10667 }
10668 [] T.timeout {
10669 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
10670 setverdict(pass);
10671 }
10672 }
10673 T.stop;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010674
10675 f_perform_clear();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010676}
10677
10678/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
10679 * osmo-bsc. */
10680testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
10681 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10682 var MSC_ConnHdlr vc_conn;
10683
10684 f_init(1, true);
10685 f_sleep(1.0);
10686
10687 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10688 vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
10689 vc_conn.done;
10690 f_shutdown_helper();
10691}
10692
10693/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
10694 */
10695testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
10696 f_init_vty();
10697
10698 f_init(1, false);
10699 f_sleep(1.0);
10700
10701 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
10702
10703 var ASP_RSL_Unitdata rx_rsl_ud;
10704 timer T := 5.0;
10705
10706 T.start;
10707 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010708 [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010709 if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
10710 T.stop;
10711 setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
10712 mtc.stop;
10713 }
10714 repeat;
10715 }
10716 [] T.timeout {
10717 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
10718 setverdict(pass);
10719 }
10720 }
10721}
10722
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010723private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
10724 /* First fully set up a speech lchan */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010725 f_assignment_codec(id, do_perform_clear := false);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010726
10727 /* Trigger re-assignment to another lchan */
10728 var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
10729
10730 /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
10731 * one MDCX on MGCP. */
10732 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
10733
10734 /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
10735 * as the old lchan used. */
10736 g_media.bts.ipa_crcx_seen := false;
10737 g_media.bts.ipa_mdcx_seen := false;
10738
10739 /* Send different BTS side RTP port number for the new lchan */
10740 g_media.bts.bts.port_nr := 4223;
10741
10742 f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
10743
10744 /* Trigger re-assignment. */
10745 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
10746
10747 timer T := 5.0;
10748 T.start;
10749 alt {
10750 [] as_assignment(assignment_st);
10751 [] as_Media();
10752 [] T.timeout {
10753 break;
10754 }
10755 }
10756
10757 if (not assignment_st.assignment_done) {
10758 setverdict(fail, "Assignment did not complete");
10759 mtc.stop;
10760 }
10761
10762 f_check_mgcp_expectations()
10763 setverdict(pass);
10764
10765 f_sleep(2.0);
10766 log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
10767
10768 /* Instruct BSC to clear channel */
10769 var BssmapCause cause := 0;
10770 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10771 interleave {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010772 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
10773 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010774 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010775 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010776 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010777 }
10778 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
10779 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10780 }
10781 }
Neels Hofmeyr40a45d12021-09-23 22:57:12 +020010782 f_expect_dlcx_conns();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010783
10784 f_sleep(0.5);
10785}
10786
10787testcase TC_reassignment_fr() runs on test_CT {
10788 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10789 var MSC_ConnHdlr vc_conn;
10790
10791 f_init(1, true);
10792 f_sleep(1.0);
10793
Neels Hofmeyrac432fa2021-11-02 16:45:56 +010010794 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010795
10796 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10797 vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
10798 vc_conn.done;
10799
10800 /* from f_establish_fully() */
10801 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
10802 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
10803 /* from re-assignment */
10804 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
10805 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
10806 f_ctrs_bsc_and_bts_verify();
10807 f_shutdown_helper();
10808}
10809
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010810const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
10811const charstring REEST_CLEAR := "REEST_CLEAR";
10812const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
10813
10814/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
10815 * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
10816 * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
10817 * the MSC as the CM Re-Establishment is handled.
10818 *
10819 * MS bts0 bts1 bsc msc test-component
10820 * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
10821 * | | _1 wait a bit, to settle down
10822 * |<-x x--| | _1 "lose connection"
10823 * | | REEST_LOST_CONNECTION
10824 * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
10825 * | | REEST_CLEAR
10826 * | |<-0---| _1 Clear Command on first A-conn
10827 * | |--0-->| _1 Clear Complete
10828 * | |<----------------->| | _1 Release first channel
10829 * | | REEST_CLEAR_DONE
10830 * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
10831 * |<-----------------|<-------|<-1---| _2 Clear Command, Release
10832 *
10833 */
10834private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
10835 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
10836 var PDU_BSSAP ass_cmd := f_gen_ass_req();
10837
10838 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
10839 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10840
10841 f_establish_fully(ass_cmd, exp_compl);
10842
10843 /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
10844 * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
10845 * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
10846 f_sleep(2.0);
10847 COORD.send(REEST_LOST_CONNECTION);
10848
10849 alt {
10850 [] COORD.receive(REEST_CLEAR);
10851 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10852 setverdict(fail, "Unexpected channel release");
10853 mtc.stop;
10854 }
10855 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
10856 setverdict(fail, "Unexpected channel release");
10857 mtc.stop;
10858 }
10859 }
10860 f_perform_clear()
Neels Hofmeyr969abd02021-09-23 22:24:08 +020010861 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010862 COORD.send(REEST_CLEAR_DONE);
10863}
10864
10865private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
10866 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
10867
10868 /* The MS lost the connection on the first channel, now establishes another one */
10869 COORD.receive(REEST_LOST_CONNECTION);
10870
10871 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
10872 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
10873 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
10874
10875 f_create_bssmap_exp(l3_enc);
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010876 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 +020010877 BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
10878
10879 /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
10880 COORD.send(REEST_CLEAR);
10881 COORD.receive(REEST_CLEAR_DONE);
10882
10883 f_sleep(2.0);
10884
10885 /* Answer the CM Re-Establishment with an Assignment Command. */
10886 var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
10887 var PDU_BSSAP ass_cmd := f_gen_ass_req();
10888 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
10889 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10890
10891 var AssignmentState st := valueof(ts_AssignmentStateInit);
10892 st.voice_call := true;
10893 st.is_assignment := true;
10894
10895 var ExpectCriteria mgcpcrit := {
10896 connid := omit,
10897 endpoint := omit,
10898 transid := omit
10899 };
10900 f_create_mgcp_expect(mgcpcrit);
10901
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010902 f_rslem_dchan_queue_enable(RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010903
10904 BSSAP.send(ass_cmd);
10905
10906 var PDU_BSSAP bssap;
10907
10908 alt {
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010909 [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
10910 [] as_Media_ipacc(RSL1, RSL2);
10911 [] as_Media_mgw();
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010912 [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
10913 break;
10914 }
10915 }
10916
10917 f_sleep(3.0);
10918
10919 f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010920 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010921}
10922
10923testcase TC_cm_reestablishment() runs on test_CT {
10924 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
10925 var MSC_ConnHdlr vc_conn1;
10926
10927 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
10928 var MSC_ConnHdlr vc_conn2;
10929 pars2.imsi := pars1.imsi;
10930 pars2.media_nr := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010931 pars2.expect_tsc := c_BtsParams[1].tsc;
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010932
10933 f_init(2, true, guard_timeout := 40.0);
10934 f_sleep(1.0);
10935
10936 vc_conn1 := f_start_handler_create(pars1);
10937 vc_conn2 := f_start_handler_create(pars2);
10938 connect(vc_conn1:COORD, vc_conn2:COORD);
10939 f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
10940 f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
10941 vc_conn1.done;
10942 vc_conn2.done;
10943
10944 f_shutdown_helper();
10945}
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010946
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010947function f_exp_ipa_rx_nonfatal(template (present) RSL_Message t_rx,
10948 boolean ignore_other_rx := true,
10949 BtsTrxIdx idx := {0, 0},
10950 float Tval := 2.0)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010951runs on test_CT return template (omit) RSL_Message {
10952 var ASP_RSL_Unitdata rx_rsl_ud;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010953 timer T := Tval;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010954
10955 T.start;
10956 alt {
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010957 [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010958 T.stop;
10959 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060010960 [ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
10961 [not ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive {
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010962 log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
10963 T.stop;
10964 return omit;
10965 }
10966 [] T.timeout {
10967 return omit;
10968 }
10969 }
10970 return rx_rsl_ud.rsl;
10971}
10972
10973private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
10974 f_vty_enter_cfg_bts(pt, bts_nr);
10975 f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
10976 f_vty_transceive(pt, "exit");
10977 f_vty_transceive(pt, "exit");
10978 f_vty_transceive(pt, "exit");
10979}
10980
10981private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
Vadim Yanitskiy35c9a332022-03-16 20:26:35 +030010982 template (present) RslChannelNr chan_nr := ?,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010983 template (present) uint12_t arfcn := ?,
10984 template (present) uint3_t tsc := ?)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010985{
10986 var RSL_IE_Body full_imm_ass_info;
10987 if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
10988 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
10989 mtc.stop;
10990 }
10991
10992 var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
10993 var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
10994 fn := fn,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010995 ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010996 page_mode := ?);
10997 if (not match(rr_imm_ass, expect_imm_ass)) {
10998 log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
10999 setverdict(fail, "Failed to match Immediate Assignment");
11000 mtc.stop;
11001 }
11002}
11003
11004testcase TC_imm_ass_post_chan_ack() runs on test_CT {
11005 var RSL_Message chan_act;
11006 var RSL_Message imm_ass;
11007
11008 f_init(1, false);
11009 f_sleep(1.0);
11010
11011 /* (should be the default anyway, just to make things clear) */
11012 f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
11013
11014 /* RA containing reason=LU */
11015 var GsmFrameNumber fn := 2342;
11016 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011017 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011018
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011019 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011020
11021 /* First send the Chan Act ACK */
11022 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 }
11029
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011030 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011031
11032 /* Then expect the Immediate Assignment, after we ACKed the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011033 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011034
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 /* Check that the lchan is working */
11039 var octetstring l3 := '00010203040506'O;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011040 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011041
11042 var BSSAP_N_CONNECT_ind rx_c_ind;
11043 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011044 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011045 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11046
11047 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011048 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011049 f_shutdown_helper();
11050}
11051
11052testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
11053 var RSL_Message chan_act;
11054 var RSL_Message imm_ass;
11055
11056 f_init(1, false);
11057 f_sleep(1.0);
11058
11059 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11060
11061 /* RA containing reason=LU */
11062 var GsmFrameNumber fn := 2342;
11063 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011064 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011065
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011066 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011067 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011068 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011069 var RSL_IE_Body chan_ident_ie;
11070 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11071 setverdict(fail, "RSL Channel Identification IE is absent");
11072 mtc.stop;
11073 }
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011074
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011075 /* (set bts 0 cfg back to default) */
11076 f_vty_set_imm_ass(BSCVTY);
11077
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011078 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011079 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011080 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11081 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011082
11083 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011084 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011085
11086 /* Check that the lchan is working */
11087 var octetstring l3 := '00010203040506'O;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011088 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011089
11090 var BSSAP_N_CONNECT_ind rx_c_ind;
11091 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011092 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011093 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11094
11095 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011096 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011097 f_shutdown_helper();
11098}
11099
Neels Hofmeyr23158742021-09-07 19:08:07 +020011100testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
11101 var RSL_Message chan_act;
11102 var RSL_Message imm_ass;
11103
11104 f_init(1, false);
11105 f_sleep(1.0);
11106
11107 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11108
11109 /* RA containing reason=LU */
11110 var GsmFrameNumber fn := 2342;
11111 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011112 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011113
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011114 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011115 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011116 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr23158742021-09-07 19:08:07 +020011117 var RSL_IE_Body chan_ident_ie;
11118 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11119 setverdict(fail, "RSL Channel Identification IE is absent");
11120 mtc.stop;
11121 }
11122
Vadim Yanitskiy69170512022-06-03 01:49:42 +060011123 /* (set bts 0 cfg back to default) */
11124 f_vty_set_imm_ass(BSCVTY);
11125
Neels Hofmeyr23158742021-09-07 19:08:07 +020011126 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011127 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011128 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11129 chan_ident_ie.chan_ident.ch_desc.v.tsc);
11130
11131 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011132 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011133
11134 /* Check that the lchan is working */
11135 var octetstring l3 := '00010203040506'O;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011136 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
Neels Hofmeyr23158742021-09-07 19:08:07 +020011137
11138 var BSSAP_N_CONNECT_ind rx_c_ind;
11139 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011140 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr23158742021-09-07 19:08:07 +020011141 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11142
11143 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011144 f_perform_clear_test_ct(dt);
Neels Hofmeyr23158742021-09-07 19:08:07 +020011145 f_shutdown_helper();
11146}
11147
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011148testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
11149 /* change Timeslot 6 before f_init() starts RSL */
11150 f_init_vty();
11151 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11152 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11153
11154 f_init(1, false);
11155 f_sleep(1.0);
11156
11157 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11158 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011159 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11160 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011161
11162 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11163 f_ts_set_chcomb(0, 0, 6, "PDCH");
11164
11165 /* block all static timeslots so that the dyn TS will be used */
11166 f_disable_all_tch_f();
11167 f_disable_all_tch_h();
11168 f_disable_all_sdcch();
11169
11170 var RSL_Message chan_act;
11171 var RSL_Message imm_ass;
11172
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011173 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
11174
11175 /* RA containing reason=LU */
11176 var GsmFrameNumber fn := 2342;
11177 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011178 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011179
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011180 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011181 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
11182 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011183
11184 /* Now activation as SDCCH8 */
11185 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011186 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011187
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011188 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011189 var RSL_IE_Body chan_ident_ie;
11190 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11191 setverdict(fail, "RSL Channel Identification IE is absent");
11192 mtc.stop;
11193 }
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011194
11195 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011196 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011197 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11198 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011199
11200 /* Only now send the Chan Act ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011201 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011202
11203 /* Check that the lchan is working */
11204 var octetstring l3 := '00010203040506'O;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011205 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011206
11207 var BSSAP_N_CONNECT_ind rx_c_ind;
11208 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011209 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011210 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11211
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011212 /* (set bts 0 cfg back to default) */
11213 f_vty_set_imm_ass(BSCVTY);
11214
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011215 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011216 f_perform_clear_test_ct(dt);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011217 f_shutdown_helper();
11218}
11219
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011220testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
11221 /* change Timeslot 6 before f_init() starts RSL */
11222 f_init_vty();
11223 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
11224 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11225
11226 f_init(1, false);
11227 f_sleep(1.0);
11228
11229 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
11230 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011231 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11232 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011233
11234 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
11235 f_ts_set_chcomb(0, 0, 6, "PDCH");
11236
11237 /* block all static timeslots so that the dyn TS will be used */
11238 f_disable_all_tch_f();
11239 f_disable_all_tch_h();
11240 f_disable_all_sdcch();
11241
11242 var RSL_Message chan_act;
11243 var RSL_Message imm_ass;
11244
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011245 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
11246
11247 /* RA containing reason=LU */
11248 var GsmFrameNumber fn := 2342;
11249 var uint8_t ra := 2;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011250 f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011251
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011252 /* Expect the dyn TS to deactivate PDCH first */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011253 f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011254
11255 /* And already the Immediate Assignment even before the PDCH Deact ACK */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011256 imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011257
11258 /* continue the Osmo style PDCH Deact (usual chan rel) */
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011259 f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011260
11261 /* Now activation as SDCCH8 */
11262 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011263 var DchanTuple dt := {-, chan_nr, {0, 0}};
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011264
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011265 chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011266 var RSL_IE_Body chan_ident_ie;
11267 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
11268 setverdict(fail, "RSL Channel Identification IE is absent");
11269 mtc.stop;
11270 }
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011271 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011272
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020011273 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
11274 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011275
11276 /* Check that the lchan is working */
11277 var octetstring l3 := '00010203040506'O;
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011278 f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011279
11280 var BSSAP_N_CONNECT_ind rx_c_ind;
11281 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011282 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011283 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
11284
Vadim Yanitskiy31778dd2022-06-14 20:55:16 +070011285 /* (set bts 0 cfg back to default) */
11286 f_vty_set_imm_ass(BSCVTY);
11287
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011288 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011289 f_perform_clear_test_ct(dt);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011290 f_shutdown_helper();
11291}
11292
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011293/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
11294testcase TC_ctrl_trx_rf_locked() runs on test_CT {
11295 var MSC_ConnHdlr vc_conn;
11296
11297 f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
11298 f_sleep(1.0);
11299
11300 /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
11301 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11302 "0,0,operational,unlocked,on,rsl-up;" &
11303 "1,0,operational,unlocked,on,rsl-up;" &
11304 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011305 "2,1,operational,unlocked,on,rsl-down;" &
11306 "2,2,operational,unlocked,on,rsl-down;" &
11307 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011308 "3,0,inoperational,locked,on,rsl-down;");
11309
11310 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock BTS 1 TRX 0");
11311 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11312 /* give it a moment to settle the FSM status */
11313 f_sleep(1.0);
11314
11315 /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
11316 * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
11317 * of "off"? But that's for a future patch if at all. */
11318 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11319 "0,0,operational,unlocked,on,rsl-up;" &
11320 "1,0,operational,locked,on,rsl-up;" &
11321 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011322 "2,1,operational,unlocked,on,rsl-down;" &
11323 "2,2,operational,unlocked,on,rsl-down;" &
11324 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011325 "3,0,inoperational,locked,on,rsl-down;");
11326
11327 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
11328 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
11329 f_sleep(1.0);
11330 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11331 "0,0,operational,unlocked,on,rsl-up;" &
11332 "1,0,operational,locked,on,rsl-up;" &
11333 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011334 "2,1,operational,unlocked,on,rsl-down;" &
11335 "2,2,operational,unlocked,on,rsl-down;" &
11336 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011337 "3,0,inoperational,locked,on,rsl-down;");
11338
11339 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
11340 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
11341 f_sleep(1.0);
11342 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11343 "0,0,operational,unlocked,on,rsl-up;" &
11344 "1,0,operational,unlocked,on,rsl-up;" &
11345 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011346 "2,1,operational,unlocked,on,rsl-down;" &
11347 "2,2,operational,unlocked,on,rsl-down;" &
11348 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011349 "3,0,inoperational,locked,on,rsl-down;");
11350
11351 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
11352 f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
11353 f_sleep(1.0);
11354 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11355 "0,0,operational,unlocked,on,rsl-up;" &
11356 "1,0,operational,unlocked,on,rsl-up;" &
11357 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011358 "2,1,operational,unlocked,on,rsl-down;" &
11359 "2,2,operational,unlocked,on,rsl-down;" &
11360 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011361 "3,0,inoperational,locked,on,rsl-down;");
11362
11363 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
11364 f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
11365 f_sleep(1.0);
11366 f_ctrl_get_exp(IPA_CTRL, "rf_states",
11367 "0,0,operational,unlocked,on,rsl-up;" &
11368 "1,0,operational,unlocked,on,rsl-up;" &
11369 "2,0,operational,unlocked,on,rsl-down;" &
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011370 "2,1,operational,unlocked,on,rsl-down;" &
11371 "2,2,operational,unlocked,on,rsl-down;" &
11372 "2,3,operational,unlocked,on,rsl-down;" &
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011373 "3,0,inoperational,locked,on,rsl-down;");
11374
11375 f_shutdown_helper();
11376}
11377
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011378const CounterNameVals counternames_cm_serv_rej := {
11379 { "cm_serv_rej", 0 },
11380 { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
11381 { "cm_serv_rej:illegal_ms", 0 },
11382 { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
11383 { "cm_serv_rej:imei_not_accepted", 0 },
11384 { "cm_serv_rej:illegal_me", 0 },
11385 { "cm_serv_rej:plmn_not_allowed", 0 },
11386 { "cm_serv_rej:loc_not_allowed", 0 },
11387 { "cm_serv_rej:roaming_not_allowed", 0 },
11388 { "cm_serv_rej:network_failure", 0 },
11389 { "cm_serv_rej:synch_failure", 0 },
11390 { "cm_serv_rej:congestion", 0 },
11391 { "cm_serv_rej:srv_opt_not_supported", 0 },
11392 { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
11393 { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
11394 { "cm_serv_rej:call_can_not_be_identified", 0 },
11395 { "cm_serv_rej:incorrect_message", 0 },
11396 { "cm_serv_rej:invalid_mandantory_inf", 0 },
11397 { "cm_serv_rej:msg_type_not_implemented", 0 },
11398 { "cm_serv_rej:msg_type_not_compatible", 0 },
11399 { "cm_serv_rej:inf_eleme_not_implemented", 0 },
11400 { "cm_serv_rej:condtional_ie_error", 0 },
11401 { "cm_serv_rej:msg_not_compatible", 0 },
11402 { "cm_serv_rej:protocol_error", 0 },
11403 { "cm_serv_rej:retry_in_new_cell", 0 }
11404};
11405
11406private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
11407{
11408 f_create_chan_and_exp();
Vadim Yanitskiya7fc5a62021-12-04 20:10:08 +030011409 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011410 BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011411 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_CM_SERV_REJ));
11412 f_perform_clear();
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011413 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011414}
11415testcase TC_cm_serv_rej() runs on test_CT {
11416 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11417 var MSC_ConnHdlr vc_conn;
11418
11419 f_init(1, true);
11420 f_sleep(1.0);
11421
11422 f_ctrs_bts_init(1, counternames_cm_serv_rej);
11423
11424 vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
11425 vc_conn.done;
11426
11427 f_ctrs_bts_add(0, "cm_serv_rej", 1);
11428 f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
11429 f_ctrs_bts_verify();
11430
Neels Hofmeyr87a65612021-11-16 15:56:45 +010011431 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011432 f_shutdown_helper();
11433}
11434
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011435/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
11436 * Activ Ack (SYS#5627). */
11437private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
11438 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Vadim Yanitskiyf0310e32021-10-26 00:30:59 +030011439
11440 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11441 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011442
11443 var BSSMAP_FIELD_CodecType codecType;
11444 codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
11445
11446 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
11447
11448 /* First establish a signalling lchan */
11449 f_create_chan_and_exp();
11450 f_rslem_dchan_queue_enable();
11451
11452 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011453
11454 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
Vadim Yanitskiy6be4cf42022-06-04 21:25:47 +060011455 activate(as_Media_mgw(fail_on_dlcx := false));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011456
11457 var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
11458 f_rslem_register(0, chan_nr);
11459
11460 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
11461 BSSAP.send(ass_cmd);
11462
11463
11464 /* Wait for the Channel Activ for the TCH channel */
11465 var ASP_RSL_Unitdata rx_rsl_ud;
11466 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
11467
11468 /* make the original SDCCH disappear */
11469 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
11470
11471 /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
11472 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
11473
11474 interleave {
11475 [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
11476 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
11477 }
11478
11479 BSSAP.send(ts_BSSMAP_ClearCommand(0));
11480 BSSAP.receive(tr_BSSMAP_ClearComplete);
11481 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
11482
11483 var MgcpCommand mgcp;
Vadim Yanitskiy6be4cf42022-06-04 21:25:47 +060011484 var MGCP_RecvFrom mrf;
11485 var template MgcpMessage msg_dlcx := { command := tr_DLCX };
11486 alt {
11487 [g_pars.aoip] MGCP.receive(tr_DLCX) -> value mgcp {
11488 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
11489 }
11490 [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
11491 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
11492 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
11493 }));
11494 }
11495 }
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011496
11497 f_sleep(0.5);
11498}
11499testcase TC_lost_sdcch_during_assignment() runs on test_CT {
11500 var TestHdlrParams pars := f_gen_test_hdlr_pars();
11501 var MSC_ConnHdlr vc_conn;
11502
11503 f_init(1, true);
11504 f_sleep(1.0);
11505
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011506 vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
11507 vc_conn.done;
11508
11509 f_shutdown_helper();
11510}
11511
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011512const CounterNameVals counternames_bsc_bts_all_available_allocated := {
11513 { "all_allocated:sdcch", 0 },
11514 { "all_allocated:static_sdcch", 0 },
11515 { "all_allocated:tch", 0 },
11516 { "all_allocated:static_tch", 0 }
11517}
11518
11519private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
11520{
11521 /* Make sure counters settle first */
11522 f_sleep(1.0);
11523
11524 /* Take a baseline of counters */
11525 f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
11526
11527 /* Elapse some time so that we see changes in counters, hopefully where expected */
11528 f_sleep(2.0);
11529
11530 /* Get new counters */
11531 var charstring_list all_changed := {};
11532 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
11533 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
11534
11535 /* Compare with expectations */
11536 var charstring_list all_expect_changed := {};
11537 for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
11538 all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
11539 }
11540 f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
11541}
11542
11543testcase TC_ratectr_all_available_allocated() runs on test_CT {
11544 var ASP_RSL_Unitdata rsl_ud;
11545 var integer i;
11546 var integer chreq_total, chreq_nochan;
11547
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011548 f_init(1, guard_timeout := 60.0);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011549 f_sleep(1.0);
11550
11551 /* Exhaust all dedicated SDCCH lchans.
11552 /* GSM 44.018 Table 9.1.8.2:
11553 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11554 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011555 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011556 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011557 chan_cleanup := chan_cleanup & { f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011558 }
11559
11560 /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
11561 * level.
11562 * All SDCCH are now occupied. */
11563 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11564
11565 /* Also fill up all remaining (TCH) channels */
11566 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011567 chan_cleanup := chan_cleanup & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011568 }
11569
11570 /* All TCH are now also occupied */
11571 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11572 "all_allocated:tch", "all_allocated:static_tch"});
11573
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011574 /* Clean up SDCCH lchans */
11575 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11576 f_perform_clear_test_ct(chan_cleanup[i]);
11577 }
11578
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011579 f_shutdown_helper();
11580}
11581
11582testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
11583 var ASP_RSL_Unitdata rsl_ud;
11584 var integer i;
11585 var integer chreq_total, chreq_nochan;
11586
11587 f_init_vty();
11588 f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
11589 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
11590 /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
11591
11592 f_init(1, guard_timeout := 60.0);
11593 f_sleep(1.0);
11594
11595 /* The dyn TS wants to activate PDCH mode, ACK that. */
11596 var RslChannelNr chan_nr;
11597 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011598 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11599 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011600
11601 /* Exhaust all dedicated SDCCH lchans.
11602 /* GSM 44.018 Table 9.1.8.2:
11603 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
11604 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011605 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011606 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011607 chan_cleanup := chan_cleanup & { f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011608 }
11609
11610 /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
11611 * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
11612 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
11613
11614 /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
11615 * Will release them later, so remember all the DchanTuples. */
11616 var DchanTuples dyn_sddch := {};
11617 dyn_sddch := dyn_sddch & { f_est_dchan_dyn('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
11618
11619 /* Also occupy the seven other SDCCH of the dyn TS */
11620 for (i := 0; i < 7; i := i+1) {
11621 dyn_sddch := dyn_sddch & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
11622 }
11623
11624 /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
11625 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
11626
11627 /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
11628 for (i := 0; i < 5; i := i+1) {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011629 chan_cleanup := chan_cleanup & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011630 }
11631
11632 /* All TCH lchans are now also occupied, both static and dynamic */
11633 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
11634 "all_allocated:tch", "all_allocated:static_tch"});
11635
11636 /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
11637 * incrementing. */
11638 var BssmapCause cause := 0;
11639 var DchanTuple dt := dyn_sddch[0];
11640 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011641 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011642
11643 /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
11644 * count as occupied, so those still both increment. */
11645 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
11646 "all_allocated:tch", "all_allocated:static_tch"});
11647
11648 /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
11649 for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
11650 dt := dyn_sddch[i];
11651 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011652 f_exp_chan_rel_and_clear(dt);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011653 }
11654
11655 /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
11656 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiye5d393c2022-05-29 16:55:42 +060011657 f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
11658 f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011659
11660 /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
11661 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
11662
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010011663 /* Clean up SDCCH lchans */
11664 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
11665 f_perform_clear_test_ct(chan_cleanup[i]);
11666 }
11667
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011668 /* clean up config */
11669 f_ts_reset_chcomb(0);
11670
11671 f_shutdown_helper();
11672}
11673
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060011674private function f_TC_chan_alloc_algo(DchanTuple dt, BtsTrxIdx idx)
11675runs on test_CT {
11676 /* MSC sends an Assignment Request */
11677 var PDU_BSSAP ass_cmd := f_gen_ass_req();
11678 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
11679 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
11680 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
11681
11682 /* Expect the BSC to allocate a TCH channel on the given BTS/TRX */
11683 var RSL_Message rsl_chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
11684 /* Send CHAN ACT NACK, so that the requested TCH channel becomes BORKEN */
11685 f_ipa_tx(ts_RSL_CHAN_ACT_NACK(rsl_chan_act.ies[0].body.chan_nr, RSL_ERR_EQUIPMENT_FAIL), idx);
11686 /* Expect to receive an Assignment Failure */
11687 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail));
11688}
11689
11690testcase TC_chan_alloc_algo_ascending() runs on test_CT {
11691 /* We need to access BTS2, which has 4 TRXs */
11692 f_init(nr_bts := 3);
11693
11694 /* HACK: work around "Couldn't find Expect for CRCX" */
11695 vc_MGCP.stop;
11696
11697 f_vty_enter_cfg_bts(BSCVTY, 2);
11698 f_vty_transceive(BSCVTY, "channel allocator ascending");
11699 f_vty_transceive(BSCVTY, "end");
11700
11701 /* Expect the BSC to allocate 4 x TCH/F channels on BTS2/TRX0 */
11702 for (var integer i := 0; i < 4; i := i + 1) {
11703 var DchanTuple dt := f_est_dchan('23'O, 23, '00000000'O, {2, 0});
11704 f_TC_chan_alloc_algo(dt, {2, 0});
11705 f_perform_clear_test_ct(dt);
11706 }
11707
11708 /* At this point all 4 x TCH/F channels are BORKEN, but they will be
11709 * resurrected upon the A-bis/OML link re-establishment. */
11710 f_shutdown_helper();
11711}
11712
11713testcase TC_chan_alloc_algo_descending() runs on test_CT {
11714 /* We need to access BTS2, which has 4 TRXs */
11715 f_init(nr_bts := 3);
11716
11717 /* HACK: work around "Couldn't find Expect for CRCX" */
11718 vc_MGCP.stop;
11719
11720 f_vty_enter_cfg_bts(BSCVTY, 2);
11721 f_vty_transceive(BSCVTY, "channel allocator descending");
11722 f_vty_transceive(BSCVTY, "end");
11723
11724 /* Expect the BSC to allocate 5 x TCH/F channels on BTS2/TRX3 */
11725 for (var integer i := 0; i < 5; i := i + 1) {
11726 var DchanTuple dt := f_est_dchan('23'O, 23, '00000000'O, {2, 0});
11727 f_TC_chan_alloc_algo(dt, {2, 3});
11728 f_perform_clear_test_ct(dt);
11729 }
11730
11731 /* At this point all 5 x TCH/F channels are BORKEN, but they will be
11732 * resurrected upon the A-bis/OML link re-establishment. */
11733 f_shutdown_helper();
11734}
11735
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011736testcase TC_chan_alloc_algo_ass_dynamic() runs on test_CT {
11737 const BtsTrxIdx TRX0 := {2, 0};
11738 const BtsTrxIdx TRX3 := {2, 3};
11739
11740 /* We need to access BTS2, which has 4 TRXs */
11741 f_init(nr_bts := 3);
11742
11743 /* HACK: work around "Couldn't find Expect for CRCX" */
11744 vc_MGCP.stop;
11745
11746 f_vty_enter_cfg_bts(BSCVTY, 2);
11747 f_vty_transceive(BSCVTY, "channel allocator mode assignment dynamic");
11748 f_vty_transceive(BSCVTY, "channel allocator dynamic-param ul-rxlev thresh 50 avg-num 2");
11749 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 0");
11750 f_vty_transceive(BSCVTY, "end");
11751
11752 var DchanTuple dt;
11753
11754 f_logp(BSCVTY, "Case a) Unknown Uplink RxLev, fall-back to ascending");
11755 dt := f_est_dchan('23'O, 23, '00000000'O, TRX0);
11756 f_TC_chan_alloc_algo(dt, TRX0);
11757 f_perform_clear_test_ct(dt);
11758
11759 f_logp(BSCVTY, "Case b) Not enough RxLev samples, use ascending");
11760 dt := f_est_dchan('23'O, 23, '00000000'O, TRX0);
11761 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11762 ts_RSL_IE_UplinkMeas(30, 0),
11763 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011764 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011765 f_TC_chan_alloc_algo(dt, TRX0);
11766 f_perform_clear_test_ct(dt);
11767
11768 f_logp(BSCVTY, "Case c) Uplink RxLev below the threshold, use ascending");
11769 dt := f_est_dchan('23'O, 23, '00000000'O, TRX0);
11770 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11771 ts_RSL_IE_UplinkMeas(45, 0),
11772 ts_RSL_IE_BS_Power(0)), TRX0);
11773 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
11774 ts_RSL_IE_UplinkMeas(48, 0),
11775 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011776 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011777 f_TC_chan_alloc_algo(dt, TRX0);
11778 f_perform_clear_test_ct(dt);
11779
11780 f_logp(BSCVTY, "Case d) Uplink RxLev above the threshold, use descending");
11781 dt := f_est_dchan('23'O, 23, '00000000'O, TRX0);
11782 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11783 ts_RSL_IE_UplinkMeas(50, 0),
11784 ts_RSL_IE_BS_Power(0)), TRX0);
11785 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
11786 ts_RSL_IE_UplinkMeas(58, 0),
11787 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011788 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011789 f_TC_chan_alloc_algo(dt, TRX3);
11790 f_perform_clear_test_ct(dt);
11791
11792 f_vty_enter_cfg_bts(BSCVTY, 2);
11793 f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 90");
11794 f_vty_transceive(BSCVTY, "end");
11795
11796 f_logp(BSCVTY, "Case e) Uplink RxLev above the threshold, but C0 load is not");
11797 dt := f_est_dchan('23'O, 23, '00000000'O, TRX0);
11798 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
11799 ts_RSL_IE_UplinkMeas(50, 0),
11800 ts_RSL_IE_BS_Power(0)), TRX0);
11801 f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
11802 ts_RSL_IE_UplinkMeas(58, 0),
11803 ts_RSL_IE_BS_Power(0)), TRX0);
Vadim Yanitskiy5f6dd352022-08-24 03:08:32 +070011804 f_sleep(0.3); /* give the IUT some time to process sent MRs */
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070011805 f_TC_chan_alloc_algo(dt, TRX0);
11806 f_perform_clear_test_ct(dt);
11807
11808 f_vty_enter_cfg_bts(BSCVTY, 2);
11809 f_vty_transceive(BSCVTY, "channel allocator ascending");
11810 f_vty_transceive(BSCVTY, "end");
11811
11812 /* At this point some TCH/F channels are BORKEN, but they will be
11813 * resurrected upon the A-bis/OML link re-establishment. */
11814 f_shutdown_helper();
11815}
11816
Harald Welte28d943e2017-11-25 15:00:50 +010011817control {
Harald Welte898113b2018-01-31 18:32:21 +010011818 /* CTRL interface testing */
Harald Welte4003d112017-12-09 22:35:39 +010011819 execute( TC_ctrl_msc_connection_status() );
Stefan Sperlingb041b3d2018-01-03 17:14:55 +010011820 execute( TC_ctrl_msc0_connection_status() );
Neels Hofmeyrf65ce872021-09-23 18:40:10 +020011821 /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
11822 * these in the AoIP test suite. */
11823 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
11824 execute( TC_stat_num_msc_connected_1() );
11825 execute( TC_stat_num_msc_connected_2() );
11826 execute( TC_stat_num_msc_connected_3() );
11827 }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020011828 execute( TC_stat_num_bts_connected_1() );
11829 execute( TC_stat_num_bts_connected_2() );
11830 execute( TC_stat_num_bts_connected_3() );
Harald Welte96c94412017-12-09 03:12:45 +010011831 execute( TC_ctrl() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020011832 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +020011833 execute( TC_ctrl_location() );
11834 }
Harald Welte898113b2018-01-31 18:32:21 +010011835
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020011836 execute( TC_si_default() );
Neels Hofmeyr66aeba42020-07-06 02:21:21 +020011837 execute( TC_si2quater_2_earfcns() );
11838 execute( TC_si2quater_3_earfcns() );
11839 execute( TC_si2quater_4_earfcns() );
11840 execute( TC_si2quater_5_earfcns() );
11841 execute( TC_si2quater_6_earfcns() );
Neels Hofmeyrad132f22020-07-08 02:20:16 +020011842 execute( TC_si2quater_12_earfcns() );
11843 execute( TC_si2quater_23_earfcns() );
11844 execute( TC_si2quater_32_earfcns() );
11845 execute( TC_si2quater_33_earfcns() );
11846 execute( TC_si2quater_42_earfcns() );
11847 execute( TC_si2quater_48_earfcns() );
11848 execute( TC_si2quater_49_earfcns() );
Pau Espin Pedrol85a84432020-07-20 18:45:03 +020011849 execute( TC_si_acc_rotate() );
Alexander Couzens4ad3a352020-09-10 22:29:12 +020011850 execute( TC_si_acc_ramp_rotate() );
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020011851
Harald Welte898113b2018-01-31 18:32:21 +010011852 /* RSL DCHAN Channel ACtivation / Deactivation */
Harald Welteae026692017-12-09 01:03:01 +010011853 execute( TC_chan_act_noreply() );
Harald Welte4003d112017-12-09 22:35:39 +010011854 execute( TC_chan_act_counter() );
Harald Welteae026692017-12-09 01:03:01 +010011855 execute( TC_chan_act_ack_noest() );
Philipp Maier9c60a622020-07-09 15:08:46 +020011856 execute( TC_chan_act_ack_noest_emerg() );
Philipp Maier606f07d2020-08-12 17:21:58 +020011857 execute( TC_chan_rqd_emerg_deny() );
Harald Welteae026692017-12-09 01:03:01 +010011858 execute( TC_chan_act_ack_est_ind_noreply() );
11859 execute( TC_chan_act_ack_est_ind_refused() );
Harald Welte618ef642017-12-14 14:58:20 +010011860 execute( TC_chan_act_nack() );
Harald Welte799c97b2017-12-14 17:50:30 +010011861 execute( TC_chan_exhaustion() );
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +070011862 execute( TC_chan_deact_silence() );
Harald Welte4003d112017-12-09 22:35:39 +010011863 execute( TC_chan_rel_rll_rel_ind() );
11864 execute( TC_chan_rel_conn_fail() );
11865 execute( TC_chan_rel_hard_clear() );
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +020011866 execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
11867 execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
Harald Welte99787102019-02-04 10:41:36 +010011868 execute( TC_chan_rel_hard_clear_csfb() );
Harald Welted8c36cd2017-12-09 23:05:31 +010011869 execute( TC_chan_rel_hard_rlsd() );
Harald Welte550daf92018-06-11 19:22:13 +020011870 execute( TC_chan_rel_hard_rlsd_ms_dead() );
Harald Welte85804d42017-12-10 14:11:58 +010011871 execute( TC_chan_rel_a_reset() );
Pau Espin Pedrolc675b612020-01-09 19:55:40 +010011872 execute( TC_chan_rel_sccp_tiar_timeout() );
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +020011873 execute( TC_chan_rel_rr_cause() );
Harald Welte6f521d82017-12-11 19:52:02 +010011874
Harald Weltecfe2c962017-12-15 12:09:32 +010011875 execute( TC_outbound_connect() );
Harald Welte898113b2018-01-31 18:32:21 +010011876
11877 /* Assignment related */
Harald Welte16a4adf2017-12-14 18:54:01 +010011878 execute( TC_assignment_cic_only() );
Harald Welte235ebf12017-12-15 14:18:16 +010011879 execute( TC_assignment_csd() );
11880 execute( TC_assignment_ctm() );
11881 execute( TC_assignment_sign() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020011882 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
11883 execute( TC_assignment_aoip_tla_v6() );
11884 }
Harald Welte235ebf12017-12-15 14:18:16 +010011885 execute( TC_assignment_fr_a5_0() );
11886 execute( TC_assignment_fr_a5_1() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020011887 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte8f67d1d2018-05-25 20:38:42 +020011888 execute( TC_assignment_fr_a5_1_codec_missing() );
11889 }
Harald Welte235ebf12017-12-15 14:18:16 +010011890 execute( TC_assignment_fr_a5_3() );
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +020011891 execute( TC_assignment_fr_a5_4() );
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +020011892 execute( TC_assignment_fr_a5_4_fail() );
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +020011893 execute( TC_assignment_fr_a5_not_sup() );
Harald Welte3c86ea02018-05-10 22:28:05 +020011894 execute( TC_ciph_mode_a5_0() );
11895 execute( TC_ciph_mode_a5_1() );
Oliver Smith50b98122021-07-09 15:00:28 +020011896 execute( TC_ciph_mode_a5_2_0() );
Oliver Smith1dff88d2021-07-09 08:45:51 +020011897 execute( TC_ciph_mode_a5_2_1() );
Harald Welte3c86ea02018-05-10 22:28:05 +020011898 execute( TC_ciph_mode_a5_3() );
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +020011899 execute( TC_ciph_mode_a5_4() );
Harald Welte16a4adf2017-12-14 18:54:01 +010011900
Harald Welte60aa5762018-03-21 19:33:13 +010011901 execute( TC_assignment_codec_fr() );
Neels Hofmeyr559d5d02021-04-16 16:50:49 +020011902 execute( TC_assignment_codec_fr_by_mode_modify() );
Harald Welte60aa5762018-03-21 19:33:13 +010011903 execute( TC_assignment_codec_hr() );
11904 execute( TC_assignment_codec_efr() );
11905 execute( TC_assignment_codec_amr_f() );
11906 execute( TC_assignment_codec_amr_h() );
Philipp Maier8a581d22019-03-26 18:32:48 +010011907
Neels Hofmeyrf246a922020-05-13 02:27:10 +020011908 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier8a581d22019-03-26 18:32:48 +010011909 execute( TC_assignment_codec_amr_f_S1() );
11910 execute( TC_assignment_codec_amr_h_S1() );
11911 execute( TC_assignment_codec_amr_f_S124() );
11912 execute( TC_assignment_codec_amr_h_S124() );
11913 execute( TC_assignment_codec_amr_f_S0() );
11914 execute( TC_assignment_codec_amr_f_S02() );
11915 execute( TC_assignment_codec_amr_f_S024() );
11916 execute( TC_assignment_codec_amr_f_S0247() );
11917 execute( TC_assignment_codec_amr_h_S0() );
11918 execute( TC_assignment_codec_amr_h_S02() );
11919 execute( TC_assignment_codec_amr_h_S024() );
11920 execute( TC_assignment_codec_amr_h_S0247() );
11921 execute( TC_assignment_codec_amr_f_S01234567() );
11922 execute( TC_assignment_codec_amr_f_S0234567() );
11923 execute( TC_assignment_codec_amr_f_zero() );
11924 execute( TC_assignment_codec_amr_f_unsupp() );
11925 execute( TC_assignment_codec_amr_h_S7() );
Neels Hofmeyr21863562020-11-26 00:34:33 +000011926 execute( TC_assignment_codec_amr_f_start_mode_auto() );
11927 execute( TC_assignment_codec_amr_h_start_mode_auto() );
Neels Hofmeyr3eb94562020-11-26 02:40:26 +000011928 execute( TC_assignment_codec_amr_f_start_mode_4() );
11929 execute( TC_assignment_codec_amr_h_start_mode_4() );
Neels Hofmeyr454d7922020-11-26 02:24:57 +000011930 execute( TC_assignment_codec_amr_startmode_cruft() );
Philipp Maier8a581d22019-03-26 18:32:48 +010011931 }
Harald Welte60aa5762018-03-21 19:33:13 +010011932
Philipp Maierac09bfc2019-01-08 13:41:39 +010011933 execute( TC_assignment_codec_fr_exhausted_req_hr() );
11934 execute( TC_assignment_codec_fr_exhausted_req_fr() );
11935 execute( TC_assignment_codec_fr_exhausted_req_fr_hr() );
11936 execute( TC_assignment_codec_fr_exhausted_req_hr_fr() );
11937 execute( TC_assignment_codec_hr_exhausted_req_fr() );
11938 execute( TC_assignment_codec_hr_exhausted_req_hr() );
11939 execute( TC_assignment_codec_hr_exhausted_req_hr_fr() );
11940 execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
11941 execute( TC_assignment_codec_req_hr_fr() );
11942 execute( TC_assignment_codec_req_fr_hr() );
Pau Espin Pedrol14475352021-07-22 15:48:16 +020011943 execute( TC_assignment_sdcch_exhausted_req_signalling() );
11944 execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
11945 execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
Philipp Maierac09bfc2019-01-08 13:41:39 +010011946
Pau Espin Pedrolcd6077f2022-09-19 20:23:37 +020011947 execute( TC_assignment_codec_hr_osmux_on() );
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +020011948 execute( TC_assignment_osmux() );
Pau Espin Pedrol29c6dfb2022-08-08 18:37:56 +020011949 execute( TC_assignment_osmux_cn() );
11950 execute( TC_assignment_osmux_bts() );
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +020011951
Harald Welte898113b2018-01-31 18:32:21 +010011952 /* RLL Establish Indication on inactive DCHAN / SAPI */
Harald Welte5cd20ed2017-12-13 21:03:20 +010011953 execute( TC_rll_est_ind_inact_lchan() );
11954 execute( TC_rll_est_ind_inval_sapi1() );
11955 execute( TC_rll_est_ind_inval_sapi3() );
11956 execute( TC_rll_est_ind_inval_sacch() );
11957
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +070011958 /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
11959 execute( TC_tch_dlci_link_id_sapi() );
11960
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070011961 /* SAPI N Reject triggered by RLL establishment failures */
11962 execute( TC_rll_rel_ind_sapi_n_reject() );
11963 execute( TC_rll_err_ind_sapi_n_reject() );
11964 execute( TC_rll_timeout_sapi_n_reject() );
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +070011965 execute( TC_rll_sapi_n_reject_dlci_cc() );
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070011966
Harald Welte898113b2018-01-31 18:32:21 +010011967 /* Paging related tests */
Harald Welte6f521d82017-12-11 19:52:02 +010011968 execute( TC_paging_imsi_nochan() );
11969 execute( TC_paging_tmsi_nochan() );
11970 execute( TC_paging_tmsi_any() );
11971 execute( TC_paging_tmsi_sdcch() );
11972 execute( TC_paging_tmsi_tch_f() );
11973 execute( TC_paging_tmsi_tch_hf() );
11974 execute( TC_paging_imsi_nochan_cgi() );
11975 execute( TC_paging_imsi_nochan_lac_ci() );
11976 execute( TC_paging_imsi_nochan_ci() );
11977 execute( TC_paging_imsi_nochan_lai() );
11978 execute( TC_paging_imsi_nochan_lac() );
11979 execute( TC_paging_imsi_nochan_all() );
Harald Welte751d3eb2018-01-31 15:51:06 +010011980 execute( TC_paging_imsi_nochan_plmn_lac_rnc() );
11981 execute( TC_paging_imsi_nochan_rnc() );
11982 execute( TC_paging_imsi_nochan_lac_rnc() );
11983 execute( TC_paging_imsi_nochan_lacs() );
11984 execute( TC_paging_imsi_nochan_lacs_empty() );
Stefan Sperling049a86e2018-03-20 15:51:00 +010011985 execute( TC_paging_imsi_nochan_cgi_unknown_cid() );
Harald Welte10985002017-12-12 09:29:15 +010011986 execute( TC_paging_imsi_a_reset() );
Harald Weltee65d40e2017-12-13 00:09:06 +010011987 execute( TC_paging_imsi_load() );
Philipp Maier779a7922018-02-16 11:00:37 +010011988 execute( TC_paging_counter() );
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +010011989 execute( TC_paging_resp_unsol() );
Pau Espin Pedrol09b9bad2022-04-21 18:48:08 +020011990 execute( TC_paging_500req() );
Pau Espin Pedrol189bf1b2022-04-27 12:42:13 +020011991 execute( TC_paging_450req_no_paging_load_ind() );
Harald Welte4e9b9cc2017-12-14 18:31:02 +010011992
11993 execute( TC_rsl_drop_counter() );
Stefan Sperling830dc9d2018-02-12 21:08:28 +010011994 execute( TC_rsl_unknown_unit_id() );
11995
11996 execute( TC_oml_unknown_unit_id() );
Harald Welte898113b2018-01-31 18:32:21 +010011997
11998 execute( TC_classmark() );
Harald Welteeddf0e92020-06-21 19:42:15 +020011999 execute( TC_common_id() );
Harald Welte898113b2018-01-31 18:32:21 +010012000 execute( TC_unsol_ass_fail() );
Harald Welteea99a002018-01-31 20:46:43 +010012001 execute( TC_unsol_ass_compl() );
Harald Weltefbf9b5e2018-01-31 20:41:23 +010012002 execute( TC_unsol_ho_fail() );
Harald Weltee3bd6582018-01-31 22:51:25 +010012003 execute( TC_err_82_short_msg() );
Harald Weltee9e02e42018-01-31 23:36:25 +010012004 execute( TC_err_84_unknown_msg() );
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012005
Harald Welte261af4b2018-02-12 21:20:39 +010012006 execute( TC_ho_int() );
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +020012007 execute( TC_ho_int_a5_0() );
12008 execute( TC_ho_int_a5_1() );
12009 execute( TC_ho_int_a5_3() );
12010 execute( TC_ho_int_a5_4() );
Neels Hofmeyr5f144212020-11-03 15:41:58 +000012011 execute( TC_ho_int_radio_link_failure() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012012
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012013 /* TC_ho_out_of_this_bsc is run last, see comment below */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +020012014 execute( TC_ho_out_fail_no_msc_response() );
12015 execute( TC_ho_out_fail_rr_ho_failure() );
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +020012016 execute( TC_ho_out_fail_no_result_after_ho_cmd() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012017
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010012018 execute( TC_ho_into_this_bsc() );
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +020012019 execute( TC_ho_into_this_bsc_a5_0() );
12020 execute( TC_ho_into_this_bsc_a5_1() );
12021 execute( TC_ho_into_this_bsc_a5_3() );
12022 execute( TC_ho_into_this_bsc_a5_4() );
Neels Hofmeyr93182e02022-02-17 21:59:07 +010012023 execute( TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() );
12024 execute( TC_ho_into_this_bsc_a5_1_3() );
Neels Hofmeyr907b23b2022-02-17 21:58:47 +010012025 execute( TC_ho_into_this_bsc_a5_mismatch() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020012026 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12027 execute( TC_ho_into_this_bsc_tla_v6() );
12028 }
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +020012029 execute( TC_srvcc_eutran_to_geran() );
Vadim Yanitskiy634f75d2022-03-14 17:04:45 +030012030 execute( TC_srvcc_eutran_to_geran_a5_3() );
Pau Espin Pedrola8ef3be2022-02-16 16:21:17 +010012031 execute( TC_srvcc_eutran_to_geran_src_sai() );
Pau Espin Pedrol35801c32021-04-19 13:03:20 +020012032 execute( TC_srvcc_eutran_to_geran_ho_out() );
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +020012033 execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
12034 execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010012035 execute( TC_ho_in_fail_msc_clears() );
12036 execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
12037 execute( TC_ho_in_fail_no_detect() );
12038 execute( TC_ho_in_fail_no_detect2() );
Neels Hofmeyra23f3b12022-03-02 19:57:12 +010012039 execute( TC_ho_into_this_bsc_sccp_cr_without_bssap() );
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012040
Neels Hofmeyr91401012019-07-11 00:42:35 +020012041 execute( TC_ho_neighbor_config_1() );
12042 execute( TC_ho_neighbor_config_2() );
12043 execute( TC_ho_neighbor_config_3() );
12044 execute( TC_ho_neighbor_config_4() );
12045 execute( TC_ho_neighbor_config_5() );
12046 execute( TC_ho_neighbor_config_6() );
12047 execute( TC_ho_neighbor_config_7() );
12048
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010012049 execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() );
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010012050 execute( TC_bssmap_clear_does_not_cause_bssmap_reset() );
Neels Hofmeyrfd445c32018-03-09 15:39:31 +010012051 execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() );
Harald Welte94e0c342018-04-07 11:33:23 +020012052
12053 execute( TC_dyn_pdch_ipa_act_deact() );
12054 execute( TC_dyn_pdch_ipa_act_nack() );
12055 execute( TC_dyn_pdch_osmo_act_deact() );
12056 execute( TC_dyn_pdch_osmo_act_nack() );
Pau Espin Pedrol37a4c152021-11-16 19:02:23 +010012057 execute( TC_dyn_ts_sdcch8_act_deact() );
12058 execute( TC_dyn_ts_sdcch8_all_subslots_used() );
12059 execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
12060 execute( TC_dyn_ts_sdcch8_act_nack() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012061
Stefan Sperling0796a822018-10-05 13:01:39 +020012062 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +020012063 execute( TC_chopped_ipa_payload() );
Stefan Sperling0796a822018-10-05 13:01:39 +020012064
Pau Espin Pedrol8f773632019-11-05 11:46:53 +010012065 /* Power control related */
12066 execute( TC_assignment_verify_ms_power_params_ie() );
Vadim Yanitskiy4b233042021-06-30 00:58:43 +020012067 execute( TC_c0_power_red_mode() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020012068
12069 /* MSC pooling */
12070 /* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
12071 * RESET->RESET-ACK is unconditionally negotiated for all configured MSCs, they always all appear as connected
12072 * to osmo-bsc. The MSC pooling tests however require disconnecting selected MSCs, and hence don't work out as
12073 * intended on SCCPlite. So for now, run these only for SCCP/M3UA. */
12074 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
12075 execute( TC_mscpool_L3Compl_on_1_msc() );
12076 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
12077 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
12078 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
12079 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
12080 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
12081 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
12082 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
12083 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
12084 execute( TC_mscpool_paging_and_response_imsi() );
12085 execute( TC_mscpool_paging_and_response_tmsi() );
12086 execute( TC_mscpool_no_allow_attach_round_robin() );
12087 execute( TC_mscpool_no_allow_attach_valid_nri() );
12088 }
12089
Harald Welte99f3ca02018-06-14 13:40:29 +020012090 execute( TC_early_conn_fail() );
12091 execute( TC_late_conn_fail() );
Oliver Smithaf03bef2021-08-24 15:34:51 +020012092 execute( TC_stats_conn_fail() );
Harald Welte99f3ca02018-06-14 13:40:29 +020012093
Philipp Maier783681c2020-07-16 16:47:06 +020012094 /* Emergency call handling (deny / allow) */
12095 execute( TC_assignment_emerg_setup_allow() );
12096 execute( TC_assignment_emerg_setup_deny_msc() );
12097 execute( TC_assignment_emerg_setup_deny_bts() );
Philipp Maier82812002020-08-13 18:48:27 +020012098 execute( TC_emerg_premption() );
12099
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +070012100 /* Frequency hopping parameters handling */
12101 execute( TC_fh_params_chan_activ() );
12102 execute( TC_fh_params_imm_ass() );
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070012103 execute( TC_fh_params_assignment_cmd() );
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070012104 execute( TC_fh_params_handover_cmd() );
Vadim Yanitskiyca974032020-09-01 07:20:39 +070012105 execute( TC_fh_params_si4_cbch() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012106
12107 if (mp_enable_lcs_tests) {
12108 execute( TC_lcs_loc_req_for_active_ms() );
12109 execute( TC_lcs_loc_req_for_active_ms_ta_req() );
12110 execute( TC_lcs_loc_req_for_idle_ms() );
12111 execute( TC_lcs_loc_req_no_subscriber() );
12112 execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
12113 execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
12114 execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
12115 execute( TC_cm_service_during_lcs_loc_req() );
12116 execute( TC_ho_during_lcs_loc_req() );
Neels Hofmeyra47a8c62022-04-07 00:31:19 +020012117 execute( TC_emerg_call_and_lcs_loc_req() );
Neels Hofmeyr61f9dc52022-05-12 23:04:40 +020012118 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() );
12119 execute( TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020012120 }
Neels Hofmeyrbf037052020-10-28 22:52:02 +000012121
12122 execute( TC_no_msc() );
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000012123
12124 execute( TC_refuse_chan_act_to_vamos() );
12125 execute( TC_refuse_mode_modif_to_vamos() );
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000012126
12127 execute( TC_reassignment_fr() );
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020012128
12129 execute( TC_cm_reestablishment() );
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020012130
12131 execute( TC_imm_ass_post_chan_ack() );
12132 execute( TC_imm_ass_pre_chan_ack() );
Neels Hofmeyr23158742021-09-07 19:08:07 +020012133 execute( TC_imm_ass_pre_ts_ack() );
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020012134 execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020012135 execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020012136
12137 execute( TC_ctrl_trx_rf_locked() );
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012138
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020012139 execute( TC_ratectr_all_available_allocated() );
12140 execute( TC_ratectr_all_available_allocated_dyn() );
12141
Neels Hofmeyrb7581872021-11-07 14:02:49 +010012142 execute( TC_cm_serv_rej() );
12143
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020012144 execute( TC_lost_sdcch_during_assignment() );
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012145
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012146 /* Channel allocator */
12147 execute( TC_chan_alloc_algo_ascending() );
12148 execute( TC_chan_alloc_algo_descending() );
Vadim Yanitskiy7c29c4e2022-06-18 03:07:50 +070012149 execute( TC_chan_alloc_algo_ass_dynamic() );
Vadim Yanitskiy1a16d312022-05-31 16:14:01 +060012150
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010012151 /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
12152 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
12153 execute( TC_ho_out_of_this_bsc() );
Harald Welte28d943e2017-11-25 15:00:50 +010012154}
12155
12156}